Skip to content

fix: read thinking_delta content from the thinking field - #2578

Merged
gavrissh merged 5 commits into
theagentrouter:mainfrom
llmctrl-io:fix/anthropic-thinking-delta
Sep 15, 2026
Merged

gavrissh merged 5 commits into
theagentrouter:mainfrom
llmctrl-io:fix/anthropic-thinking-delta

Conversation

@khalidDaoud

Copy link
Copy Markdown
Contributor

Description

text_delta and thinking_delta are separate variants of the SDK's
RawContentBlockDeltaUnion and carry their payload in different fields. The
Anthropic stream parser read .Text for both, so every extended thinking token
reached OpenAI clients as an empty string.

The union documents the split itself:

// This field is from variant [TextDelta].
Text string `json:"text"`
...
// This field is from variant [ThinkingDelta].
Thinking string `json:"thinking"`

thinking_delta now reads .Thinking. Everything else about the handling is
unchanged — thinking is still folded into delta.content alongside text.

Impact: the Anthropic-to-OpenAI streaming path, for any backend using this
parser (GCPAnthropic, AWSAnthropic), whenever the model streams extended
thinking. The response is well-formed and returns 200; the reasoning content is
just missing, which makes it easy to miss in testing.

Related Issues/PRs (if applicable)

None that I could find — happy to open an issue first if you would prefer that.

Special notes for reviewers (if applicable)

TestAnthropicStreamParser_ThinkingDelta drives a stream with one thinking
block (two deltas plus a signature_delta) followed by one text block, and
collects the non-empty delta.content values in order. Before the change it
collects only the text block's content:

expected: []string{"Let me work through it. ", "Two plus two is four.", "4"}
actual  : []string{"4"}

make precommit is clean and go test ./internal/translator/... -count=1
passes. make test has four pre-existing failures in internal/controller
(TestBackendSecurityPolicyController_{ReconcileOIDC_Fail,RotateCredential, RotateExpiredCredential,ExecutionRotation}) which reproduce unmodified on
main and are unrelated to this change.

Per the generative AI policy: this change was developed with AI assistance
(Claude). I have reviewed it, understand it, and can revise any part of it on
request.

text_delta and thinking_delta are separate variants of the SDK's
RawContentBlockDeltaUnion and carry their payload in different fields:
.Text is populated only for text_delta, .Thinking only for
thinking_delta. The parser read .Text for both, so every extended
thinking token reached OpenAI clients as an empty string.

The union documents this itself:

    // This field is from variant [TextDelta].
    Text string `json:"text"`
    // This field is from variant [ThinkingDelta].
    Thinking string `json:"thinking"`

Affects the Anthropic-to-OpenAI streaming path for any backend using
this parser (GCPAnthropic, AWSAnthropic) whenever the model streams
extended thinking.

TestAnthropicStreamParser_ThinkingDelta drives a stream with one
thinking block and one text block. Before the change it collects only
the text block's content; after it collects both thinking deltas in
order.

Signed-off-by: khaliddaoud <mohamed.khalid@gmail.com>
@khalidDaoud
khalidDaoud requested a review from a team as a code owner August 24, 2026 17:12
@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Aug 24, 2026
@gavrissh
gavrissh requested a review from a team as a code owner September 8, 2026 21:14

@gavrissh gavrissh 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.

Thanks for helping out with this change!

@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@netlify

netlify Bot commented Sep 10, 2026

Copy link
Copy Markdown

Deploy Preview for theagentrouter canceled.

Name Link
🔨 Latest commit b693b6a
🔍 Latest deploy log https://app.netlify.com/projects/theagentrouter/deploys/6aa93a5a1740920008bc36c7

@gavrissh

Copy link
Copy Markdown
Contributor

@khalidDaoud There are some Test failures. Could you check?

@gavrissh
gavrissh merged commit b4c644a into theagentrouter:main Sep 15, 2026
40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants