Repository navigation
acpmux: move a chat to another daemon with its history, queue and draft (acpmux.transfer.v1, cx-xtg0.6) - #19359
Conversation
…and draft (cx-xtg0.6) Red: acpmux has no transfer protocol. Two daemons; the test moves a chat between them through _acpmux/transfer_*: each queued prompt runs once, on the target; the source runs nothing once the move began, takes no prompt while it moves, and an aborted move gives the chat back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd draft (cx-xtg0.6) acpmux.transfer.v1: any client moves a chat between two daemons (a sibling build's, or a remote machine's) through _acpmux/transfer_*, so neither daemon needs to reach the other. - Source transfer_begin freezes the chat (no prompt, no queued start; a running turn refuses the move unless interrupt), makes its bundle and answers the manifest; transfer_read pages it. - Target transfer_receive / transfer_write / transfer_finish import it, in another folder path if given, and run its queue there at once. - Source transfer_commit withdraws the queue, clears the draft and closes the chat; transfer_abort gives it back. - The move is in the log, so a restart keeps the chat frozen: each queued prompt runs once, on one daemon. - Local socket and peers only. acpmux transfer SESSION --to SOCKET is the reference client. The summary says moving. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…x-xtg0.6) Review: - A prompt that waited for the turn lock as the move began runs nowhere. - The queue (edit, send now, remove) and the draft are refused while the chat moves. - Only the local socket moves a chat; a remote daemon will take one through its own guarded entry. - The moved queue is back before the chat is visible on the target, so no new prompt runs ahead of it. - The reference client commits when a lost finish answer had landed, and aborts only when the target lacks the chat. - A move carries at most 4 GiB in 10,000 files; moves left a day are swept. - A chat that moved away can come back; a read never reaches a receive. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-xtg0.6) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e (cx-xtg0.6) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The reference client commits a move whose finish answer was lost only when the target logged transferred_in with this transfer id; a chat with the same id there may be another copy (its queue would be lost). - A chat that moved away is known from its transferred record, so it can come back after a restart too; its closed copy gives way only once the chat's folder is there. - A chat being moved takes no steer, and a queued prompt sent now waits instead of steering; its policy cannot change; an abort after the commit is refused. - begin refuses a move while a turn recovered from an agent host runs. - A receive's pages keep it from the sweep; reads refuse IN- as in-. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…steering/chat-transfer # Conflicts: # cmux-tui/crates/acpmux/src/hub/queue.rs
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
Summary
An agent chat could not move between daemons.
_acpmux/export/importonly wrote and read bundle directories on one disk. Import never made the queue live, and nothing retired the source, so a queued prompt could run on both daemons or on neither.This adds acpmux.transfer.v1: any client moves a chat from one acpmux daemon to another, carrying its history, queue (held state included), draft and agent store. The other daemon can be a sibling build's (tagged builds each run their own daemon) or a remote machine's. The client pumps the bundle, so neither daemon needs to reach the other. This is the base for the Swift
session.transferchat slice (cx-xtg0.7) and for Move to Cloud.Source
_acpmux/transfer_begin {sessionId, interrupt?}:transfer.busy) unlessinterruptstops it.{schema, transferId, sessionId, files:[{path,size}], session}._acpmux/transfer_read {transferId, path, offset, limit≤4 MiB}: returns{data (base64), next, eof}._acpmux/transfer_commit {sessionId, transferId, to?}: withdraws the queue (it runs on the target), clears the draft and closes the chat._acpmux/transfer_abort {sessionId, transferId}: gives the chat back as it was.Target
_acpmux/transfer_receive {manifest}: returns{receiveId}. Refused withtransfer.exists(that chat is here) ortransfer.harness(agent not configured here). A chat that moved away from here can come back._acpmux/transfer_write {receiveId, path, offset, data}: pages, in order._acpmux/transfer_finish {receiveId, cwd?, name?, from?}:cwdif its folder has another path here;transferred_in {transferId}and answers the session summary.Exactly once: the move is in the log (
transfer_out,transfer_aborted,transferred). A daemon that restarts mid-move keeps the chat frozen until commit or abort. A client aborts only when the target lacks the move. If a finish answer is lost, the client commits only when the target's log hastransferred_inwith this transfer id.Reference client:
acpmux transfer SESSION --to SOCKET [--cwd] [--name] [--interrupt].Limits:
moving, andinitializefeatures gainsessionTransfer.closes cx-xtg0.6
Testing
tests/hub_integration/transfer.rsruns two in-process daemons with the fake agent; the test is the client that moves the chat.interrupt, and refuses a prompt, a queue edit and a draft change. An aborted move gives it back: its queue runs and it takes prompts again.cmux-tui-rust-check.sh test transfer::(fleet)cmux-tui-rust-check.sh all transfer(fleet: fmt, clippy, tests)cmux-remote interactive_echo_stays_responsive_during_bidirectional_bulk_transfer, which the filter also matches; it is unrelated and failed the same way on another worker.test draft(fleet)test queue(fleet)chatmux-relay writer_queue_preserves_complete_fifo_lines, unrelated and seen on base runs beforeTwo review subagents read this (correctness and security); their findings are fixed above. Notable ones:
God-file check: no file over budget grew.
requests.rshas two one-line changes;hub_integration.rsis unchanged in length.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Adds
acpmux.transfer.v1, letting any client move a chat from one acpmux daemon to another—carrying its history, queue (including held prompts), draft, and agent store. The client pumps the bundle between the two daemons, so neither needs to reach the other.Closes cx-xtg0.6.
Key points
transfer_beginfreezes the chat; a running turn refuses the move unlessinterruptis set.transfer_read/transfer_writepage the bundle;transfer_finishimports it with its queue live.transfer_commitwithdraws the queue and closes the source;transfer_abortgives the chat back.acpmux transfer SESSION --to SOCKETis the reference client.Written for commit be4fd57. Summary will update on new commits.