Skip to content

acpmux: the app's WebSocket takes binary upload frames, with no size cap - #25803

Merged
teamleaderleo merged 6 commits into
feat-cmux-nextfrom
hb-busy-accept/upload-frames
Oct 27, 2026
Merged

teamleaderleo merged 6 commits into
feat-cmux-nextfrom
hb-busy-accept/upload-frames

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

The app's native side streams a file's raw bytes to the daemon as WebSocket binary frames: no base64, no size cap, a few frames of memory whatever the file's size. Stacked on #25793 (base is its branch). Contract: #25774, sections 1 and 1b.

Leo: "why the FUCK SHOULD THERE BE A FUCKING SIZE CAP ANYWAYS JUST FUCKING / I ALREADY SAID WE NEED ARBITARRILY LARGE FILES OF ANY TYPE". The spec: files of any type and size stream to disk in chunks, resumable, with progress; bytes never cross the page binding as base64; the peer hop is uncapped and resumable.

Change

src/server/upload_frames.rs, wired into the WebSocket reader in server/mod.rs:

  • One binary frame is one _acpmux/file_put_data request: "AMUP", a u32 big-endian header length, the JSON-RPC header {"id", "method": "_acpmux/file_put_data", "params": {sessionId, uploadId, offset}}, then the raw bytes. The answer is an ordinary text response with the same id: {offset} once the bytes are on disk (file_uploads::append, shared with file_put_chunk), or the upload.* reasons from acpmux: resumable uploads report where they stand, check their bytes, and fail on size only when the disk is full #25793.
  • One worker per connection writes frames in order from a queue of 4 (WINDOW). A sender may keep 4 in flight; past that the socket slows it. Stop condition: the worker ends when the connection's reader ends (its sender drops) or the writer closes.
  • Only the local app's connection (Origin::LocalApp) may send frames. Any other gets filePut.remote as its answer, never silence (the original bug was an app bridge that dropped oversize calls unanswered).
  • A text message on the same connection is read only after every frame before it is written and answered (InFlight: a count and a Notify; the worker releases what it holds when it ends). So a finish, status or prompt sent right behind the last frames sees all their bytes. A connection that sends no frames never waits.
  • A chat on a peer: the bytes go to the peer that owns it as file_put_chunk requests of at most 512 KiB over the peer link, so the peer hop has no cap and resumes the same way (status and finish are forwarded). A peer that does not list filePutChunks is refused at begin and at every frame, before anything is sent.
  • Feature uploadFrames; _acpmux/file_put_data is in the protocol registry.

Risk: contained to WebSocket binary frames, which the daemon dropped before. Text frames take the same path as before, except that on a connection with frames in flight they wait for those frames.

Tests

  • tests/upload_frames.rs: a 6 MiB file in 1 MiB frames, 2 then 4 in flight, answered in order; the connection drops and a new one resumes from file_put_status; a stale frame is upload.offset with the resume offset; finish with sha256. A Web connection's frame is answered filePut.remote. A peer's chat gets the frames written on the peer, SHA-256 intact.
  • a_finish_right_behind_its_frames_sees_every_byte: a finish sent right behind 5 unanswered frames (3 rounds) gets its answer after every frame's. Before the fix, the finish was answered ahead of 3 frames ([3, 4, 8] against [3, 4, 5, 6, 7, 8]).
  • a_peer_without_chunked_uploads_is_refused_before_anything_is_sent: a peer listing filePut but not filePutChunks is refused filePut.unsupported at begin and at a frame, and gets nothing.
  • tests/prompt_uploads_large.rs (Linux): a 2,000,000,000-byte file of no known type streamed the app's way (1 MiB frames, 4 in flight) to a busy chat, finished with its sha256, named in a prompt, then checked at the path the agent got.

Results (cmux-ci test, 32-vCPU Linux):

2 GB: uploaded in 8.406496689s, accepted in 1.252289ms, sha256 7c0b933376ce085551dd57695c4a77881a2783679c5969eec9299817a02ecb41, peak RSS 62 MiB
50 screenshots: uploaded and accepted in 218.690875ms, accept 59.379628ms

Not in this PR: the native sender (its owner builds against this), and model-sized copies of large images per harness (next PR).

Agent session: agent session

🤖 Generated with Claude Code

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@teamleaderleo
teamleaderleo force-pushed the hb-busy-accept/upload-resume branch 2 times, most recently from eedba3d to b35e059 Compare October 27, 2026 00:55
@teamleaderleo
teamleaderleo force-pushed the hb-busy-accept/upload-frames branch from aa23033 to b942f7e Compare October 27, 2026 00:55
@teamleaderleo
teamleaderleo force-pushed the hb-busy-accept/upload-frames branch 2 times, most recently from 15a44a8 to e966c95 Compare October 27, 2026 01:23
@teamleaderleo
teamleaderleo force-pushed the hb-busy-accept/upload-resume branch from 768cb76 to 7d01fa3 Compare October 27, 2026 01:44
@teamleaderleo
teamleaderleo force-pushed the hb-busy-accept/upload-frames branch from e966c95 to f5c570c Compare October 27, 2026 01:45
@teamleaderleo
teamleaderleo force-pushed the hb-busy-accept/upload-frames branch from f5c570c to f45cb86 Compare October 27, 2026 02:50
@teamleaderleo
teamleaderleo force-pushed the hb-busy-accept/upload-frames branch from f45cb86 to 39a825b Compare October 27, 2026 03:19
Base automatically changed from hb-busy-accept/upload-resume to feat-cmux-next October 27, 2026 05:27
teamleaderleo and others added 6 commits October 26, 2026 22:28
… GB file reaches a busy chat that way

Binary data frames on the app's own WebSocket (4 in flight), resumed from
file_put_status after a disconnect, finish checked by sha256; any other
connection gets a refusal as its answer; a peer's chat is written on the peer.
A 2 GB file of no known type streams in 1 MiB frames to a busy chat, is
accepted in under a second, and reaches the agent by path with its SHA-256
intact, with a small peak RSS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
…der with no size cap

One binary frame is one _acpmux/file_put_data request: "AMUP", a u32
big-endian header length, the JSON-RPC header {sessionId, uploadId, offset},
then the raw bytes. A per-connection worker writes frames in order from a
queue of 4 and answers each once its bytes are on disk, so memory stays at a
few frames whatever the file's size. Any connection but the local app's gets
filePut.remote as its answer, never silence. A peer's chat gets the bytes as
file_put_chunk requests over the peer link. Feature uploadFrames.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
…the frame it edits next

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
…e, and a peer without chunked uploads is refused up front

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
…upload to a peer without filePutChunks is refused before anything is sent

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
…before the finish's

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-1288bbb2b5d2f5c6b66a
@teamleaderleo
teamleaderleo force-pushed the hb-busy-accept/upload-frames branch from 67d5359 to 65f722d Compare October 27, 2026 05:28
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 27, 2026
@blacksmith-sh

blacksmith-sh Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Found 7 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmpn7ehl082/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmpxacty1vc/summary-fail.json (live):/summary-fail.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@github-actions

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

red: cmux-next checks (god files, concurrency, crash safety, l10n); no finished base run on e6adb7f to compare; do not merge until green; see lane-rules

@teamleaderleo
teamleaderleo marked this pull request as ready for review October 27, 2026 05:44
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-e3m83 created for this PR by the cmux coordinator.

@teamleaderleo
teamleaderleo merged commit cc33fa8 into feat-cmux-next Oct 27, 2026
228 of 308 checks passed
@teamleaderleo
teamleaderleo deleted the hb-busy-accept/upload-frames branch October 27, 2026 06:00
@github-actions

Copy link
Copy Markdown
Contributor

The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/40458763715 at 9a52a3c failed: cmux-next generated files.
Those jobs last passed at 865b6c3. This pull request is one of 5 merged since: #25885, #25876, #25803, #25955, #25774.
If the failure is in your change, fix forward on feat-cmux-next. Pull requests run only the tiers their paths reach (docs/ci/cmux-next-tiers.md); label a batch PR full-ci to run them all before merging.

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

This branch was previously deployed

3 inactive deployments
artifacts — 65f722dc Deployed Oct 27, 2026 by teamleaderleo via add the Windows daemon to the tree #62445
sentry-dsyms — 65f722dc Deployed Oct 27, 2026 by teamleaderleo via upload cmux-tui dSYMs to Sentry #62445
ci-routing-agent — 65f722dc Deployed Oct 27, 2026 by teamleaderleo via wait for same-key tree publisher #62445
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant