Repository navigation
fix(provider): port upstream Bedrock unsigned reasoning filter (anomalyco/opencode#45769) - #1661
devin-ai-integration[bot] wants to merge 2 commits into
Conversation
…lyco/opencode#45769) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
dev-punia-altimate
left a comment
There was a problem hiding this comment.
🤖 Code Review — OpenCodeReview (Gemini) — 2 finding(s)
- 2 anchored to a line (posted inline when the comment stream is on)
- 0 without a line anchor
All findings (full text)
1. packages/opencode/src/provider/transform.ts (L144)
[🔵 LOW] According to the review checklist, avoid using the any type without providing an explanatory comment. If the exact type is unknown, consider using unknown (e.g., Record<string, unknown>), or add a comment explaining why any is necessary.
Suggested change:
const options = part.providerOptions as Record<string, unknown> | undefined
2. packages/opencode/src/provider/transform.ts (L146-L148)
[🔵 LOW] The review checklist strictly prohibits the use of non-strict equality operators (!=). Please replace != null with strict inequality checks (!== null and/or !== undefined).
Suggested change:
return (
(metadata?.signature !== undefined && metadata?.signature !== null) ||
(metadata?.redactedContent !== undefined && metadata?.redactedContent !== null) ||
(metadata?.redactedData !== undefined && metadata?.redactedData !== null)
)
| // The Bedrock SDK only replays signed or redacted reasoning. Unsigned reasoning must go | ||
| // before cache points are assigned, or it can leave an empty or cache-point-only message. | ||
| if (model.api.npm === "@ai-sdk/amazon-bedrock") { | ||
| const options = part.providerOptions as Record<string, any> | undefined |
There was a problem hiding this comment.
[🔵 LOW] According to the review checklist, avoid using the any type without providing an explanatory comment. If the exact type is unknown, consider using unknown (e.g., Record<string, unknown>), or add a comment explaining why any is necessary.
Suggested change:
| const options = part.providerOptions as Record<string, any> | undefined | |
| const options = part.providerOptions as Record<string, unknown> | undefined |
| return ( | ||
| metadata?.signature != null || metadata?.redactedContent != null || metadata?.redactedData != null | ||
| ) |
There was a problem hiding this comment.
[🔵 LOW] The review checklist strictly prohibits the use of non-strict equality operators (!=). Please replace != null with strict inequality checks (!== null and/or !== undefined).
Suggested change:
| return ( | |
| metadata?.signature != null || metadata?.redactedContent != null || metadata?.redactedData != null | |
| ) | |
| return ( | |
| (metadata?.signature !== undefined && metadata?.signature !== null) || | |
| (metadata?.redactedContent !== undefined && metadata?.redactedContent !== null) || | |
| (metadata?.redactedData !== undefined && metadata?.redactedData !== null) | |
| ) |
🤖 Code Review — OpenCodeReview (Gemini) — No Issues FoundNo supported files changed. |
Issue for this PR
Closes #1659
Type of change
What does this PR do?
Ports anomalyco/opencode#45769 (filter unreplayable Bedrock reasoning before caching).
@ai-sdk/amazon-bedrock(4.0.112 here) only replays reasoning that hassignatureorredactedData. It drops any other reasoning when it converts messages. The fork'snormalizeMessageskept Bedrock reasoning whenever its text was non-empty. Suppose an interrupted or unsigned turn leaves an assistant message with onlyPartial thoughtreasoning and an empty text part. That message survived the filter, andapplyCachingadded acachePointto it. The SDK then sent an assistant message with no content or only a cache point, Bedrock rejected the request, and the next turn in the session failed.On
@ai-sdk/amazon-bedrock, the filter now keeps only reasoning whose metadata hassignature,redactedContentorredactedData. It reads that metadata from the stored provider namespace (providerOptions[model.providerID], whichmessage()later remaps ontobedrock) and falls back tobedrock. Because this runs beforeapplyCaching, a message left empty is removed, not cached. Text and tool calls next to unsigned reasoning are kept. Behavior for@ai-sdk/anthropicis unchanged. The change is wrapped inaltimate_change ... upstream_fix:markers inside the existing fork block.How did you verify your code works?
packages/opencode/test/provider/transform.test.ts("Bedrock reasoning replay"). Two of them run the transformed messages throughcreateAmazonBedrockwith a mockedfetchand assert the exact Converse request body, with and without cache points. The others cover signed or redacted reasoning across thebedrock,amazon-bedrockand custom provider namespaces, the stored-namespace precedence, kept text and tool calls, and unchanged behavior for non-Bedrock providers. 11 of the new tests fail onmain. With this change, all 391 tests in the file pass.bun run typecheck(tsgo) inpackages/opencodepasses, and so does the pre-pushbun typecheck.bun run script/upstream/analyze.ts --markers --base origin/main --strict: ok.Cost side effects
None. This only removes message parts that the SDK already dropped.
Screenshots / recordings
Not a UI change.
Checklist
Tracked in #1478. Related Bedrock work: #1425 (stream decoding and cached-token billing; it doesn't touch
transform.ts).Written by Devin
Summary by cubic
Ports the upstream Bedrock unsigned reasoning filter so interrupted or unsigned reasoning no longer leaves empty or cache-only messages that Bedrock rejects.
@ai-sdk/amazon-bedrock; Anthropic behavior is unchanged.signature,redactedContent, orredactedDatais removed before cache points are assigned, so empty messages are dropped instead of cached.Written for commit d5f9469. Summary will update on new commits.