fix: collapse post-compaction messages when compaction drops the user prompt#205
Open
zhudatou630 wants to merge 1 commit into
Open
fix: collapse post-compaction messages when compaction drops the user prompt#205zhudatou630 wants to merge 1 commit into
zhudatou630 wants to merge 1 commit into
Conversation
… prompt When compaction fires mid-turn, pi replaces the compacted history (including the original user prompt) with a compaction summary and the agent keeps producing tool calls and a final answer with no user message left to anchor the turn. ChatWindow's message grouping only treated role==="user" as a turn anchor, so after such a compaction every subsequent tool call and assistant reply rendered standalone and never folded into a collapsed ProcessDetailsGroup — the whole post-compaction tail stayed expanded even after the run ended. Treat a compaction summary (role "custom", customType "compaction") as a group anchor too: it renders as the compaction block, the process messages after it fold into ProcessDetailsGroup, and the final assistant renders as the answer. Live-tail detection now uses the last anchor (user or compaction) instead of only the last user message, so a compaction summary that sits after the last user message still anchors the streaming segment.
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.
Problem
During a long agentic turn, auto-compaction can fire mid-turn. When it does, pi replaces the compacted history — including the original user prompt — with a compaction summary and the agent keeps producing tool calls and a final answer. There is no user message left to anchor the rest of the turn.
ChatWindow's message grouping only treatedrole === \"user\"as a turn anchor. After a mid-turn compaction, every subsequent tool call and assistant reply rendered standalone and never folded into a collapsedProcessDetailsGroup. The whole post-compaction tail stayed expanded even after the run ended — the auto-collapse that normally happens when a turn completes was lost.Repro
Real session data confirms it: a compaction entry whose
firstKeptEntryIdpoints at anassistantmessage, followed byassistant/toolResultentries with nousermessage after it. The loaded message list is[compaction(custom), assistant, toolResult, …], so the grouping loop never enters the user-anchored branch and renders everything standalone.Fix
Treat a compaction summary (
role: \"custom\",customType: \"compaction\") as a group anchor too:ProcessDetailsGroup(collapsed by default).Live-tail detection now uses the last anchor (user or compaction) instead of only the last user message, so a compaction summary that sits after the last user message still anchors the currently-streaming segment.
Verification
tsc --noEmit— no new errors in the touched file.standalone × N(nothing collapses).Scope
Single-file, ~26-line change in
components/ChatWindow.tsx. No behavior change for sessions without mid-turn compaction (lastAnchorIdx === lastUserIdxin the normal case).