Repository navigation
A long chat is no longer read in full on every prompt - #11
Merged
Merged
Conversation
Three readers loaded every message and part of a session on each prompt: the prompt loop's history (MessageV2.stream, on every model step, before filterCompacted kept only what follows the newest compaction), prune after each turn, and the ACP usage update, which fetched the whole session over HTTP to sum its cost. On a chat with 65 MB of history a prompt peaked at 1.0-1.6 GB and took 4-6 s. - filterCompactedEffect pages newest first through MessageV2.scanNewestFirst and stops where filterCompacted stops; both run the same walk (compactedScanner). - prune walks through Session.scanNewestFirst and stops at the newest summary or the first cleared output, as its loop already did. - The usage update reads the newest 20 messages and sends no cost. ACP makes cost optional and DocuMentor reads only used and size. test/pg/bounded-history.test.ts holds the paged read to the full one for sessions without a compaction, with one, with a retained tail across a page boundary, with two, and with an unfinished summary, and counts the pages each reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0148RPMT9kUkZ6BL4TtebZJe
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 72 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
|
Hey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
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.
Every prompt read the whole session three times. On a long chat that dominated the opencode process's memory and time.
What changes
MessageV2.filterCompactedEffectpages newest first and stops at the newest compaction. Before,MessageV2.stream()loaded every message on each model step, andfilterCompactedthen threw most of them away. Upstream v1.19.3 has the same eager read. Both the paged read and the syncfilterCompactedrun one walk,compactedScanner, so they cannot drift apart.prunewalks through a newSession.scanNewestFirstand stops where its loop already stopped (newest summary, first cleared output), instead of loading the session first.usage_updatereads the newest 20 messages and sends nocost. The total needed every message over the in-process HTTP API on each prompt.costis optional in ACP, and DocuMentor reads onlyusedandsize(AcpChunkMapper.handleUsageUpdate).Measured
A compiled
--singlebuild, driven over ACP stdio the way DocuMentor'sStdioAgentClientdoes, against a fake OpenAI-compatible LLM and local Postgres 18. The synthetic chat has 2,979 messages and 68 MB of part JSON with a compaction near the end. Fresh process,session/resume, then 3 prompts, two runs each:The history changes alone, measured separately, took the peak from 1.04–1.64 GB to 0.58–0.69 GB, the same as a short chat. The rest comes from the models catalogue: the DocuMentor PR gives each chat process a catalogue cut to the model policy's providers, about 200 MB per process.
Tests
test/pg/bounded-history.test.ts(new) holds the paged read to the full read (filterCompacted(stream())) for five cases: no compaction, a compaction without a tail, a retained tail that crosses a page boundary, two compactions, and an unfinished summary. It counts theMessageV2.pagespans each reads, and checks thatscanNewestFirststops where its visitor stops.prunetests now exercise the paged walk.bun test test/session test/acp test/pggives 637 pass, 0 fail.Not in this PR
Expanding the models catalogue lazily inside
Providerwas tried and measured, then left out. It saved only 40–80 MB: 23 providers with built-in loaders still expand (2,546 models), and the core v2 catalogue (core/src/plugin/models-dev.ts) still writes all 9,142 models. A trimmedOPENCODE_MODELS_PATHshrinks all three consumers at once, so it lives in DocuMentor.🤖 Generated with Claude Code
https://claude.ai/code/session_0148RPMT9kUkZ6BL4TtebZJe