Conjunto de herramientas read/bash/edit/write/grep/find/ls
El directorio tools/ es el conjunto de herramientas integradas de pi. Cada herramienta es una estructura de dos capas, ToolDefinition (con schema, descripción, prompt snippet, guidelines) y AgentTool (función de ejecución), unidas vía wrapToolDefinition. index.ts re-exporta todas las fábricas y ofrece tres combinaciones predefinidas: createCodingTools / createReadOnlyTools / createAllTools. Las herramientas de escritura (edit, write) pasan por withFileMutationQueue para serializar y evitar carreras al modificar el mismo archivo concurrentemente.
Responsabilidades
- read: lee archivos de texto/imagen; las imágenes soportan resize automático (
autoResizeImages); el texto se trunca porDEFAULT_MAX_LINES/DEFAULT_MAX_BYTES. Verpackages/coding-agent/src/core/tools/read.ts:205-236. - bash: ejecuta comandos de shell, rastrea procesos detached hijos, ofrece abort y timeout. Ver
packages/coding-agent/src/core/tools/bash.ts:264-280. - edit / write: edición y creación de archivos; ambos pasan por
withFileMutationQueue. Verpackages/coding-agent/src/core/tools/edit.ts:288-316ypackages/coding-agent/src/core/tools/write.ts:181-210. - grep / find / ls: búsqueda y listado de archivos basados en
fdyrg, respetando.gitignore. Verpackages/coding-agent/src/core/tools/grep.ts:122-135,packages/coding-agent/src/core/tools/find.ts:112-125,packages/coding-agent/src/core/tools/ls.ts:99-112. - Fábricas de combinación:
createToolDefinition/createTooldispatchan porToolName;createCodingToolspor defecto da 4 piezas (read/bash/edit/write),createReadOnlyToolsda 4 piezas (read/grep/find/ls). Verpackages/coding-agent/src/core/tools/index.ts:96-136ypackages/coding-agent/src/core/tools/index.ts:138-184. - Serialización de escrituras:
withFileMutationQueuemantiene una cadena de Promises por realpath del archivo; las escrituras del mismo archivo se encolan en orden de invocación; archivos distintos se paralelizan. Verpackages/coding-agent/src/core/tools/file-mutation-queue.ts:19-39.
Motivación de diseño
¿Por qué herramientas en dos capas? ToolDefinition es para el LLM: schema, description, prompt snippet, guidelines, todo eso se inyecta en el system prompt. AgentTool es el cuerpo de ejecución y sólo le importa al runtime. Separarlas permite que la misma definición impulse varios cuerpos: por ejemplo, la definición de read puede tener en modo RPC una implementación distinta de operations (los unit tests de read pueden inyectar un fs mock).
¿Por qué serializar escrituras? El LLM puede invocar edit/write varias veces al mismo archivo en un turno concurrente; sin serializar, el último en escribir sobrescribe los anteriores y el contenido se corrompe. withFileMutationQueue usa realpathSync.native como key para que symlinks y rutas reales compartan la misma cola. Archivos distintos siguen en paralelo, sin perder throughput.
¿Por qué read incluye por defecto promptGuidelines: ["Use read to examine files instead of cat or sed."]? Porque al construir el system prompt se pegan los guidelines de cada tool, y el LLM al ver "prefiere read sobre bash con cat" evita caminos ineficientes.
Archivos clave
packages/coding-agent/src/core/tools/— Directorio de herramientas: bash.ts / edit.ts / find.ts / grep.ts / ls.ts / read.ts / write.ts / truncate.ts / file-mutation-queue.ts.packages/coding-agent/src/core/tools/index.ts:1-69— Re-export de todos loscreate*Tool/create*ToolDefinition.packages/coding-agent/src/core/tools/index.ts:81-115— TipoToolNamey dispatch decreateToolDefinition.packages/coding-agent/src/core/tools/index.ts:138-196— Tres combinaciones:createCodingTools/createReadOnlyTools/createAllTools.packages/coding-agent/src/core/tools/file-mutation-queue.ts:4-13— MapfileMutationQueuesygetMutationQueueKey, resolución realpath.packages/coding-agent/src/core/tools/file-mutation-queue.ts:19-39—withFileMutationQueue, cola vía cadena de Promises.packages/coding-agent/src/core/tools/read.ts:205-236—createReadToolDefinition, detección de imágenes, resize, gestión de abort signal.packages/coding-agent/src/core/tools/read.ts:360-362—createReadTool, envolturawrapToolDefinition.
La implementación de withFileMutationQueue es una cadena de promises; cada invocación nueva se cuelga del .then del promise anterior:
// packages/coding-agent/src/core/tools/file-mutation-queue.ts:19-39
export async function withFileMutationQueue<T>(filePath: string, fn: () => Promise<T>): Promise<T> {
const key = getMutationQueueKey(filePath);
const currentQueue = fileMutationQueues.get(key) ?? Promise.resolve();
let releaseNext!: () => void;
const nextQueue = new Promise<void>((resolveQueue) => {
releaseNext = resolveQueue;
});
const chainedQueue = currentQueue.then(() => nextQueue);
fileMutationQueues.set(key, chainedQueue);
await currentQueue;
try {
return await fn();
} finally {
releaseNext();
if (fileMutationQueues.get(key) === chainedQueue) {
fileMutationQueues.delete(key);
}
}
}El execute de read acepta signal: AbortSignal y rechaza inmediatamente al Ctrl+C del usuario:
// packages/coding-agent/src/core/tools/read.ts:225-237
const absolutePath = resolveReadPath(path, cwd);
return new Promise<{ content: (TextContent | ImageContent)[]; details: ReadToolDetails | undefined }>(
(resolve, reject) => {
if (signal?.aborted) {
reject(new Error("Operation aborted"));
return;
}
let aborted = false;
const onAbort = () => {
aborted = true;
reject(new Error("Operation aborted"));
};
signal?.addEventListener("abort", onAbort, { once: true });Flujo de datos
Selección y ejecución de herramientas:
Límites y fallos
- Abort signal: read rechaza enseguida si
signal.aborted, y las tareas async comprueban el flagaborted, evitando race conditions. Verpackages/coding-agent/src/core/tools/read.ts:228-237. - Fallo de realpath:
getMutationQueueKeycae aresolve(filePath)sirealpathSync.nativelanza, garantizando que se pueda encolar incluso para archivos ya borrados. Verpackages/coding-agent/src/core/tools/file-mutation-queue.ts:6-13. - Resize de imagen fallido: si
resizeddevuelve null, se sustituye por un placeholder de texto "Image omitted: could not be resized below the inline image size limit", sin error directo. Verpackages/coding-agent/src/core/tools/read.ts:255-258. - Modelos no visuales: read comprueba si
ctx?.modelsoporta visión; si no, añade un textogetNonVisionImageNotepara que el LLM sepa que la imagen realmente no es visible. - Nombre de herramienta desconocido: el switch default de
createToolDefinitionlanzaUnknown tool name, sin devolver undefined silenciosamente. Verpackages/coding-agent/src/core/tools/index.ts:112-114.
Resumen
tools/ es la caja de herramientas integrada de pi, estructura de dos capas (ToolDefinition para el LLM, AgentTool para el runtime); las herramientas de escritura se serializan con withFileMutationQueue para evitar carreras concurrentes. Las tres combinaciones predefinidas cubren codificación, sólo lectura y conjunto completo. Cómo se ensamblan estas herramientas en la sesión en ensamblaje createAgentSession; los hooks en capa de orquestación AgentSession.