Skip to content

acpmux clients (Rust): read a paged session list whole - #28273

Merged
teamleaderleo merged 9 commits into
feat-cmux-nextfrom
lane/acpmux-rust-clients-pages
Nov 1, 2026
Merged

teamleaderleo merged 9 commits into
feat-cmux-nextfrom
lane/acpmux-rust-clients-pages

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

On 2026-10-30 one daemon's session list with tools was 17 MB, past acpmux's largest reply, and acpmux refused it as message.too_large. #28182 makes _acpmux/sessions and _acpmux/watch with no limit answer such a list in byte-bounded pages: the first rows with a nextCursor, the rest from _acpmux/sessions {cursor, ...the same params less enabled}. The in-repo Rust clients that ask for the whole list read only the first reply, so against a paged daemon they would see only the first page.

A list that fits is still one reply with no cursor, so these clients behave as before against an older acpmux.

What changed

  • cmux-tui/crates/cmux-tui-core/src/server/agent_session_link.rs: AcpmuxLink::call_whole_list does what acpmux's Client::whole_list does. With a limit it makes one plain call, since that caller pages for itself. Otherwise it follows nextCursor through _acpmux/sessions with the same params less enabled and appends each page's sessions. timeout bounds each reply.
  • agent_session_children.rs (agent-session-children), agent_session_stream.rs (the attach's _acpmux/watch, whose list picks the children the attachment follows) and agent_transfer/agent_update.rs (the update plan's chat list) read their lists through it. The watch's first page and its cursor pages are merged before descendant_ids reads them.
  • cmux-next-ios/rust/crates/cmux-mobile-host/src/notify_waiting.rs: the phone push watch asks for each next page by its cursor. The classifier loads every page's rows and each row is observed. A failed page reconnects the watch, which reads the list again from its start. notify.rs: doc comment only.
  • agent_chat_notices.rs already pages with a limit and is unchanged.
  • Tests: agent_session_attach_tests.rs gives the fake acpmux a two-page _acpmux/sessions and a two-page watch. session_children_reads_every_page_of_a_list_too_big_for_one_reply and session_children_follows_a_child_only_a_later_watch_page_names cover cmux-tui-core. a_watch_list_past_one_reply_reads_its_rest_from_the_cursor covers mobile-host.

Tests

Red/green are both on hosted Linux through cmux-ci test at the PR head. The red run used the test commit alone and the green run used the fix.

bash scripts/ci/init-submodule.sh ghostty-next && ./scripts/install-zig-ci.sh
(cd cmux-tui && cargo test -p cmux-tui-core --lib session_children)
(cd cmux-next-ios/rust && cargo test -p cmux-mobile-host notify_waiting)

Observed / Not run

Changelog

none

Agent session: agent session

🤖 Generated with Claude Code

teamleaderleo and others added 2 commits October 30, 2026 10:22
acpmux answers `_acpmux/sessions` and `_acpmux/watch` with no `limit` in
byte-bounded pages with a `nextCursor` when the whole list is over its
largest reply. These tests fail today: agent-session-children lists only
the first page, the attach's watch misses a child only a later page names,
and the phone push watch never asks for the rest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c11d09c9f41988fc1d93
acpmux (#28182) answers `_acpmux/sessions` and `_acpmux/watch` with no
`limit` in byte-bounded pages with a `nextCursor` once the whole list is
over its largest reply, instead of refusing it as message.too_large. A list
that fits is one reply with no cursor, so these clients work unchanged
against an older acpmux.

- AcpmuxLink::call_whole_list mirrors acpmux's Client::whole_list: with a
  `limit` it is one call; else it follows `nextCursor` through
  `_acpmux/sessions` with the same params less `enabled`, concatenating
  `sessions`.
- agent-session-children, the attach's watch (the children it follows)
  and agent update's plan read their list through it.
- The phone push watch asks for each next page by its cursor and loads and
  observes every page's rows; a failed page reconnects the watch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c11d09c9f41988fc1d93
@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 30, 2026
@blacksmith-sh

blacksmith-sh Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Found 3 test failures on Blacksmith runners:

Failures

Test View Logs
test_a_picked_signing_label_has_a_rerun_alternative (main.RunsOnFallbackTests.test_
a_picked_signing_label_has_a_rerun_alternative)/
test_a_picked_signing_label_has_a_rerun_alternative (main.RunsOnFallbackTests.test_
a_picked_signing_label_has_a_rerun_alternative)
View Logs
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)/
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)
View Logs
test_no_runs_on_chain_ends_on_the_reserved_side_label (main.RunsOnFallbackTests.tes
t_no_runs_on_chain_ends_on_the_reserved_side_label)/
test_no_runs_on_chain_ends_on_the_reserved_side_label (main.RunsOnFallbackTests.tes
t_no_runs_on_chain_ends_on_the_reserved_side_label)
View Logs

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

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

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

Review a95e1cb: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr28273 -f ref=lane/acpmux-rust-clients-pages -f platform=macos -f backend_mode=local

web and size checks: green

Shipped in:

…repeated cursor and a page with no sessions

call_whole_list (cmux-tui-core) joined acpmux's byte pages without
restoring newest-first order, so the 256-entry caps in session children
and attach tracking could drop newer descendants. It also stopped
silently at a non-string cursor, looped on a repeated one, and took a page
with no sessions array for whole. It now does what acpmux's
Client::whole_list does. The mobile host's watch paging
(Waiting::next_page) refuses the same bad pages, so the watch reconnects
instead of paging forever or passing a partial list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c11d09c9f41988fc1d93
teamleaderleo and others added 3 commits October 31, 2026 01:54
…own error

Review follow-ups on reading acpmux's paged session lists whole:
- LinkError::BadList replaces the made-up Rpc refusal, so children and
  agent update report agent_session.bad_list / agent_update.bad_list
  instead of 'acpmux refused the request' (documented in spec/commands.md);
- an attach whose watch list comes in bad pages is refused, rather than
  following only some descendants and losing the rest's changes;
- an _acpmux/sessions reply with no sessions array fails too (a watch
  reply from before watches had one is taken as before);
- the mobile host's watch page has a 60 s deadline, past which the watch
  reconnects, like its info lookups;
- the children fixture carries updatedAt, and its paged fake serves the
  older rows first, as byte pages can, so the test checks the sort.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c11d09c9f41988fc1d93
…t not whole

call_whole_list passed a continuation page's own error (a refusal, a
timeout, a closed link) up as it was, so the attach, which refuses only a
BadList, went on with the first page alone and followed none of its
descendants. A failed page past the first is now BadList too ('acpmux's
session list could not be read whole'); the first page's error is the
call's as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c11d09c9f41988fc1d93
@cursor

cursor Bot commented Oct 31, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot 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.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol xhigh, next-review): SHIP at 17ee908

SHIP at 17ee908

Visual verdict: no images; Leo tries the build

  1. [P2] [follow-up] agent_session_link.rs:202: Continuation requests retain the callers’ five-second timeout, but acpmux permits longer pacing delays. Each request without limit costs a full list reservation; after two immediate pages, a third can legitimately wait 10–15 seconds. Such lists fail as BadList, refusing attachment instead of completing pagination. Account for server pacing and the outer client’s request deadline; test a delayed third page.

  2. [P2] [follow-up] agent_session_stream.rs:83: Child notifications are discarded while continuation pages load. ReaderSlot::hold drops notifications naming another session until the attachment becomes live. A child created between pages whose paging hash falls before the current cursor appears in no page, and its creation notification is discarded. The attachment consequently misses that child until another list or reconnect. Preserve and replay child changes received during pagination.

Source review completed. Rust tests could not run because this box has neither cargo nor rustc.

Follow-ups:

  • Allow paced continuation replies to complete within coordinated request deadlines.
  • Retain child-session changes received while assembling the watch list.

cmux-bot[bot]
cmux-bot Bot previously approved these changes Oct 31, 2026

@cmux-bot cmux-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmux-bot approves 17ee908: an independent review passed this exact head (next-review receipt by teamleaderleo). A push needs a new review; a later BLOCK at this head dismisses this approval.

@cmux-bot
cmux-bot Bot temporarily deployed to ci-routing-agent October 31, 2026 23:23 Inactive
@cmux-bot
cmux-bot Bot dismissed their stale review October 31, 2026 23:27

A newer verdict blocks b26524d (no independent SHIP at the head).

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (next-review patch-id; carried): SHIP at b26524d

The independent SHIP at 17ee908 carries to this head: the PR's own change (git diff $(git merge-base feat-cmux-next HEAD) HEAD) has the same git patch-id --verbatim (663c8265eb48be17) at both heads, and no merge between them was resolved by hand. Nothing new to review. A newer BLOCK, or any change to the PR's own diff, ends the carry.

@teamleaderleo
teamleaderleo merged commit 56778aa into feat-cmux-next Nov 1, 2026
231 of 234 checks passed
@teamleaderleo
teamleaderleo deleted the lane/acpmux-rust-clients-pages branch November 1, 2026 00:17

This branch was previously deployed

3 inactive deployments
artifacts — b26524df Deployed Oct 31, 2026 by cmux-bot[bot] via add the Windows daemon to the tree #92038
ci-routing-agent — b26524df Deployed Oct 31, 2026 by github-actions[bot] via cmux-next macOS placement #56164
sentry-dsyms — b26524df Deployed Oct 31, 2026 by cmux-bot[bot] via upload cmux-tui dSYMs to Sentry #92038
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