Repository navigation
Chat: send images and PDFs to acpmux ahead of the prompt, by reference - #23047
teamleaderleo wants to merge 24 commits into
Conversation
Red before the fix: acpmux has no _acpmux/attachment_put, the host refuses it, and the page sends every image inline in the prompt frame. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cf0-cb72-7882-92b8-379487dc4c66&host=cosmic-gray
Six Retina screenshots in one prompt made a frame past acpmux's 16 MiB WebSocket limit, and acpmux reset the chat's connection (2026-10-20). Now the page puts each image or PDF with _acpmux/attachment_put (sessionId, mimeType, data), which acpmux keeps by SHA-256 as it already keeps prompt images, marked as that chat's. The prompt block names it as uri: acpmux-attachment:<id> with no data, and acpmux puts the bytes back before the prompt runs. An id that chat did not put refuses the prompt (attachment.missing) instead of running it without the image. The host allows the put for a chat in the pane's scope, in the pane's shape and with no gesture: it runs nothing, and the prompt keeps its gesture. An acpmux without the method (an older one, or a peer's), or a put that fails, gets the images inline as before. A prompt frame is now small, so the host's prompt journal keeps image prompts for resend too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cf0-cb72-7882-92b8-379487dc4c66&host=cosmic-gray
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Owned by an agent session · session |
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Passes: CI passes on CI passes on Written by web and size checks: green
Tour of Gallery before/after for
States
Pick other states with a |
|
Visual preview of ca401a9: in the maintainers' private review feed. |
|
Found 18 test failures on Blacksmith runners: Failures
...and 8 more test failures. View all on Blacksmith: run 39719772293, run 39719772113, run 39719772135
|
…puts take A prompt with images waited for its puts before its session/prompt, so a prompt sent after it without attachments (a harness switch's held prompts, a prompt behind a queued one) could reach acpmux first. Each send now writes its request only after the one before it did; a put with no answer in 30 s goes inline. The page-allowlist parity test reads ATTACHMENT_PUT like PREWARM_METHOD. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cf0-cb72-7882-92b8-379487dc4c66&host=cosmic-gray
|
|
…ment-put # Conflicts: # cmux-tui/crates/acpmux/src/hub/prompt_images.rs # cmux-tui/crates/acpmux/tests/prompt_images.rs
…ment-put # Conflicts: # cmux-tui/crates/acpmux/src/server/requests.rs
…nd call The ordering chain awaited the (empty) puts and the previous prompt even when there was nothing to wait for, so session/prompt went out a few microtasks later. A socket dropped right after the send then failed the requests in flight before the prompt's was registered, and it waited forever (transcript-steer-continuous: a Send now whose request the dropped socket fails). Now a send waits only for its own puts and for a prompt sent before it whose request is not written yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cf0-cb72-7882-92b8-379487dc4c66&host=cosmic-gray
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cf0-cb72-7882-92b8-379487dc4c66&host=cosmic-gray
…ment-put # Conflicts: # webviews/src/agent-session/acpmux/direct.ts
…ment-put # Conflicts: # webviews/src/agent-session/acpmux/attachments.ts
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
|
|
|
Picks up base's fix for the agent pane's wave.css styles, red at the last merge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cf0-cb72-7882-92b8-379487dc4c66&host=big-red
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (subagent, correctness first): SHIP at ad88838 Independent subagent reviews: SHIP at bd47c1e (full PR, incl. the agent pane allowlist and Rust policy mirror parity); its medium finding (a queued prompt removed while its images upload still ran) fixed in 47217d3 (failing test) and e036a81, re-reviewed SHIP; that review's two low findings fixed in 7d708aa, re-reviewed SHIP. ad88838 is a clean merge of feat-cmux-next (base's wave.css and ResetAllRetiredKeysTests fixes) that leaves this PR's files unchanged. Agent session: big-red |
|
|
|
Orphaned: no activity for 14 h, and no lane holds a lease on it. The orphan sweep could not merge |
|
Review (codex gpt-6-astra xhigh, next-review): BLOCK at dd8e557
|
|
Superseded by #25730 (merged as 21f1b02). That PR sends prompt files by reference: the prompt names a finished upload of its own chat, the daemon resolves it before anything reads the prompt, and a reference outside the chat's uploads is refused. Unlike this PR it has no 10 MiB limit, and it covers every file type, not just images and PDFs. The app sender is being built against its contract (cmux-tui/crates/acpmux/docs/prompt-uploads.md), with resumable and binary uploads in #25793 and #25803. Nothing here is still needed, so I'm closing this rather than re-cutting it. |
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Summary
_acpmux/attachment_put {sessionId, mimeType, data}keeps an image or PDF (at most 10 MiB; a larger one still goes inline) by SHA-256 under<ACPMUX_HOME>/attachments, the same store prompt images already use. It marks the file as that chat's and answers{id}.uri: "acpmux-attachment:<id>"with nodata. acpmux puts the bytes back before anything else reads the prompt, souser_messageimage ids,_acpmux/attachmentreads, PDF handling and harness delivery are unchanged. A prompt that names an id its own chat did not put is refused withattachment.missing; it is not run without the image.AcpmuxPaneMethods, pluspolicy.json): the put is allowed only for a chat in the pane's scope, with exactlysessionId,mimeTypeanddata, and needs no gesture. It runs nothing; the prompt still needs its gesture. The relay already strips_metainside prompt blocks, which is why the reference uses ACP'surifield.direct.tsputAttachments,attachments.tspromptBlocks): it puts only when the daemon lists_acpmux/attachment_putininitialize. Images go inline as before for an older acpmux, a peer's acpmux without the method, or a put that fails.Why
On 2026-10-20 a coordinator chat lost its connection. A prompt with six Retina screenshots was about 15 MB of base64, and the next one passed acpmux's 16 MiB WebSocket frame limit. acpmux reset the socket, and the chat said "Not sent: The agent connection was interrupted". The product call is never to refuse a person's screenshots and to send attachments out of band, so prompt size never hits a frame limit. Related PRs:
Tests (committed red before the fix)
cmux-tui/crates/acpmux/tests/prompt_images.rsan_attachment_put_ahead_goes_with_the_prompt_that_names_it:user_messagenames the image, and_acpmux/attachmentreads its bytes back;attachment.missing, and nothing is logged for it.AgentPaneAttachmentRelayTests.anImageIsPutOnlyForTheChatInTheShapeThePaneSends: refuses a chat outside the pane's scope and an extra param, and passes the pane's own shape without a gesture.webviews/src/agent-session/acpmux/attachmentPut.test.ts:promptBlocksnames a kept image by reference;Notes
policy.jsonalike; their lists match.attachments/today (prompt images on base have none either); the put marks are empty files beside it. A follow-up gives puts the age sweep and purge-on-kill thathub/file_uploads.rshas.Agent session: cosmic-gray
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Images and PDFs are sent to acpmux ahead of the prompt that names them, by URI, keeping attachment bytes out of prompt frames and avoiding WebSocket frame-limit disconnects. Prompts reach acpmux in send order, even when earlier attachment puts take longer.
_acpmux/attachment_putkeeps images and PDFs up to 10 MiB by SHA-256 and marks them for that chat, so the base64 read-back fits one acpmux message.attachment.missing.Written for commit dd8e557. Summary will update on new commits.