Ir al contenido

Aspectos internos del tiempo de ejecución de la herramienta Resolve

Este documento explica cómo se modelan los flujos de trabajo de vista previa/aplicación en el agente de codificación y cómo las herramientas personalizadas pueden participar mediante pushPendingAction.

resolve es una herramienta oculta que finaliza una acción de vista previa pendiente.

  • action: "apply" ejecuta apply(reason) sobre la acción pendiente y persiste los cambios.
  • action: "discard" invoca reject(reason) si se proporciona; de lo contrario, descarta la acción con un mensaje predeterminado “Discarded”.

Si no existe ninguna acción pendiente, resolve falla con:

  • No pending action to resolve. Nothing to apply or discard.

Las acciones pendientes forman una pila (LIFO)

Sección titulada «Las acciones pendientes forman una pila (LIFO)»

Las acciones pendientes se almacenan en PendingActionStore como una pila de tipo push/pop:

  • push(action) añade una nueva acción pendiente en la cima.
  • peek() inspecciona la acción actual en la cima.
  • pop() elimina y devuelve la acción en la cima.
  • hasPending indica si la pila no está vacía.

resolve siempre consume la acción pendiente más reciente primero (pop()), por lo que las herramientas que producen múltiples vistas previas se resuelven en orden inverso al de su registro.

ast_edit previsualiza primero los reemplazos estructurales. Cuando la vista previa tiene reemplazos y aún no se ha aplicado, agrega una acción pendiente que contiene:

  • etiqueta (resumen legible por humanos)
  • sourceToolName (ast_edit)
  • callback apply(reason: string) que vuelve a ejecutar la edición AST con dryRun: false

resolve(action="apply", reason="...") pasa reason a este callback.

Herramientas personalizadas: pushPendingAction

Sección titulada «Herramientas personalizadas: pushPendingAction»

Las herramientas personalizadas pueden registrar acciones pendientes compatibles con resolve mediante CustomToolAPI.pushPendingAction(...).

CustomToolPendingAction:

  • label: string (obligatorio)
  • apply(reason: string): Promise<AgentToolResult<unknown>> (obligatorio) — se invoca al aplicar; reason es la cadena pasada a resolve
  • reject?(reason: string): Promise<AgentToolResult<unknown> | undefined> (opcional) — se invoca al descartar; el valor de retorno reemplaza el mensaje predeterminado “Discarded” si se proporciona
  • details?: unknown (opcional)
  • sourceToolName?: string (opcional, por defecto "custom_tool")
import type { CustomToolFactory } from "@f5-sales-demo/xcsh";
const factory: CustomToolFactory = pi => ({
name: "batch_rename_preview",
label: "Batch Rename Preview",
description: "Previews renames and defers commit to resolve",
parameters: pi.typebox.Type.Object({
files: pi.typebox.Type.Array(pi.typebox.Type.String()),
}),
async execute(_toolCallId, params) {
const previewSummary = `Prepared rename plan for ${params.files.length} files`;
pi.pushPendingAction({
label: `Batch rename: ${params.files.length} files`,
sourceToolName: "batch_rename_preview",
apply: async (reason) => {
// apply writes here
return {
content: [{ type: "text", text: `Applied batch rename. Reason: ${reason}` }],
};
},
reject: async (reason) => {
// optional: cleanup or notify on discard
return {
content: [{ type: "text", text: `Discarded batch rename. Reason: ${reason}` }],
};
},
});
return {
content: [{ type: "text", text: `${previewSummary}. Call resolve to apply or discard.` }],
};
},
});
export default factory;

Disponibilidad en tiempo de ejecución y fallos

Sección titulada «Disponibilidad en tiempo de ejecución y fallos»

pushPendingAction es conectado por el cargador de herramientas personalizadas mediante el PendingActionStore de la sesión activa.

Si el tiempo de ejecución no dispone de un almacén de acciones pendientes, pushPendingAction lanza:

  • Pending action store unavailable for custom tools in this runtime.

Comportamiento de selección de herramientas

Sección titulada «Comportamiento de selección de herramientas»

Cuando PendingActionStore.hasPending es verdadero, el tiempo de ejecución del agente inclina la selección de herramientas hacia resolve, de modo que las vistas previas pendientes se finalicen explícitamente antes de que continúe el flujo normal de herramientas.

  • Utilice acciones pendientes únicamente para operaciones destructivas o de alto impacto que deban admitir aplicación/descarte explícito.
  • Mantenga label conciso y específico; se muestra en la salida del renderizador de resolve.
  • Asegúrese de que apply(reason) sea determinista e idempotente para una ejecución de un solo disparo; reason es informativo y no debe modificar el comportamiento.
  • Implemente reject(reason) cuando el descarte requiera limpieza (estado temporal, bloqueos, notificaciones); omítalo en vistas previas sin estado donde el mensaje predeterminado sea suficiente.
  • Si su herramienta puede preparar múltiples vistas previas, recuerde la semántica LIFO: la última acción enviada se resuelve primero.