Skip to content

fix(provider): port upstream Bedrock unsigned reasoning filter (anomalyco/opencode#45769) - #1661

Open
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1793814180-bedrock-unsigned-reasoning
Open

devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1793814180-bedrock-unsigned-reasoning

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #1659

Type of change

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

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 has signature or redactedData. It drops any other reasoning when it converts messages. The fork's normalizeMessages kept Bedrock reasoning whenever its text was non-empty. Suppose an interrupted or unsigned turn leaves an assistant message with only Partial thought reasoning and an empty text part. That message survived the filter, and applyCaching added a cachePoint to 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 has signature, redactedContent or redactedData. It reads that metadata from the stored provider namespace (providerOptions[model.providerID], which message() later remaps onto bedrock) and falls back to bedrock. Because this runs before applyCaching, a message left empty is removed, not cached. Text and tool calls next to unsigned reasoning are kept. Behavior for @ai-sdk/anthropic is unchanged. The change is wrapped in altimate_change ... upstream_fix: markers inside the existing fork block.

How did you verify your code works?

  • Ported the upstream tests to packages/opencode/test/provider/transform.test.ts ("Bedrock reasoning replay"). Two of them run the transformed messages through createAmazonBedrock with a mocked fetch and assert the exact Converse request body, with and without cache points. The others cover signed or redacted reasoning across the bedrock, amazon-bedrock and 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 on main. With this change, all 391 tests in the file pass.
  • bun run typecheck (tsgo) in packages/opencode passes, and so does the pre-push bun 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

  • I have tested my changes locally
  • I have not included unrelated changes in this PR
  • I checked for cost side effects (model calls, queries or cloud resources that grow with user data) and described them, or wrote "none"

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.

  • Applies only to @ai-sdk/amazon-bedrock; Anthropic behavior is unchanged.
  • Reasoning without signature, redactedContent, or redactedData is removed before cache points are assigned, so empty messages are dropped instead of cached.
  • Adds ported upstream tests covering signed/redacted reasoning, namespace precedence, and provider behavior.

Written for commit d5f9469. Summary will update on new commits.

View guided diff Turn on auto-fix

…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>
@coderabbitai

coderabbitai Bot commented Nov 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 20e48c87-9d26-46c7-a8e1-7c8788cde85f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@dev-punia-altimate dev-punia-altimate 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.

🤖 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

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.

[🔵 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:

Suggested change
const options = part.providerOptions as Record<string, any> | undefined
const options = part.providerOptions as Record<string, unknown> | undefined

Comment on lines +146 to +148
return (
metadata?.signature != null || metadata?.redactedContent != null || metadata?.redactedData != null
)

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.

[🔵 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:

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)
)

@dev-punia-altimate

Copy link
Copy Markdown
Contributor

🤖 Code Review — OpenCodeReview (Gemini) — No Issues Found

No supported files changed.

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.

Bedrock: unsigned reasoning leaves empty or cache-point-only assistant messages

1 participant