5ff277349c
- 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.
54 lines
2.5 KiB
Markdown
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.
|