keep pricing objects in anthropic path for ai-sdk compatibility - #5886
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughAnthropic and Bedrock streaming responses now always include ChangesMessage-start usage emission
DeepSeek test handler validation
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/providers/anthropic/messagestartusage_test.go`:
- Around line 85-90: Extend the serialized-frame assertions in the message start
usage test alongside the existing inputTokens checks: read
message.usage.output_tokens, verify it is a gjson.Number, and assert its value
is zero so omitted output_tokens fails the test.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: befd93a1-14ec-4d6b-9e2b-951079442cfe
📒 Files selected for processing (4)
core/providers/anthropic/messagestartusage_test.gocore/providers/anthropic/responses.gocore/providers/bedrock/invoke.gocore/providers/bedrock/invoke_test.go
c710223 to
534271b
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/providers/deepseek/anthropic_test.go`:
- Around line 54-70: Synchronize all six httptest handlers in
core/providers/deepseek/anthropic_test.go at lines 54-70, 104-121, 165-175,
227-237, 289-295, and 329-338 with their test goroutines: remove direct t.Fatalf
calls and unsynchronized access to captured or capturedPath, send validation
errors and captured values through buffered channels, then perform assertions in
the test goroutine.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 851696df-1928-405d-927d-8489f69c3dc0
📒 Files selected for processing (5)
core/providers/anthropic/messagestartusage_test.gocore/providers/anthropic/responses.gocore/providers/bedrock/invoke.gocore/providers/bedrock/invoke_test.gocore/providers/deepseek/anthropic_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
- core/providers/bedrock/invoke.go
- core/providers/anthropic/responses.go
- core/providers/bedrock/invoke_test.go
- core/providers/anthropic/messagestartusage_test.go
534271b to
f86fb1e
Compare
7192207 to
cf642b7
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
cf642b7 to
a906f5c
Compare
f86fb1e to
071106e
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
a906f5c to
fa93a62
Compare
071106e to
947280d
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
fa93a62 to
647b82b
Compare
947280d to
3d9fd15
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
647b82b to
ce5a846
Compare
3d9fd15 to
25b850d
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
Merge activity
|
The base branch was changed.
## Summary Fixes #5885. `@ai-sdk/anthropic` (versions 4.0.6–4.0.32) marks `message.usage` and `message.usage.input_tokens` as required fields in its `message_start` schema, while `id`, `model`, and `role` are nullable. When Bifrost omitted the `usage` key entirely on `message_start` frames — which happened for every non-Anthropic provider, including Bedrock Converse, because usage figures aren't available until the terminal event — the SDK aborted the stream before the first token reached the client. The fix emits an all-zero `usage` object on `message_start` when no real figures are available. Zeros are chosen over Anthropic's own `output_tokens: 1` placeholder because Bedrock's `message_delta` carries absolute totals rather than cumulative deltas; a client summing both frames would over-count by one. Zero is neutral under both interpretations, and Bifrost's passthrough accumulator uses max-merge, so a zero can never displace a real figure later in the stream. ## Changes - `responses.go`: The `else` branch that previously left `messageUsage` nil now populates an all-zero `AnthropicUsage` struct, ensuring the `usage` key is always present on the wire regardless of `omitempty`. - `invoke.go`: `message_start` frames built for the Bedrock `/invoke-with-response-stream` path now include a `usage` map with zero placeholders by default. When `resp.Response.Usage` is non-nil, real figures replace the zeros and cache token fields are conditionally included. - Tests updated to assert that `usage` is present and zero when unknown, and that real figures are preferred when available. A second test marshals the struct to raw JSON and validates the wire representation directly, since the original `omitempty` bug was invisible to struct-level nil checks. ## Type of change - [x] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [ ] Transports (HTTP) - [x] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [ ] Docs ## How to test ```sh go test ./core/providers/anthropic/... ./core/providers/bedrock/... ``` Validate that streaming through a Bedrock-backed model with an `@ai-sdk/anthropic` client no longer aborts on the first frame. The `message_start` event should contain `message.usage.input_tokens = 0` and `message.usage.output_tokens = 0`, with authoritative totals arriving on `message_delta`. ## Breaking changes - [x] No ## Related issues Closes #5885 See also #5821 (the prior fix that introduced the omission) ## Security considerations None. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [ ] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable
…mhq#5886) ## Summary Fixes maximhq#5885. `@ai-sdk/anthropic` (versions 4.0.6–4.0.32) marks `message.usage` and `message.usage.input_tokens` as required fields in its `message_start` schema, while `id`, `model`, and `role` are nullable. When Bifrost omitted the `usage` key entirely on `message_start` frames — which happened for every non-Anthropic provider, including Bedrock Converse, because usage figures aren't available until the terminal event — the SDK aborted the stream before the first token reached the client. The fix emits an all-zero `usage` object on `message_start` when no real figures are available. Zeros are chosen over Anthropic's own `output_tokens: 1` placeholder because Bedrock's `message_delta` carries absolute totals rather than cumulative deltas; a client summing both frames would over-count by one. Zero is neutral under both interpretations, and Bifrost's passthrough accumulator uses max-merge, so a zero can never displace a real figure later in the stream. ## Changes - `responses.go`: The `else` branch that previously left `messageUsage` nil now populates an all-zero `AnthropicUsage` struct, ensuring the `usage` key is always present on the wire regardless of `omitempty`. - `invoke.go`: `message_start` frames built for the Bedrock `/invoke-with-response-stream` path now include a `usage` map with zero placeholders by default. When `resp.Response.Usage` is non-nil, real figures replace the zeros and cache token fields are conditionally included. - Tests updated to assert that `usage` is present and zero when unknown, and that real figures are preferred when available. A second test marshals the struct to raw JSON and validates the wire representation directly, since the original `omitempty` bug was invisible to struct-level nil checks. ## Type of change - [x] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [ ] Transports (HTTP) - [x] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [ ] Docs ## How to test ```sh go test ./core/providers/anthropic/... ./core/providers/bedrock/... ``` Validate that streaming through a Bedrock-backed model with an `@ai-sdk/anthropic` client no longer aborts on the first frame. The `message_start` event should contain `message.usage.input_tokens = 0` and `message.usage.output_tokens = 0`, with authoritative totals arriving on `message_delta`. ## Breaking changes - [x] No ## Related issues Closes maximhq#5885 See also maximhq#5821 (the prior fix that introduced the omission) ## Security considerations None. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [ ] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable

Summary
Fixes #5885.
@ai-sdk/anthropic(versions 4.0.6–4.0.32) marksmessage.usageandmessage.usage.input_tokensas required fields in itsmessage_startschema, whileid,model, androleare nullable. When Bifrost omitted theusagekey entirely onmessage_startframes — which happened for every non-Anthropic provider, including Bedrock Converse, because usage figures aren't available until the terminal event — the SDK aborted the stream before the first token reached the client.The fix emits an all-zero
usageobject onmessage_startwhen no real figures are available. Zeros are chosen over Anthropic's ownoutput_tokens: 1placeholder because Bedrock'smessage_deltacarries absolute totals rather than cumulative deltas; a client summing both frames would over-count by one. Zero is neutral under both interpretations, and Bifrost's passthrough accumulator uses max-merge, so a zero can never displace a real figure later in the stream.Changes
responses.go: Theelsebranch that previously leftmessageUsagenil now populates an all-zeroAnthropicUsagestruct, ensuring theusagekey is always present on the wire regardless ofomitempty.invoke.go:message_startframes built for the Bedrock/invoke-with-response-streampath now include ausagemap with zero placeholders by default. Whenresp.Response.Usageis non-nil, real figures replace the zeros and cache token fields are conditionally included.usageis present and zero when unknown, and that real figures are preferred when available. A second test marshals the struct to raw JSON and validates the wire representation directly, since the originalomitemptybug was invisible to struct-level nil checks.Type of change
Affected areas
How to test
go test ./core/providers/anthropic/... ./core/providers/bedrock/...Validate that streaming through a Bedrock-backed model with an
@ai-sdk/anthropicclient no longer aborts on the first frame. Themessage_startevent should containmessage.usage.input_tokens = 0andmessage.usage.output_tokens = 0, with authoritative totals arriving onmessage_delta.Breaking changes
Related issues
Closes #5885
See also #5821 (the prior fix that introduced the omission)
Security considerations
None.
Checklist
docs/contributing/README.mdand followed the guidelines