Skip to content

fix(core): label automatic continuations - #56310

Open
MuonChaser wants to merge 2 commits into
anomalyco:devfrom
MuonChaser:codex/mark-synthetic-resume
Open

MuonChaser wants to merge 2 commits into
anomalyco:devfrom
MuonChaser:codex/mark-synthetic-resume

Conversation

@MuonChaser

@MuonChaser MuonChaser commented Oct 17, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #56295

Type of change

  • Bug fix

What does this PR do?

Mark interrupted-stream and output-token-limit continuations with <system-reminder> and explicitly say they are automatic, not user input or approval. The existing continuation instruction and user role are retained.

The labels are added where those two messages are created. Synthetic text supplied by clients and plugins, including editor selections and attached resources, stays unchanged.

How did you verify your code works?

Bun 1.4.2, Node 24:

  • bun run check: lint and all 35 workspace typechecks passed.
  • From packages/core, the runner, message-mapping and instruction test files passed 10 consecutive runs: 2,650 passed on each of macOS and Linux.
  • The incomplete-stream regression fails on the original implementation. It checks serialized OpenAI Chat, Responses and Anthropic requests using TestLLM, rather than live model behavior. Ten runs also passed while the full core suite was running.
  • macOS full core suite: 6,625 passed, 43 skipped, 7 failed. All seven also reproduce on the unmodified implementation under Bash 3.2; the corresponding Linux shell tests passed (721 passed, 19 skipped).
  • Linux full-suite validation is incomplete: the host lacks ripgrep, has an older Git without init -b, and its existing service occupies OAuth callback port 8080. The affected-file and shell results above are from the final revision.

Screenshots / recordings

Request-payload regression coverage above applies to this logic change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

AI-assisted implementation and testing with OpenAI Codex.

Label model-visible synthetic context as automatically generated rather than
user input or approval. Preserve its existing message ID, user role and body,
and leave durable session history unchanged.

Extend the interrupted-stream regression to cover a pending approval request
and inspect the OpenAI Chat, Responses and Anthropic wire representations.
Update existing synthetic-message assertions for the added provenance text.

Fixes anomalyco#56295

Assisted-by: OpenAI Codex
Signed-off-by: MuonChaser <[email protected]>
Copilot AI balanced review requested due to automatic review settings October 17, 2026 04:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixes the reported case. With the issue's script and the simulated model, the continuation after an interrupted stream is now labelled as automatic; on the base branch it goes out as a plain user message. The three changed core test files pass and core typechecks.

Public API: no schema, route or event changes. Text sent through POST /api/session/:sessionID/synthetic and the plugin session.synthetic() now always reaches the model with this label. Calls still work; only the wording sent to the model changes.

Main concern: the label is added in toLLMMessage to every synthetic message, but not all of them come from OpenCode itself. The TUI sends the user's editor selection as a synthetic message (packages/tui/src/component/prompt/index.tsx:1344). ACP sends user-attached embedded resources the same way (packages/cli/src/acp/turn.ts:230). Sessions migrated from v1 also store synthetic messages. All of these would now reach the model as "not user input", which could make it give less weight to context the user chose to share. See the inline comment.

Related: #36682, #49042

Message.make({
id: message.id,
role: "user",
content: `[Automatically generated by OpenCode; not user input or approval]\n\n${message.text}`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds the label to every synthetic message, not only the ones OpenCode generates. The TUI sends the user's editor selection as a synthetic message (packages/tui/src/component/prompt/index.tsx:1344). ACP sends embedded resources the user attached the same way (packages/cli/src/acp/turn.ts:230). Sessions migrated from v1 also store synthetic messages. All of these would now go to the model as "not user input or approval", which is wrong for content the user supplied.

It would be safer to mark the messages where they are created: the CONTINUE_AFTER_INCOMPLETE_STREAM / CONTINUE_AFTER_OUTPUT_LIMIT continuations in runner/llm.ts, and possibly restart resume. For example, wrap them in <system-reminder>, as plugin/plan.ts already does. Another option is to label only messages carrying a source flag in their metadata. That way, synthetic text from clients and plugins reaches the model unchanged.

Mark interrupted-stream and output-limit continuations at their source. Preserve synthetic context supplied by clients and plugins.

Assisted-by: OpenAI Codex
Signed-off-by: MuonChaser <[email protected]>
@MuonChaser MuonChaser changed the title fix(core): mark synthetic context as automatic fix(core): label automatic continuations Oct 17, 2026

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

session: auto-continue after a stream interruption is delivered as an unmarked synthetic user message

2 participants