Replies: 1 comment 2 replies
|
Verified against rc.2 (HEAD b150a55) — the drop is real, and the fields are in scope at the exact line you quote, so this is a two-field one-site fix.
Your reproduction (sandbox-policy workspace-write refusal, approval raised) is exactly the case where reason carries the whole question: the sandbox refusal reason is what a human needs to decide allow-once vs reject. toolName alone (write or bash) would still leave the client guessing why the tool call needs approval; reason turns the bare id into a decidable prompt. The handler has it in scope — it is purely a forwarding decision.
At :274-276, forward what the asker supplied into the toolCall object. The ToolCallUpdate fields you cite (title, kind, rawInput, content) are the SDK's own channel for this:
This stays inside the automation-only boundary you quote: nothing new is published on the session stream, no terminal/diff/card machinery, just the question itself carried on the permission request. The client still chooses allow once / reject once / cancel — it just now has the information to choose.
The bridge's comment at :268-269 says permission requests are a machine policy channel for ACP clients and never infers a durable grant from an unknown client response. Forwarding toolName/reason does not change either property — the grant semantics stay one-shot, and the client remains a blind policy voter that can now see what it is voting on. The fix is compatible with the documented contract.
The ACP bridge tests (packages/acp/acp/tests) should assert the forwarded toolCall carries title/content — a regression test that would have caught this drop. The minimal test: emit approval/request with toolName + reason, capture the requestPermission call, assert toolCall.title equals toolName and the text content equals reason. Your #4277 proposal (opt-in tool-call progress) is the complementary half — with title/content on the permission request and optional progress on the stream, a human-facing ACP client has both "what is being asked" and "what the agent did". They compose cleanly. |
Uh oh!
There was an error while loading. Please reload this page.
@deepseek-ai/dsh-acpasks the client to approve a baretoolCallId:The bridge publishes no tool updates — deliberately, per ACP as an automation-only protocol — so that id is one the client has never seen. It has nothing to correlate it to and nothing to describe, and can only render a generic prompt.
That same note deliberately keeps one-shot
session/request_permission: "The client chooses allow once, reject once, or cancel." A choice that cannot be described isn't one.Why this reads as a bug rather than a boundary
The information is already at the call site and dropped.
ApprovalRequest(packages/interaction/user-approval/src/index.ts) carries:readonly toolName: string— "The tool the question is about (presentation and audit)"readonly reason?: string— "The asker's human-readable explanation of WHY it is asking"and ACP's
ToolCallUpdate— the exact type thetoolCallfield takes — already allows optionaltitle,kind,rawInputandcontent. Passing what the asker supplied is not presentation policy; it is the question.Reproduction
dsh0.1.0-rc.8, repo atb150a55(0.1.1-rc.2),@agentclientprotocol/sdk0.14.1sandbox-policyworkspace-write,dsh-user-approvalpolicy: asksession/newin some directory.<path outside the workspace>using your tools."Received, client side:
Rendered, with nothing to work from:
"The agent asks permission to continue."This is not a corner case for attended deployments: with
workspace-write+ask, the only time DSH asks is when it is about to act outside the workspace — the moment when knowing what it is matters most.Fix
toolName→toolCall.title;reason, when present → a text content block. No new session updates, so the output boundary is untouched.approval.spec.tsasserts withtoMatchObject, so it stays green.Patch, with tests and end-to-end output (
summarybecomes"write"): iamenahs#1 —npm run typecheck0,npm run lint0, ACP suite 84 passed. Happy to reshape it however you'd prefer, or to hand it over as a description if you'd rather write it yourselves.Found while building an ACP client against DSH; the same client drives Codex, Claude Code and Cursor, and this is the one place where the approval cannot be shown.
All reactions