acpmux: name a sent prompt's pasted blocks (user_message.pasted)
The composer sends each paste as its own ACP text block marked _meta: {"cmux": {"pasted": true}}, but the daemon dropped the marker, so a sent message couldn't show a collapsed "Pasted text · N lines" chip. A prompt's user_message now has pasted: [{start, end}], one entry for each pasted block, as UTF-16 code-unit offsets into text. A client can read a paste with text.slice(start, end). The key is left out when nothing was pasted.
prompt_textis now built onprompt_text_parts: one walk that joins the non-context text blocks with "\n" (as before, with no trimming) and records the pasted ranges. The text and the ranges can't drift apart.append_promptaddspasted, so it covers both turns and steers. So do thequeuedrecord andqueue_edit'squeue_updatedrecord.pastedis added only when the record'stextis exactly the text the ranges were computed from.cmux-tui/crates/acpmux/docs/acpmux-schema.jsondocumentspastedonuser_messageandqueued. It also documentsuser_message.images, which was missing. The webviews copy (handoff/schema/acpmux-schema.json) is a sha-pinned snapshot of #16930 (seepin.jsonandschema.test.ts), so I left it alone.user_messageisn't in the protocol IR (spec/acpmux-protocol.json), so the codegen doesn't change either.
Changelog
none
Red and green
Command: cmux-ci run --class isolated --script scripts/ci/cmux-tui-rust-check.sh --arg test --arg pasted --ref <sha>
- Test commit 5ec342e58ac0fc7b9ad98c25d9b9b6ff66682c9b (step 95dc39dd39b5f2eb4fb28465): red.
a_prompts_pasted_blocks_are_named_by_their_utf16_range_in_its_textanda_queued_prompts_pasted_blocks_are_named_while_it_waits_and_once_it_runsfail withpasted= Null.a_prompt_with_nothing_pasted_names_no_pasted_rangepasses. - Fix commit 4623497cd4e8674ca2ebff47d82f3e06871e85d4 (step 85f35c44d43eb6610b52d417): green. 4 tests run, 4 passed (the three above and an unrelated
image_pastetest that matches the filter).
The UTF-16 test puts 👀 (a non-BMP character, two UTF-16 units) and accented letters before and inside the pastes, then checks each range with a UTF-16 slice.
Observed / Not run
- Observed: the fleet red and green runs above;
python3 scripts/cmux-next/prepush-gate.py(no new violations);rustfmt --checkon the changed files. - Not run: the full cmux-tui test suite, clippy, and
bun run check(no webviews file changed). CI covers these.
Agent session: cosmic-gray
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Names pasted text blocks on a sent prompt's user_message (and on queued records) as UTF-16 {start, end} ranges of the recorded text, so the chat can fold each into a "Pasted text · N lines" chip.
- The composer sends each paste as its own ACP text block marked
_meta.cmux.pasted; previously the daemon dropped that marker, so sent messages couldn't show pastes. prompt_textis now derived from a singleprompt_text_partswalk that joins the text blocks and records each paste's range, so the ranges can never drift from the text.pastedis added touser_message(turns and steers), thequeuedrecord, andqueue_edit'squeue_updatedrecord, only when something was pasted and the record's text matches the computed text.acpmux-schema.jsondocumentspastedonuser_messageandqueued, and also documents the previously missingimagesfield onuser_message. The webviews copy and protocol IR are untouched.