fix(tui): show a visible marker where /rebuild inserted a context boundary - #1940
Closed
wqymi wants to merge 1 commit into
Closed
fix(tui): show a visible marker where /rebuild inserted a context boundary#1940wqymi wants to merge 1 commit into
wqymi wants to merge 1 commit into
Conversation
…ndary A `/rebuild` inserts one user message whose parts are a `checkpoint` part plus `synthetic: true` text parts. The TUI's PART_MAPPING only covers text/tool/reasoning, and UserMessage only renders when a non-synthetic text part exists — so the whole boundary message rendered as nothing and the user had no way to tell that a rebuild happened, or where. Compaction, by contrast, leaves a visible summary assistant message behind, so the boundary is at least locatable there. Render the checkpoint part as a one-line marker row, using the same badge row pattern already used for cron fires and actor notifications. No rebuild or compaction logic changes.
Collaborator
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The UX gap
After a manual
/rebuild, the TUI shows nothing. The user cannot tell that a rebuild happened, and cannot tell where the context boundary is.checkpoint.insertRebuildBoundary(src/session/checkpoint.ts:1444-1490) inserts exactly onerole: "user"message whose parts are:{ type: "checkpoint", coveredUpTo, ... }part{ type: "text", synthetic: true }parts (the rendered context + index + actor registry)Neither renders in the TUI:
PART_MAPPINGinsrc/cli/cmd/tui/routes/session/index.tsx:1845-1849only mapstext,tool,reasoning— acheckpointpart falls through<Show when={component()}>and renders nothing.UserMessageonly draws its bubble when a non-synthetic text part exists (index.tsx:1513, gated atindex.tsx:1615), so all the synthetic context text is hidden too.Net effect: the whole boundary message renders as zero rows.
Compaction is locatable by comparison, because
SessionCompaction.processCompactionwrites a real assistant message (agent: "compaction",summary: true,src/session/compaction.ts:341-346) whose text part renders normally — you see the summary block sitting in the transcript. Rebuild has no equivalent: its summary lives insidesynthetic: trueuser text parts, which are never displayed.(
filterCompacted,src/session/message-v2.ts:1029, breaks the context slice on either part type, so both are equally real boundaries — only one of them was visible.)The fix
Render the
checkpointpart as a one-line marker row inUserMessage, reusing the badge-row pattern the TUI already uses for cron fires and actor notifications (samebox marginTop/paddingLeft={2}, samebackgroundElementbadge + muted trailing text):Placed inline at the boundary message's position, so it marks where the rebuild happened, not just that it happened.
New i18n keys (
en/zh/zht; other locales fall back to English via thebasemerge incontext/language.tsx:18):tui.session.rebuild_boundary.label—context rebuilt/上下文已重建/上下文已重建tui.session.rebuild_boundary.detail—earlier messages summarized/较早消息已摘要/較早訊息已摘要No rebuild or compaction logic is touched — this is purely making an already-existing boundary visible.
Note on consistency
The web/share renderer (
packages/ui) does have a dedicated divider:PART_MAPPING["compaction"]→MessageDivider label={i18n.t("ui.messagePart.compaction")}(packages/ui/src/components/message-part.tsx:1325-1328), andsession-turn.tsx:233already treats acheckpointpart as a divider trigger. The TUI has no compaction divider at all — compaction is only visible there via its summary message. This PR does not add a TUI compaction divider (out of scope); the new marker follows the TUI's own inline badge-row language rather than importing the web divider.Verification
bun typecheck(packages/opencode) — exit 0bun test test/cli/cmd/tui/— 68 pass / 0 failbun test test/session/checkpoint-rebuild-unify.test.ts— 3 pass / 0 fail (this already pins the invariant the marker keys off:expect(boundary.parts.some((p) => p.type === "checkpoint")).toBe(true)at line 168)test/cli/cmd/tui/rebuild-boundary-marker.test.tspins the marker copy in en/zh/zht and asserts zh/zht are actually translated rather than silently falling back to English. There is no render/snapshot harness for TUI message parts (the existing TUI tests all cover pure helpers), so there was no compaction-marker snapshot test to mirror.To see it live: open a TUI session with some history, run
/rebuild, and the marker row appears inline at the point the boundary was inserted.