Files
oh-my-pi/docs/resolve-tool-runtime.md
T
can1357 5ff277349c refactor(coding-agent): consolidated tool surface onto xd:// devices and hub
- Added the `xd://` virtual device protocol (`internal-urls/xd-protocol.ts`, `tools/xdev.ts`): tools declaring `loadMode: "discoverable"` are unmounted from the request tools array and driven via `read xd://` (list/docs+schema) and `write xd://<tool>` (execute), gated by the `tools.xdev` setting (default on) and inlined into the system prompt.
- Merged the `irc`, `job`, and `launch` tools into a single `hub` tool (`tools/hub/`, `async/job-manager.ts`): messaging keeps `send`/`inbox`/`list`, job control maps to `wait`/`cancel`/`jobs`, process supervision keeps `start`/`logs`/`stop`/`restart`/`describe` with `ps`, and the unified `wait` races background jobs against peer messages; SDK `IrcTool`/`JobTool`/`LaunchTool` are replaced by `HubTool`.
- Removed the hidden `resolve` tool in favor of the `xd://resolve`/`xd://reject`/`xd://propose` resolution devices, auto-including `write` whenever a deferrable tool or plan mode is present.
- Removed the BM25 tool-discovery system: the `search_tool_bm25` tool, the `tool-discovery` module, the `tools.discoveryMode`/`mcp.discoveryMode`/`mcp.discoveryDefaultServers`/`tools.essentialOverride` settings, per-tool MCP selection, and the `mcp_tool_selection` message type.
- Unified tool presentation on `ToolLoadMode` (`essential`|`discoverable`), replacing the custom-tool `xdev?: boolean` opt-out; custom, extension, MCP, RPC host, image-generation, and TTS tools now default to `discoverable`, and added a `satisfies` predicate to `SoftToolRequirement`.
- Removed the standalone `ssh` command tool and `ssh/ssh-executor` (the `ssh://` read/write/search protocol stays), and made `--tools` address hidden built-ins.
- Updated collab-web to render `xd://` dispatches and `hub` op families, dropped the `search_tool_bm25`/`ssh`/`report-finding` renderers, refreshed tool docs and prompts, and migrated the affected tests and changelogs.
2026-07-15 15:16:29 +02:00

54 lines
2.5 KiB
Markdown

# Resolution devices runtime
Pending previews and plan approval no longer use a `resolve` tool. They finalize through three plain-text writes handled by `packages/coding-agent/src/tools/resolve.ts`:
- `/xdev/resolve` — apply the pending staged preview; body = reason text
- `/xdev/reject` — discard the pending staged preview; body = reason text
- `/xdev/propose` — submit the plan for approval while plan mode is active; body = the plan slug/title (`<slug>` for `local://<slug>-plan.md`)
## Preview flows
Preview producers call `queueResolveHandler(...)` with `apply(reason)` and optional `reject(reason)` callbacks. That registers a non-forcing pending invoker in `ToolChoiceQueue`.
While a preview is pending, `AgentSession.nextToolChoiceDirective()` returns a soft requirement:
- `toolName: "write"`
- `satisfies: isPreviewResolutionToolCall`
- reminder from `resolve-device-reminder.md`
So the model can comply by writing to `/xdev/resolve` or `/xdev/reject`; a write to any other path is still a detour and gets skipped/escalated.
Dispatch path:
- `dispatchResolutionDevice(session, "resolve" | "reject", text)`
- `peekQueueInvoker() ?? peekPendingInvoker()`
- `runResolveInvocation(...)`
`reject` with no pending action succeeds (`Nothing to reject; no pending action remains.`). `resolve` with no pending action throws.
## Plan approval
Plan mode installs a separate proposal handler through `setPlanProposalHandler(...)`.
- `InteractiveMode` uses it to hand `PlanApprovalDetails` to the plan-review UI.
- ACP mode uses it to run elicitation/approval and emit mode updates.
- PlanYolo uses it to auto-approve and switch to the execution target.
Dispatch path:
- `dispatchResolutionDevice(session, "propose", title)`
- `peekPlanProposalHandler()`
`/xdev/propose` is only valid while plan mode is active.
## Why `write` is guaranteed
Because previews and plan approval now ride `write`, the harness keeps `write` available whenever it is needed:
- `createTools(...)` auto-appends `write` when a `deferrable` tool is active (e.g. `ast_edit`)
- `createAgentSession(...)` keeps `write` registered when a deferrable tool exists or plan mode is enabled
## Custom tools
Custom tools still stage previews through `pushPendingAction(...)`; the loader forwards them into `queueResolveHandler(...)`. Nothing about the custom-tool API changes except the model-facing finalization step: the follow-up is now a plain-text write to `/xdev/resolve` or `/xdev/reject`, not a `resolve` tool call.