feat(mirror): opt-in chunking for long inter-agent mirrors (MIRROR_CHUNKS)#213
feat(mirror): opt-in chunking for long inter-agent mirrors (MIRROR_CHUNKS)#213A-MO7SEN wants to merge 1 commit into
Conversation
lodar
left a comment
There was a problem hiding this comment.
Reviewed. The shape is right and I want this — opt-in, MIRROR_CHUNKS=1 reproduces the current behaviour byte-for-byte, and the flood ceiling stays bounded at max_chunks * max_chars rather than becoming unbounded, which is the thing that would have made me say no. Also apologies: CI never ran on this because first-time-contributor workflow approval was sitting unactioned. Approved now, and on #197 too.
One real defect, in the label rather than the chunking:
(( _idx > 1 )) && _label="${to_label} (cont. ${_idx}/${max_chunks})"The denominator is the configured ceiling, not the number of chunks this body actually produces. With MIRROR_CHUNKS=5 and a 1000-char body at max_chars=800, the reader sees (cont. 2/5) and waits for three more messages that will never arrive. Worse in the group, where mirrors from several agents interleave — "2/5" is a promise that the next three messages in the topic are continuations of this one.
Since the total is knowable before the loop:
local _total=${#trimmed}
local _need=$(( (_total + max_chars - 1) / max_chars ))
(( _need > max_chunks )) && _need=$max_chunksthen label against _need. _need is also the cleaner loop bound — _idx <= _need says "as many chunks as this body needs, capped" directly, where _off < _total && _idx <= max_chunks makes the reader derive it.
Two smaller things, neither blocking:
- The overflow arm
(( _idx == max_chunks && _off < _total ))is correct but only because_idxcan't exceedmax_chunks; with_needit becomes_idx == _need, which is the same test stated as itself. ${trimmed:$_off:$max_chars}counts characters, so under a multibyte locale a chunk can exceed Telegram's byte limit at the boundary. Not a regression — the existing crop has the same property — so I'd leave it, but the comment claiming a bounded ceiling is a byte claim resting on a character count. Worth a word in the comment rather than a code change.
No test in the diff. mirror_interagent_outbound posts through _mirror_post, so a fixture that captures the posted bodies and asserts chunk count + label + the crop counter on the last chunk would be cheap, and the label bug above is exactly what it would have caught. Happy to take the PR with a test added; if you'd rather not, say so and I'll write it — I'm not going to make a correct contribution wait on our harness conventions.
This will need a rebase on top of current main — it conflicts on the generated 5dive bundle, which our merge queue serialises (our problem, tracked as DIVE-2091, not yours). Rebuild with ./build.sh rather than resolving the bundle by hand; git will happily auto-merge that artifact into something no build produced.
|
Heads-up so you don't chase this: GitHub now shows this as conflicting again. That's the committed Don't rebase just to clear the red. Push whatever you're doing on the review notes, and I'll rebuild the bundle against whatever |
…UNKS) A long agent send/ask mirror crops at MIRROR_MAX_BODY_CHARS (default 800) with a '(+N chars)' tail — right for flood control, but an operator watching a team coordinate loses the middle of every substantive message. MIRROR_CHUNKS=<n> lets a long mirror span up to n messages (each up to MIRROR_MAX_BODY_CHARS, chunks 2..n labelled 'cont. i/n'); overflow past the last chunk still crops with the counter, so the ceiling stays bounded at n*max_chars. Default 1 — byte-identical to today unless opted in. Running live on my box with MIRROR_CHUNKS=6 and a five-agent team. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Rebased this onto current Why it was conflicting, and why that was our problem rather than yours: the only file that actually conflicted was Worth saying explicitly: the 47k-line bundle auto-merges without conflict, which is worse than conflicting. That would produce an artifact no build ever created. So the correct resolution is always to rebuild from We have a ticket open to stop making contributors hit this at all (DIVE-2091). Until it lands, ping me or just leave it — rebasing this class of conflict is ours to do. Checks should re-run automatically. Thanks for the contribution. |
Watching my five-agent team coordinate in the group, every substantive inter-agent message gets cropped at 800 chars — the interesting part is always in the '(+N chars)' I can't see. Bumping MIRROR_MAX_BODY_CHARS helps until 4096; past that there's no option at all.
This adds
MIRROR_CHUNKS=<n>: a long mirror may span up to n messages (chunks labelled 'cont. i/n'), and only what overflows the last chunk gets cropped with the counter. Flood control survives — the ceiling is just n×max_chars instead of max_chars. Default is 1, byte-identical to current behavior; nobody sees a change unless they opt in.Running live on my box with
MIRROR_CHUNKS=6via a systemd drop-in. Independent of #197 — same file, different function, happy to rebase whichever lands second.🤖 Generated with Claude Code