feat(acp): show the command in execute titles; test via the real bash tool; RFC for terminal rendering

- bash presentCall title is now "description — command" (e.g. "List files in
  src — ls -la src"). An execute-kind ACP card HIDES rawInput (Zed renders it
  only for non-terminal tools), so the command must ride in the always-visible
  title to be seen — matching how claude-agent-acp/codex-acp title execute
  tools. The command stays in rawInput too for non-execute UIs that show it.
- Rework the acp tool-call presentation tests (turns + load replay) to drive the
  REAL dsh-tool-bash + dsh-bash-local via a new makeBridgeHarness({ withBash })
  option, running an actual `echo` — instead of an inline fake bash tool. The
  mock MODEL still scripts the call (deterministic, no key), but the tool and
  executor are real, so the test verifies the shipping presentCall/presentResult.
- AGENTS.md: add the principle "prefer the REAL implementation over a mock/
  stand-in in tests" (mock only the expensive/non-deterministic boundary).
- RFC (proposed): the ACP terminal sub-protocol + command classification — the
  capability-gated rich rendering (live cwd-header terminal card, classify a
  `cat` as a read / `grep` as a search) that the reference adapters do; the
  fenced ```console text block stays the no-capability baseline. Studied
  codex-acp, claude-agent-acp, and Zed's renderer to ground it.
This commit is contained in:
Tianyi Cui
2026-06-18 11:23:12 +08:00
parent 8a92338d2f
commit 8acafe918f
13 changed files with 144 additions and 86 deletions
+10 -7
View File
@@ -133,15 +133,18 @@ export function renderResult(result: BashRunResult): string {
// ---------------------------------------------------------------------------
/**
* Pending-state presentation for a `bash` call: the model-written `description`
* is the always-visible title (the schema requires it precisely so a UI has a
* readable summary — "List files in the current directory"), `kind: 'execute'`
* (a terminal/run treatment), and the exact `command` is the `rawInput` so the
* verbatim command stays visible in a UI's detail view without crowding the
* title. Mirrors how Zed / the reference ACP adapters render execute tools.
* Pending-state presentation for a `bash` call. The title is the model-written
* `description` followed by the exact `command` ("List files — ls -la src"):
* `kind: 'execute'` gets a terminal/run treatment in a UI, but an execute-kind
* card HIDES `rawInput` (Zed: `should_show_raw_input = !is_terminal_tool`), so
* the command MUST ride in the always-visible title to be seen — the reference
* ACP adapters (claude-agent-acp, codex-acp) likewise put the command in the
* title for execute tools. The description leads (a readable summary the schema
* requires); the command follows so the verbatim text is still there. `rawInput`
* still carries the bare command for non-execute UIs that DO render it.
*/
function presentBashCall(args: { command: string; description: string }): ToolCallPresentation {
return { title: args.description, kind: 'execute', rawInput: args.command }
return { title: `${args.description}${args.command}`, kind: 'execute', rawInput: args.command }
}
/**