Skip to content

feat: migrate anthropic provider to AI SDK#11275

Draft
daniel-lxs wants to merge 1 commit intomainfrom
feat/anthropic-ai-sdk-migration
Draft

feat: migrate anthropic provider to AI SDK#11275
daniel-lxs wants to merge 1 commit intomainfrom
feat/anthropic-ai-sdk-migration

Conversation

@daniel-lxs
Copy link
Member

@daniel-lxs daniel-lxs commented Feb 6, 2026

Summary

Migrates the Anthropic provider (src/api/providers/anthropic.ts) from using the raw @anthropic-ai/sdk to @ai-sdk/anthropic with the Vercel AI SDK, following the same pattern already used by Gemini and Vertex providers.

Key Changes

New Files

  • src/api/transform/caching/ai-sdk-anthropic.ts — Cache breakpoint utility that adds providerOptions.anthropic.cacheControl to AI SDK messages
  • src/api/transform/caching/__tests__/ai-sdk-anthropic.spec.ts — Tests for the cache utility

Modified Files

  • src/package.json — Added @ai-sdk/anthropic dependency
  • src/api/providers/anthropic.ts — Full rewrite from raw SDK to AI SDK pattern:
    • Uses createAnthropic() + streamText()/generateText() from the AI SDK
    • Cache breakpoints via post-processing utility (consistent with existing caching/ directory pattern)
    • System prompt caching with providerOptions.anthropic.cacheControl
    • Thinking config mapped from budget_tokensbudgetTokens (snake_case → camelCase)
    • All beta headers passed manually via headers option
    • Fixes thought signature capture — previously not implemented (noted at old line 308)
    • Adds redacted thinking support via getRedactedThinkingBlocks()
    • Cache write tokens from providerMetadata.anthropic.cacheCreationInputTokens
  • src/api/transform/ai-sdk.ts — Enhanced processAiSdkStreamPart to handle reasoning-end with signatures; convertToAiSdkMessages preserves thinking block signatures and redacted_thinking
  • src/api/providers/__tests__/anthropic.spec.ts — Full rewrite: 33 tests
  • src/api/transform/__tests__/ai-sdk.spec.ts — Updated for thinking/signature handling

Testing

  • 33 tests passing in anthropic.spec.ts
  • 60 tests passing in ai-sdk.spec.ts
  • 8 tests passing in ai-sdk-anthropic.spec.ts
  • All existing provider tests unaffected

Migration Pattern

Follows the established AI SDK migration pattern from Gemini/Vertex:

  1. Convert Anthropic messages → AI SDK ModelMessage[] via convertToAiSdkMessages()
  2. Post-process with cache breakpoints via addAiSdkAnthropicCacheBreakpoints()
  3. Stream via streamText()result.fullStreamprocessAiSdkStreamPart()
  4. Capture reasoning/signatures from result.reasoning after stream completes

Important

Migrates Anthropic provider to AI SDK, adding cache and reasoning support, with extensive testing.

  • Behavior:
    • Migrates anthropic.ts to use @ai-sdk/anthropic and ai for message processing.
    • Implements cache breakpoints for Anthropic models in ai-sdk-anthropic.ts.
    • Handles reasoning and tool call stream parts in ai-sdk.ts.
  • Testing:
    • Adds ai-sdk-anthropic.spec.ts for cache utility tests.
    • Updates anthropic.spec.ts with 33 tests for new SDK behavior.
    • Updates ai-sdk.spec.ts for reasoning and signature handling.
  • Dependencies:
    • Adds @ai-sdk/anthropic to package.json.

This description was created by Ellipsis for 8356162. You can customize this summary. It will automatically update as commits are pushed.

@roomote
Copy link
Contributor

roomote bot commented Feb 6, 2026

Rooviewer Clock   See task

Reviewed the Anthropic AI SDK migration. One issue flagged:

  • Bearer auth token mode sends an empty x-api-key header alongside Authorization: Bearer, which may break custom backends that validate x-api-key (comment)

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

Comment on lines +67 to 78
const useAuthToken = !!(this.options.anthropicBaseUrl && this.options.anthropicUseAuthToken)

this.client = new Anthropic({
const headers: Record<string, string> = { ...DEFAULT_HEADERS }
if (useAuthToken && this.options.apiKey) {
headers["Authorization"] = `Bearer ${this.options.apiKey}`
}

this.provider = createAnthropic({
apiKey: useAuthToken ? "" : (this.options.apiKey ?? "not-provided"),
baseURL: this.options.anthropicBaseUrl || undefined,
[apiKeyFieldName]: this.options.apiKey,
headers,
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When useAuthToken is true, setting apiKey: "" causes @ai-sdk/anthropic to send an x-api-key: "" header on every request, alongside the Authorization: Bearer header added here. The old code used the Anthropic SDK's authToken constructor option, which sent only the Authorization: Bearer header and never set x-api-key. Custom Anthropic-compatible backends that validate x-api-key for non-empty values will reject these requests. This only affects users with a custom anthropicBaseUrl who also enable anthropicUseAuthToken. One possible workaround is to pass apiKey: undefined (if the AI SDK accepts it) or to strip x-api-key from outgoing requests via a custom fetch wrapper.

Fix it with Roo Code or mention @roomote and request a fix.

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.

1 participant