Skip to content

opencode run --format json emits auto-compaction internals as ordinary text events #42238

Description

@AmAzing129

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

  1. Create or resume a session close enough to the model context limit to trigger automatic compaction.
  2. Run:
    opencode run --format json --thinking --auto --session <session-id>
  3. Capture stdout JSONL.
  4. 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.ts creates a compaction assistant message marked mode: "compaction", agent: "compaction", and summary: true.
  • Its summary is persisted as an otherwise ordinary text part and is published to the live event stream.
  • cli/cmd/run.ts subscribes 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 dev branch 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions