Repository navigation
Description
Summary
When automatic compaction occurs, opencode run --format json --thinking --auto emits internal compaction output as normal type: "text" JSONL events. This includes the compaction assistant summary and, in some cases, the synthetic user continuation prompt. JSONL consumers cannot distinguish these from user-visible assistant output.
Reproduction
- Create or resume a session close enough to the model context limit to trigger automatic compaction.
- Run:
opencode run --format json --thinking --auto --session <session-id>
- Capture stdout JSONL.
- After compaction, observe normal text events containing the compaction summary and possibly:
Continue if you have next steps, or stop and ask for clarification if you are unsure how to proceed.
Expected behavior
Ordinary text events should contain only final, user-visible assistant output. Internal compaction content should either be omitted, emitted as a distinct control/compaction event, or include enough owner-message metadata (role, summary, mode, agent) for consumers to filter it safely. In particular, synthetic user content must not be emitted as visible assistant text.
Actual behavior
The JSON runner outputs completed text parts based on part.type === "text" and part.time.end, without checking the owner message. Consequently, these internal parts are emitted as normal text, for example:
{"type":"text","part":{"type":"text","text":"<internal compaction summary>"}}
{"type":"text","part":{"type":"text","text":"Continue if you have next steps, or stop and ask for clarification if you are unsure how to proceed.","synthetic":true,"metadata":{"compaction_continue":true}}}This can expose compaction summaries that include serialized history, tool-call/tool-result transcripts, or other internal content. One downstream integration observed an erroneous 73,227-character assistant message containing 26 tool calls and 27 tool results.
Root-cause evidence
session/compaction.tscreates a compaction assistant message markedmode: "compaction",agent: "compaction", andsummary: true.- Its summary is persisted as an otherwise ordinary text part and is published to the live event stream.
cli/cmd/run.tssubscribes to that stream and emits completed text parts without inspecting their owner message.- After successful automatic compaction, the synthetic continuation user message can also be published; the same missing role/owner filtering allows it to be emitted as
text.
Filtering only part.synthetic would not fully fix this: compaction-summary text parts themselves do not carry that flag.
Environment
- OpenCode repository: current
devbranch as of 2026-08-13 - Command:
opencode run --format json --thinking --auto [--session <id>] - Plugins: none required
- OS: any (non-interactive JSON runner behavior)
A regression test could publish a completed compaction-summary assistant text part and a synthetic continuation user text part to the runner event loop, then assert neither is emitted as a normal text event.
Activity
github-actions commentedon Aug 13, 2026
This issue might be a duplicate of existing issues. Please check:
opencode run --format json. The two are related and a fix likely addresses both interfaces.dajiaohuang commentedon Aug 13, 2026
Current
devemits every completed text part fromrun --format jsonbefore resolving the owning message, while the compaction marker lives on that message rather than the part.For the JSONL contract, should the fix (a) suppress compaction-summary and synthetic-continuation text entirely, preserving the existing event schema, or (b) emit a distinct control/compaction event with owner metadata? I lean toward (a) because these parts are not user-visible assistant output and it avoids expanding the public stream schema, but the intended compatibility contract needs confirmation before implementation.
vladislav-miroshnikov commentedon Sep 9, 2026
@kitlangton #42316 hides compaction-owned parts and synthetic continuation text without changing the JSONL schema. I noticed that its guards also affect normal text output. Should this fix apply only to JSONL, or should both modes hide those internal messages?
Once that's settled, I can resolve the #43675 overlap while keeping descendant permission tracking and add a focused mocked-compaction output test.
dajiaohuang commentedon Sep 10, 2026
I recommend hiding compaction-owned parts and synthetic continuation prompts in both --format json and the default text mode. They are internal session mechanics, not user-visible assistant output; exposing them in plain text is the same leak with a less structured consumer. The shared event loop already has one owner-message filter, so applying it to both modes avoids divergent behavior without changing the JSONL schema. Please keep ordinary assistant text (and explicitly requested reasoning) unchanged, and add one default-text regression alongside the JSONL test.
neriousy commentedon Oct 19, 2026
In v2, compaction summaries are published as separate compaction events instead of assistant text, and
opencode runprints only assistant text in both the default and--format jsonoutput. Compaction summaries therefore no longer appear as ordinarytextevents, and no synthetic continuation prompt is added after compaction. To get v2:npm i -g @opencode/cli@latestorcurl -fsSL https://opencode.ai/v2/install | bash(desktop: update the app). If you still see this on v2, please open a new issue with the details.freshen(opencode-ci-harness): drop the compaction-as-text gap, it is …