Replies: 1 comment 1 reply
|
Verified all of this against rc.2 (HEAD b150a55) — the claims hold, and I want to add the one argument I think is strongest in your favor, which comes from the note itself.
The handler at packages/acp/acp/src/index.ts:218-252 is a single choke point that emits only committed assistant text/images. The comment there is explicit: "Raw chunks, reasoning, tools, plans, titles, and retry markers are presentation or trace data and stay off the automation wire." So tool events do reach the handler via session/event — the bridge just ignores them. That means your patch is a filter widening at one site, not new plumbing, and the ordering guarantee you rely on is real: every delivery is chained on the previous outputTail (index.ts:228-239), so any tool update appended to that chain cannot land after the text that describes it. I also confirmed edges.spec.ts:25 pins the current behavior with exactly the title you quote, and sdk/protocol/README.md:39 contains the dead-capability sentence verbatim.
The note's Consequences justify excluding tool traces by saying automation clients "inspect durable logs or another API when they need reasoning, tool traces, titles, or richer state." But the same note removed the path that would make that practical: ACP "does not provide session load/list/delete" and is fresh-session-only. An ACP client cannot read the durable log of the session it just ran — the sanctioned route is "another API", and as you found, the JSON-RPC surface explicitly has no server-to-client requests today (the SDK README calls it dead capability pending future approval flows). So right now there is no surface where an automation client gets both a permission flow and a tool trace. That is a real hole, and your proposal is the only one in the repository that closes it.
Look at the note's excluded list: "Reasoning, raw chunks, tool activity, todos, plans, titles, retry markers, terminal metadata, diffs, locations, resource links." The first two are intermediate model output. The rest are UI state or editor presentation. Tool calls are the odd member out — they are durable agent actions, and the SDK already has vocabulary for them (ToolCallUpdate is part of the SessionUpdate union, the same union as the committed answer). Carving tool events out of the presentation set does not reopen the editor bridge; it corrects a grouping that the note made for convenience rather than principle.
With title/content on the permission request (the #4276 fix) and tool progress on the stream (this), a human-facing ACP client gets both "what is being asked" and "what the agent did" — the two halves of a transcript. If both land, the ACP surface stops being a blind answer box and becomes a protocol where an automation client can show its work. The default-none opt-in is the right call — it keeps every existing deployment's silence and gives the maintainers a reviewable, reversible increment. I'd like to see this one move. |
Uh oh!
There was an error while loading. Please reload this page.
A conforming ACP client shows a finished DSH turn as an answer with no visible work. It cannot say whether the agent read a file, ran a command, or produced the answer from nothing — and when a permission request arrives for
call_…(#4276), there is no call in the transcript to attach it to.I have read ACP as an automation-only protocol, and this doesn't argue with it. Terminal cards, diffs, locations, session navigation, configuration pickers and human elicitation belong exactly where that note put them — that bridge really had become a second product UI.
The narrower claim:
tool_callandtool_call_updateare different in kind from those. They are two members of the spec's ownSessionUpdateunion — what the agent did, not how an editor draws it. The note groups them with terminal metadata and editor cards; I think that grouping is what costs more than it saves, because it is the one thing every ACP client needs and the only one the protocol has a word for.The idea
One config value, default off:
'none'— the established contract, unchanged: committed assistant text and images only. Automation clients,dsh-subagent-acpincluded, see no difference.'tools'— addstool_call(id, tool name as title, kind, parsedrawInput) andtool_call_update(completed/failed, result text). Nothing else joins: no terminals, diffs, locations, plans, titles, reasoning or elicitation.Opt-in matters more than the mapping: the deployment that wants a human watching asks for it, and every other deployment keeps today's silence by default.
What it looks like
Same build, same prompt — "Read app.js and say in one sentence what it exports." — through an ACP client:
A working patch, if it's useful to have something concrete to react to: iamenahs#2 — tool updates ride the existing per-session
outputTailchain so a call never lands after the text that describes it,acp-demoforwards the value,npm run typecheck0,npm run lint0, 95 tests pass includingedges.spec.ts's "does not emit tool, terminal, plan, title, or reasoning presentation updates", untouched, because the default isnone.The alternative I looked at first
@deepseek-ai/dsh-sdk-jsonrpc-serverforwards the wholesession/eventstream and would solve this for one client without touching ACP at all. It has no approval flow —packages/sdk/protocol/README.md: "Server→client requests are dead capability… the Python SDK's responder surface exists for future approval flows" — so today it trades a human in the loop for fidelity. ACP is the only surface with both, which is why I'm asking here rather than just moving over.If the answer is "the SDK is where interactive clients belong, and the approval flow is coming", that's a perfectly good answer — I'd just like to know which road to build on. Context: I maintain an ACP client that also drives Codex, Claude Code and Cursor, and DSH is the one agent whose work the transcript can't show.
All reactions