4.6 KiB
4.6 KiB
resolve
Finalizes a queued preview action by applying or discarding it.
Source
- Entry:
packages/coding-agent/src/tools/resolve.ts - Model-facing prompt:
packages/coding-agent/src/prompts/tools/resolve.md - Key collaborators:
docs/resolve-tool-runtime.md— preview/apply runtime referencepackages/coding-agent/src/extensibility/custom-tools/loader.ts— forwards custom pending actions into the queuepackages/coding-agent/src/tools/ast-edit.ts— built-in preview producer examplepackages/coding-agent/src/session/agent-session.ts— tool-choice queue and invoker access
Inputs
| Field | Type | Required | Description |
|---|---|---|---|
action |
`"apply" | "discard"` | Yes |
reason |
string |
Yes | Required explanation passed through to the queued callback. |
Outputs
- Single-shot result.
execute()returns whatever the queued invoker returns, withdetailswrapped/augmented to include:actionreasonsourceToolName?label?sourceResultDetails?— originalresult.detailsfrom the apply/reject callback when present
- If
discardhas no custom reject callback, the default success payload isDiscarded: <label>. Reason: <reason>. - The TUI renderer is inline and merges call+result into one block.
Flow
- Preview-producing code calls
queueResolveHandler(...)with a label, source tool name, andapply(reason)callback, plus optionalreject(reason). queueResolveHandler(...)asks the session for a forcedresolvetool choice and pushes it into the tool-choice queue withpushOnce(...).- The queued entry is marked
now: true; if the model rejects that forced tool choice,onRejectedreturnsrequeue, so the reminder comes back. queueResolveHandler(...)also injects aresolve-remindersteering message:This is a preview. Call the resolve tool to apply or discard these changes.- When
resolve.execute()runs, it wraps the call inuntilAborted(...)and fetches the current queue invoker withsession.peekQueueInvoker(). - If no invoker exists, it throws
ToolError("No pending action to resolve. Nothing to apply or discard."). - Otherwise it invokes the queued callback with
{ action, reason }. - For
apply, it always executes the producer'sapply(reason)callback. - For
discard, it executesreject(reason)when provided; if that callback is absent or returnsundefined,resolvefabricates the default discard message. - Before returning, it merges resolve metadata into
result.detailsso renderer/UI code can show the action, label, and originating tool.
Modes / Variants
apply: runs the queuedapply(reason)callback and returns its content.discardwith reject callback: runsreject(reason)and returns that callback's content.discardwithout reject callback: returns the built-inDiscarded: ...text payload.
Side Effects
- Session state
- Consumes the current pending preview through the session tool-choice queue; there is no separate pending-action stack.
- Adds a
resolve-remindersteering message when a preview is queued.
- User-visible prompts / interactive UI
- No direct prompt. The visible effect depends on the preview-producing tool and the resolve renderer.
- Background work / cancellation
untilAborted(...)lets abort signals interrupt resolution before invoking the callback completes.
Limits & Caps
- Hidden tool: not discoverable in the normal tool index (
packages/coding-agent/src/tools/resolve.ts,packages/coding-agent/src/session/agent-session.ts). - Exactly one active queue invoker is consulted per call via
session.peekQueueInvoker(). - There is no independent queue depth cap in this tool; ordering follows the shared tool-choice queue (
docs/resolve-tool-runtime.md).
Errors
- No pending preview: throws
ToolError("No pending action to resolve. Nothing to apply or discard."). - Any exception from the queued
apply/rejectcallback propagates throughresolve. - Aborts during
untilAborted(...)surface as the underlying abort error from the utility.
Notes
reasonis informational;resolvepasses it through but does not interpret it.queueResolveHandler(...)is the canonical built-in integration point; custom tools usepushPendingAction(...), which the loader forwards into the same mechanism.- The tool only works because another tool already staged a preview and forced a one-shot
resolvechoice. sourceResultDetailsis added only when the apply/reject callback returned a non-nulldetailsfield; custom pending-actiondetailsare not forwarded automatically by the loader.