fix(core): fail content-filtered and outputless length settlements by clopca · Pull Request #47533 · anomalyco/opencode · GitHub
Skip to content

fix(core): fail content-filtered and outputless length settlements - #47533

Open
clopca wants to merge 1 commit into
anomalyco:v2from
clopca:length-settlement
Open

fix(core): fail content-filtered and outputless length settlements#47533
clopca wants to merge 1 commit into
anomalyco:v2from
clopca:length-settlement

Conversation

@clopca

@clopca clopca commented Sep 5, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #46596
Related: #40146

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Two settlement paths recorded provider failures as success:

  1. SessionGenerate.generate (backing POST /api/session/:id/generate) returned response.text regardless of the finish reason. A stream finishing content_filtered, or max_tokens with no text and no tool call, produced {"data":{"text":""}} with HTTP 200.
  2. In the runner, publish-llm-event.ts failed the assistant step on content-filter, but a step finishing length with reasoning-only output (no text, no tool call) settled as succeeded. The user saw an empty assistant message recorded as a successful turn. On Bedrock with adaptive thinking this is the common failure mode when the output budget is spent on reasoning.

Changes:

  • generate.ts: raise AIError(ContentPolicyError) on content-filter and AIError(InvalidProviderOutputError) on length with empty text and no tool calls, instead of returning empty text.
  • publish-llm-event.ts: track usefulOutput (any non-empty text delta/end or a tool call) separately from outputStarted. On finish-step with length and no useful output, fail the assistant with provider.invalid-output. Reasoning parts and rawFinish are still recorded, so the truncated reasoning remains available for diagnosis. Truncated responses that did produce partial text or a tool call keep settling as before, so no valid output is lost.

This is a re-submission of #46602, rebased on current v2 (the original was auto-closed by the compliance bot because the checklist section was missing). generate-node.ts was folded into generate.ts upstream in #46639, and #46937 removed the stepStreamed/stepFailed flags; the change is adapted to both.

How did you verify your code works?

  • packages/core/test/session-generate.test.ts: new case "fails transient generation when the provider filters or exhausts output before answering" covering both content-filter and reasoning-only length, asserting the typed AIError reason and that durable session state is untouched.
  • packages/core/test/session-runner-tool-events.test.ts: new case asserting a reasoning-only length step settles as provider.invalid-output while keeping the reasoning part, and that length with partial text still succeeds.
  • bun run test test/session-generate.test.ts test/session-runner-tool-events.test.ts in packages/core: 29 pass, 0 fail.
  • bun typecheck across the monorepo (33 packages) clean.

Screenshots / recordings

Not a UI change.

Checklist

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

Steps ending in content_filtered, or in max_tokens without any text or
tool call, settled as succeeded with empty output. Users saw blank
responses recorded as success, and the terminal filtered segment stayed
in history, causing subsequent generations on the session to return
empty text as well.

Session generate now raises ContentPolicyError on content-filter and
InvalidProviderOutputError on outputless length. The runner publisher
tracks useful output (text or tool call) separately from durable output:
reasoning-only length keeps its reasoning and rawFinish for diagnosis
but settles as provider.invalid-output, while truncated responses with
partial text remain successful.
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant