Description
select in packages/core/src/session/compaction.ts partitions the conversation into head (the text summarized during auto-compaction) and recent (kept verbatim) at a token budget. When the budget boundary lands mid-message, that message is split into a prefix (head) and suffix (recent).
The split branch sets split = index + 1, and split is then used as both the end of head's full-message slice and the start of recent's slice:
head = [...conversation.slice(0, split), splitPrefix] → slice(0, index + 1) includes the full boundary message, then splitPrefix (a truncated copy of that same message) is appended. The boundary message appears twice in head.
recent = [splitSuffix, ...conversation.slice(split)] → correct.
head is the exact text fed to the summarizer, so whenever the keep-budget boundary lands mid-message (common for a large tool result) the boundary message is sent to the summarizer twice — full and truncated. This wastes input tokens on every overflow-triggered compaction, can push the summary prompt past the context limit so compaction silently fails to recover from overflow, and feeds the summarizer a self-contradictory full-vs-truncated copy.
Steps to reproduce
- Have a conversation where the keep-budget boundary falls in the middle of a message (e.g. a large tool result).
- Trigger auto-compaction.
- The summarizer input (head) contains the boundary message in full AND its truncated prefix — duplicated.
Operating System
macOS
Description
selectinpackages/core/src/session/compaction.tspartitions the conversation intohead(the text summarized during auto-compaction) andrecent(kept verbatim) at a token budget. When the budget boundary lands mid-message, that message is split into a prefix (head) and suffix (recent).The split branch sets
split = index + 1, andsplitis then used as both the end of head's full-message slice and the start of recent's slice:head = [...conversation.slice(0, split), splitPrefix]→slice(0, index + 1)includes the full boundary message, thensplitPrefix(a truncated copy of that same message) is appended. The boundary message appears twice in head.recent = [splitSuffix, ...conversation.slice(split)]→ correct.headis the exact text fed to the summarizer, so whenever the keep-budget boundary lands mid-message (common for a large tool result) the boundary message is sent to the summarizer twice — full and truncated. This wastes input tokens on every overflow-triggered compaction, can push the summary prompt past the context limit so compaction silently fails to recover from overflow, and feeds the summarizer a self-contradictory full-vs-truncated copy.Steps to reproduce
Operating System
macOS