Problem or Opportunity
The ACP terminal capability lets an agent request that the client (Termul) run a command in a sandboxed subprocess. The Rust backend implements this fully and correctly — all five terminal RPCs (terminal/create, terminal/output, terminal/wait_for_terminal_exit, terminal/kill, terminal/release) are wired in src-tauri/src/acp/manager.rs:898-1022, with TerminalRegistry providing UTF-8-safe buffering, front-truncation, exit polling, and release_all on teardown (src-tauri/src/acp/terminal.rs).
However, the renderer only shows a static label for these tool calls and never displays the command output. In ToolCallCard.tsx:69-82:
if (item.type === 'terminal') {
// The ACP `terminal` content variant only references a terminal by id; its
// live output is fetched separately via `terminal/output` (not embedded in
// the tool call), so we surface the reference rather than inline output.
const terminalId = (item as { terminalId?: string }).terminalId
return (
<div ... >
{terminalId ? `Terminal ${terminalId}` : 'Terminal'}
</div>
)
}
The comment claims output is "fetched separately via terminal/output", but there is no UI code that actually fetches and displays it. The terminal/* RPCs are agent→client requests serviced by the backend; the renderer has no IPC command to retrieve an ACP terminal's output — it only sees tool-call updates that reference a terminalId.
Result: when an agent exercises the terminal capability (e.g. runs npm test, git status, a build script), the command executes correctly on the backend, but the user has no way to see what the command printed. The tool-call card just says "Terminal term-3". This makes the highest-risk client capability (arbitrary command execution) effectively unauditable from the UI, which is a significant trust/usability problem for production use.
Proposed Solution
- Expose a read-only IPC surface for ACP terminal output. Add a Tauri command (e.g.
acp_terminal_output(agent_id, terminal_id)) that returns the current buffered output + running flag + exit status from TerminalRegistry::output (src-tauri/src/acp/terminal.rs). Keep it read-only; the agent remains the sole writer.
- Render output in
ToolCallCard. When a tool-call content item has type === 'terminal', fetch and render the output (collapsible by default, expandable on click). Poll or subscribe while the terminal is running; stop once it exits.
- Surface exit status. Show exit code / signal (SIGINT/SIGKILL/SIGTERM on Unix) alongside the output, reusing the existing
TerminalExitStatus shape.
- Respect the buffer cap. If output was front-truncated (the
truncated flag), show an indicator like "output truncated (first N bytes omitted)".
Success Criteria
Additional Context
- Backend (complete, no change needed):
src-tauri/src/acp/terminal.rs, src-tauri/src/acp/manager.rs:898-1022.
- Frontend gap:
src/renderer/components/chat/ToolCallCard.tsx:69-82.
- The
allow_terminal capability defaults to false on AgentConfig (src-tauri/src/acp/config.rs:87-92) and is advertised in client_capabilities (src-tauri/src/acp/client.rs:30-32) — that gating is correct and should stay.
- Related: this is the renderer-side completion of the agent terminal capability (ADR-tagged M6 in
client.rs:30-32).
Problem or Opportunity
The ACP terminal capability lets an agent request that the client (Termul) run a command in a sandboxed subprocess. The Rust backend implements this fully and correctly — all five terminal RPCs (
terminal/create,terminal/output,terminal/wait_for_terminal_exit,terminal/kill,terminal/release) are wired insrc-tauri/src/acp/manager.rs:898-1022, withTerminalRegistryproviding UTF-8-safe buffering, front-truncation, exit polling, andrelease_allon teardown (src-tauri/src/acp/terminal.rs).However, the renderer only shows a static label for these tool calls and never displays the command output. In
ToolCallCard.tsx:69-82:The comment claims output is "fetched separately via
terminal/output", but there is no UI code that actually fetches and displays it. Theterminal/*RPCs are agent→client requests serviced by the backend; the renderer has no IPC command to retrieve an ACP terminal's output — it only sees tool-call updates that reference aterminalId.Result: when an agent exercises the terminal capability (e.g. runs
npm test,git status, a build script), the command executes correctly on the backend, but the user has no way to see what the command printed. The tool-call card just says "Terminal term-3". This makes the highest-risk client capability (arbitrary command execution) effectively unauditable from the UI, which is a significant trust/usability problem for production use.Proposed Solution
acp_terminal_output(agent_id, terminal_id)) that returns the current buffered output + running flag + exit status fromTerminalRegistry::output(src-tauri/src/acp/terminal.rs). Keep it read-only; the agent remains the sole writer.ToolCallCard. When a tool-call content item hastype === 'terminal', fetch and render the output (collapsible by default, expandable on click). Poll or subscribe while the terminal is running; stop once it exits.TerminalExitStatusshape.truncatedflag), show an indicator like "output truncated (first N bytes omitted)".Success Criteria
ToolCallCard.Additional Context
src-tauri/src/acp/terminal.rs,src-tauri/src/acp/manager.rs:898-1022.src/renderer/components/chat/ToolCallCard.tsx:69-82.allow_terminalcapability defaults tofalseonAgentConfig(src-tauri/src/acp/config.rs:87-92) and is advertised inclient_capabilities(src-tauri/src/acp/client.rs:30-32) — that gating is correct and should stay.client.rs:30-32).