Skip to content

refactor(providers): migrate anthropic to the official @anthropic-ai/sdk - #1075

Merged
murdore merged 1 commit into
releasefrom
refactor/migrate-anthropic-native
Jun 7, 2026
Merged

murdore merged 1 commit into
releasefrom
refactor/migrate-anthropic-native

Conversation

@murdore

@murdore murdore commented Jun 7, 2026 •

Copy link
Copy Markdown
Contributor

What & why

Migrates anthropic off @ai-sdk/anthropic + streamText onto the official @anthropic-ai/sdk (Messages API) — removing the last @ai-sdk provider-package import from the providers tree. Also deletes the dead anthropicBaseProvider.ts (AnthropicProviderV2: no registry entry, no runtime importers — only stale audit-list mentions).

This was scoped first (full inventory of the 1,296-line provider + the official-SDK mapping); the OAuth/tier machinery ports verbatim by construction — only the client construction and the two generation paths change.

Design

Auth (preserved verbatim): OAuth detection/tiers (~/.neurolink credentials, ANTHROPIC_OAUTH_TOKEN, scope-based tier detection + model downgrade), token refresh, beta headers, and the proven createOAuthFetch wrapper (current-token getter, UA spoofing, ?beta=true) now wrap the official client. API-key path: new Anthropic({ apiKey, defaultHeaders, baseURL, fetch: proxyFetch }).

ANTHROPIC_BASE_URL inversion: the official SDK appends /v1 itself — the opposite of @ai-sdk/anthropic, which required a version-suffixed base. A trailing /vN is now stripped (with a debug note), so both historical env forms keep working.

generate(): getAISDKModel() returns a V3 delegating adapter over messages.create — BaseProvider.generate + middleware + GenerationHandler work unchanged. Thinking blocks → V3 reasoning parts (result.reasoning/reasoningTokens); cache_read/cache_creation tokens → V3 cache usage (Langfuse cost dashboards keep cache metrics); json responseFormat emulated with the same forced-tool strategy @ai-sdk/anthropic used.

executeStream(): native Messages streaming loop —

  • text_delta → content chunks; thinking_delta → the reasoning chunk channel (from feat(providers): surface reasoning_content natively in the SSE client + base #1073); signature_delta captured so thinking blocks replay correctly when tool use continues a turn (API requirement);
  • tool_use accumulation → execution → tool_result user turn → loop to maxSteps;
  • OTel span keeps the neurolink.provider.streamText name (dashboard continuity); tool:end emission + tool-execution storage match the old onStepFinish hooks; NoOutput sentinel + capturedProviderError wiring match the cohort — the test:context 6.x sentinel audits now point at providers/anthropic and the patterns are verified present in the built output.

Public API preserved: getAuthHeaders, validateModelAccess, usage/auth/tier getters, refreshAuthIfNeeded, getLastResponseMetadata, the anthropicModels re-exports, ANTHROPIC_BETA_HEADERS. The rule-violating export defaults are removed (named exports only; nothing imported them).

Build note

@anthropic-ai/sdk's beta webhooks module imports the optional standardwebhooks package — stubbed in the browser bundle (server-only webhook verification), following the build script's existing npm-stub pattern.

@ai-sdk/anthropic stays in package.json solely for the browser entry's createAnthropic re-export, until the planned breaking browser-surface removal later in this series.

Validation

  • pnpm run check (svelte-check + tsc --strict) — pass, 0 errors
  • lint + format — pass (0 errors)
  • pnpm run build + publint — pass ("All good!")
  • stream-span audit — 106/106 (anthropic passes the typed-errors sweep)
  • sse-client suite — 14/14
  • dist audit greps (stampNoOutputSpan, capturedProviderError = error, buildNoOutputSentinel) — all present in dist/lib/providers/anthropic.js

Single commit, per the repo's single-commit policy.

Summary by CodeRabbit

  • New Features

    • Integrated official Anthropic SDK for enhanced Anthropic provider capabilities, including improved support for images, tool calls, and system prompts.
    • Added OAuth authentication support for Anthropic provider.
  • Chores

    • Updated provider implementation and test references.

Copilot AI review requested due to automatic review settings June 7, 2026 20:39
@vercel

vercel Bot commented Jun 7, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
neurolink Ready Ready Preview, Comment Jun 7, 2026 8:59pm

@coderabbitai

coderabbitai Bot commented Jun 7, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@murdore, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 54 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d53e6b83-5b33-4a22-ab26-3be19439306c

📥 Commits

Reviewing files that changed from the base of the PR and between 9eb573e and f66769a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • package.json
  • scripts/build-browser.mjs
  • src/lib/providers/anthropic.ts
  • src/lib/providers/anthropicBaseProvider.ts
  • src/lib/utils/noOutputSentinel.ts
  • test/continuous-test-suite-context.ts
  • test/continuous-test-suite-stream-span.ts
📝 Walkthrough

Walkthrough

This PR migrates the Anthropic provider from @ai-sdk/anthropic to the official @anthropic-ai/sdk client. Changes include adding the new SDK dependency, implementing native conversion utilities for the Messages API, restructuring OAuth and API-key initialization, replacing getAISDKModel with a delegating model implementation, and rewriting executeStream for native streaming with multi-step tool execution. The deprecated anthropicBaseProvider.ts is removed and all test references updated accordingly.

Changes

Anthropic SDK Migration

Layer / File(s) Summary
Dependency and build setup
package.json, scripts/build-browser.mjs
Add @anthropic-ai/sdk ^0.102.0 dependency. Stub standardwebhooks in browser build and export Webhook from proxy module.
SDK imports and conversion utility contracts
src/lib/providers/anthropic.ts
Update imports to use official @anthropic-ai/sdk. Add utility imports for timeout, no-output sentinel, and tool processing. Define native conversion helpers for Anthropic Messages API: image blocks, tool results, system/message mapping, tool schema/choice, and stop-reason mapping with ANTHROPIC_DEFAULT_MAX_TOKENS.
Constructor OAuth and API-key initialization
src/lib/providers/anthropic.ts
Update constructor to initialize SDK client separately for OAuth vs API-key modes. OAuth mode uses placeholder apiKey and delegates auth to oauthFetch. API-key mode normalizes ANTHROPIC_BASE_URL by stripping /vN suffix, then creates client with proxy fetch and default headers.
getAISDKModel delegating implementation
src/lib/providers/anthropic.ts
Replace getAISDKModel to return V3 LanguageModel that maps V3 prompt/messages/tools/responseFormat/thinking into Anthropic Messages params and calls client.messages.create directly. Emulate JSON format via synthetic tool. Convert response content back to V3 format (text, reasoning, tool calls) with finishReason and cache-aware token usage. Throw on doStream.
executeStream native streaming with multi-step tool loop
src/lib/providers/anthropic.ts
Rewrite executeStream to use SDK streaming Events API with multi-step tool execution: merge abort signals, build payload once, stream while accumulating thinking/text/tool_use, replay assistant turn, execute tools, emit tool-end events, persist storage, append tool_result turn, and repeat until no tool_use or max steps. Wrap in OTel span, defer analytics/cost, preserve no-output sentinel and error handling. Update getModel() to return this.getAISDKModel().
Test and reference cleanup
src/lib/utils/noOutputSentinel.ts, test/continuous-test-suite-context.ts, test/continuous-test-suite-stream-span.ts
Update comment and three provider references from anthropicBaseProvider to anthropic in NoOutput sentinel regression tests. Remove filter exclusion of anthropicBaseProvider.ts to include file in provider error convention audit. File src/lib/providers/anthropicBaseProvider.ts (315 lines) is deleted.

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

released

Suggested reviewers

  • Tara-ag
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main change: migrating the Anthropic provider to the official @anthropic-ai/sdk library, which aligns perfectly with the changeset's primary objective.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/migrate-anthropic-native

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 7, 2026 •

Copy link
Copy Markdown
Contributor

✅ Single Commit Policy - COMPLIANT

Status: Policy requirements met • 1 commit • Valid format • Ready for merge

📊 View validation details

📝 Commit Details

  • Hash: f66769a134c159c0dbb38899bd48a25a05504a69
  • Message: refactor(providers): migrate anthropic to the official @anthropic-ai/sdk
  • Author: Sachin Sharma

✅ Validation Results

  • Single commit requirement met
  • No merge commits in branch
  • Semantic commit message format verified
  • Ready for squash merge to release branch

🤖 Automated validation by NeuroLink Single Commit Enforcement

@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/lib/providers/anthropic.ts (1)

477-482: 💤 Low value

Empty string fallback for toolCallId and toolName may cause API errors.

Anthropic's API requires valid id and name fields for tool_use blocks. If the source data has undefined values, passing empty strings could result in API validation errors or unexpected behavior. Consider logging a warning when these fields are missing.

🛡️ Proposed defensive handling
           } else if (p?.type === "tool-call") {
             let input: unknown = p.input;
             if (typeof input === "string") {
               try {
                 input = JSON.parse(input);
               } catch {
                 input = {};
               }
             }
+            const toolCallId = p.toolCallId ?? "";
+            const toolName = p.toolName ?? "";
+            if (!toolCallId || !toolName) {
+              logger.warn("[messagesToAnthropic] tool-call missing id or name", {
+                hasToolCallId: !!p.toolCallId,
+                hasToolName: !!p.toolName,
+              });
+            }
             blocks.push({
               type: "tool_use",
-              id: p.toolCallId ?? "",
-              name: p.toolName ?? "",
+              id: toolCallId,
+              name: toolName,
               input: input ?? {},
             });
           }
🤖 Prompt for 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.

In `@src/lib/providers/anthropic.ts` around lines 477 - 482, The current
blocks.push call creates a "tool_use" block with empty-string fallbacks for
p.toolCallId and p.toolName which can trigger Anthropic validation errors;
update the logic around the push in the function handling p (the code that
builds the blocks array and references p.toolCallId/p.toolName/input) to
validate that p.toolCallId and p.toolName are present and non-empty before
adding the block, and if either is missing log a warning (use the existing
logger) and skip adding the "tool_use" block (or alternatively surface an error)
so you never send empty id/name to the API.
🤖 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.

Nitpick comments:
In `@src/lib/providers/anthropic.ts`:
- Around line 477-482: The current blocks.push call creates a "tool_use" block
with empty-string fallbacks for p.toolCallId and p.toolName which can trigger
Anthropic validation errors; update the logic around the push in the function
handling p (the code that builds the blocks array and references
p.toolCallId/p.toolName/input) to validate that p.toolCallId and p.toolName are
present and non-empty before adding the block, and if either is missing log a
warning (use the existing logger) and skip adding the "tool_use" block (or
alternatively surface an error) so you never send empty id/name to the API.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1291a576-0817-4c7a-9cb7-836885e006f4

📥 Commits

Reviewing files that changed from the base of the PR and between 1fb8950 and 9eb573e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • package.json
  • scripts/build-browser.mjs
  • src/lib/providers/anthropic.ts
  • src/lib/providers/anthropicBaseProvider.ts
  • src/lib/utils/noOutputSentinel.ts
  • test/continuous-test-suite-context.ts
  • test/continuous-test-suite-stream-span.ts
💤 Files with no reviewable changes (1)
  • src/lib/providers/anthropicBaseProvider.ts

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Migrates the Anthropic provider implementation from @ai-sdk/anthropic/streamText to the official @anthropic-ai/sdk (Messages API), removes the unused anthropicBaseProvider.ts, and updates associated audits/build tooling to reflect the new provider surface.

Changes:

  • Replaces Anthropic client construction and generation/streaming paths to use the official @anthropic-ai/sdk Messages API directly.
  • Deletes the dead src/lib/providers/anthropicBaseProvider.ts and updates continuous test-suite wiring/audits to point at providers/anthropic.
  • Adds @anthropic-ai/sdk to dependencies and stubs standardwebhooks for the browser bundle build.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
test/continuous-test-suite-stream-span.ts Updates provider error audit target list after removing anthropicBaseProvider.
test/continuous-test-suite-context.ts Updates “all providers wired” / span-stamping / error-capture audit targets to providers/anthropic.
src/lib/utils/noOutputSentinel.ts Updates documentation references from anthropicBaseProvider to anthropic.
src/lib/providers/anthropicBaseProvider.ts Deleted unused provider implementation.
src/lib/providers/anthropic.ts Main migration to official Anthropic SDK; adds Messages API conversions, V3 delegating model for generate(), and native streaming/tool loop.
scripts/build-browser.mjs Stubs standardwebhooks (optional peer) and exposes Webhook in the proxy stub exports.
pnpm-lock.yaml Locks @anthropic-ai/sdk@0.102.0 and its new transitive deps.
package.json Adds @anthropic-ai/sdk dependency.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +427 to +441
const p = part as {
type?: string;
text?: string;
image?: unknown;
data?: unknown;
url?: unknown;
};
if (p?.type === "text" && typeof p.text === "string") {
blocks.push({ type: "text", text: p.text });
} else if (p?.type === "image" || p?.type === "image_url") {
const img = toAnthropicImageBlock(p.image ?? p.data ?? p.url);
if (img) {
blocks.push(img);
}
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed real — MessageBuilder marks system messages (and GenerationHandler the last tool definition) with providerOptions.anthropic.cacheControl, so dropping them silently disabled prompt caching. Fixed in f66769a: a cacheControlOf helper now honors the contract everywhere — system messages (block-form system emitted only when breakpoints exist, plain string otherwise for wire-compat), per-part AND message-level on user/assistant blocks (message-level applies to the last block, the AI-SDK convention), and tool definitions on both the V3 doGenerate path and the stream path.

Comment on lines +457 to +467
const p = part as {
type?: string;
text?: string;
toolCallId?: string;
toolName?: string;
input?: unknown;
};
if (p?.type === "text" && typeof p.text === "string") {
if (p.text.length > 0) {
blocks.push({ type: "text", text: p.text });
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in f66769a — assistant text parts now carry their per-part cache_control, and message-level cacheControl is applied to the message's last block (same as the user path).

@Tara-ag Tara-ag 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.

Review Complete: Approve with Minor Suggestion

Summary

Successfully reviewed the migration of Anthropic provider from @ai-sdk/anthropic to the official @anthropic-ai/sdk. This is a substantial refactor (+994/-548 lines) that removes the last @ai-sdk provider-package import from the providers tree.

Issues Found: 1 Minor

Severity Count Description
🔒 CRITICAL 0 None
⚠️ MAJOR 0 None
💡 MINOR 1 Debug log at line ~760 logs ANTHROPIC_BASE_URL without credential redaction
💬 SUGGESTION 0 None

Verification Against CLAUDE.md Rules

Rule Status Notes
Rule 1 (dynamic imports) ✅ N/A Provider file - registry handles dynamic imports
Rule 3 (Gemini tools+JSON) ✅ N/A Anthropic provider
Rule 4 (CLI≠SDK) ✅ Pass No CLI concerns leaked
Rule 5 (backward compat) ✅ Pass Public API preserved per PR description
Rule 6 (formatProviderError returns) ✅ Pass Correctly returns typed errors, never throws
Rules 7-13 ✅ Pass Enforced by ESLint/CI

Key Positive Findings

  1. Proper Error Handling: formatProviderError correctly maps SDK errors to typed errors (NetworkError, AuthenticationError, RateLimitError, ProviderError) and returns them rather than throwing.

  2. Streaming Architecture: executeStream correctly uses the BaseProvider tool-merge pattern - receives pre-merged tools via options.tools and converts them for the native SDK.

  3. No-Output Sentinel: Correctly implements buildNoOutputSentinel, stampNoOutputSpan, and capturedProviderError wiring per the test audit requirements (verified in dist audit).

  4. Browser Build: Properly stubs standardwebhooks (optional peer dep from SDK's beta webhooks module) for browser bundles.

  5. BASE_URL Handling: Correctly inverts the version suffix handling - strips /vN since the official SDK appends /v1 itself, maintaining backward compatibility with both historical env var forms.

Recommended Follow-up

Consider using redactUrlCredentials() from ../utils/logSanitize.js when logging ANTHROPIC_BASE_URL in debug statements (line ~760) to align with the pattern used by other providers (OpenAI, Groq, Ollama, etc.). This is a defensive practice, not a blocking issue.

Decision

APPROVE - The migration is well-architected, preserves backward compatibility, and follows all critical project rules. The one minor issue identified is non-blocking and can be addressed in a follow-up if desired.

// a version-suffixed base URL — the form the previous @ai-sdk/anthropic
// implementation REQUIRED (`https://api.anthropic.com/v1`) — would
// double up as `/v1/v1/messages`. Normalize the inverse way now: strip
// a trailing `/vN` segment when present so both historical forms of

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.

💡 MINOR: Credential exposure in debug log

The debug log at line 760 logs baseURL directly without redacting potential credentials:

logger.debug(
  "[AnthropicProvider] Stripping the version suffix from " +
    "ANTHROPIC_BASE_URL — the official Anthropic SDK appends /v1 " +
    "to the base URL itself.",
  { baseURL: raw, rewrittenTo: stripped },  // <-- raw URL may contain credentials
);

Risk: If ANTHROPIC_BASE_URL contains credentials (e.g., https://user:pass@proxy.example.com), they will appear in debug logs.

Suggestion: Import and use redactUrlCredentials from ../utils/logSanitize.js (already used by other providers like OpenAI, Groq, etc.):

import { redactUrlCredentials } from "../utils/logSanitize.js";

// Then in the log:
logger.debug(
  "[AnthropicProvider] Stripping the version suffix from ANTHROPIC_BASE_URL...",
  { baseURL: redactUrlCredentials(raw), rewrittenTo: redactUrlCredentials(stripped) },
);

This aligns with the pattern established in other providers (see openAI.ts, groq.ts, ollama.ts, etc.).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in f66769a — both fields of that debug log now go through redactUrlCredentials (the shared helper from #1068).

} as unknown as LanguageModel;
}

protected formatProviderError(error: unknown): Error {

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.

✅ Verified: formatProviderError correctly returns errors

The implementation correctly follows CLAUDE.md Critical Rule 6: formatProviderError returns typed errors rather than throwing them. The method properly maps:

  • TimeoutError → NetworkError
  • API_KEY_INVALID / Invalid API key → AuthenticationError
  • Rate limit patterns → RateLimitError
  • Network errors (ECONNRESET, ENOTFOUND, etc.) → NetworkError
  • Server errors (5xx) → ProviderError

The error messages appropriately reference "configured credentials" rather than specific env vars (consistent with bootstrapped standards). Good practice.

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.

Review Summary for anthropic.ts

✅ Positive Findings

  1. CLAUDE.md Rule 6 Compliance: formatProviderError correctly returns typed errors rather than throwing them. Properly maps to NetworkError, AuthenticationError, RateLimitError, and ProviderError.

  2. Streaming Tool-Merge Contract: The executeStream implementation correctly uses pre-merged tools from BaseProvider.stream() via options.tools, maintaining the tool-merge contract.

  3. No-Output Sentinel Pattern: Correctly implements buildNoOutputSentinel, stampNoOutputSpan, and capturedProviderError wiring per the test audit requirements.

  4. Backward Compatibility: Public API preserved (getAuthHeaders, validateModelAccess, usage/auth/tier getters, refreshAuthIfNeeded, etc.).

⚠️ Minor Issues

  1. Credential Exposure in Debug Log (line ~760): The debug log when stripping version suffix from ANTHROPIC_BASE_URL logs the raw URL without redacting potential credentials. Should use redactUrlCredentials() from ../utils/logSanitize.js (pattern used by other providers like OpenAI, Groq, etc.).

Overall Assessment

Well-architected migration that removes the @ai-sdk/anthropic dependency while preserving all existing functionality. The native SDK integration follows established patterns in the codebase.

Comment thread scripts/build-browser.mjs
'which','pdf-to-img','express-rate-limit','@hono/node-server','powershell-utils',
'wsl-utils','default-browser','default-browser-id','run-applescript','open',
'@langfuse/langfuse','undici','bullmq','croner','ioredis',
// Optional peer of @anthropic-ai/sdk's beta webhooks module (server-only

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.

✅ Verified: Browser stub for standardwebhooks

Correctly adds standardwebhooks to the npm stubs list for the browser bundle. This is the proper approach for handling the optional peer dependency from @anthropic-ai/sdk's beta webhooks module (server-only webhook signature verification) that would otherwise fail in browser builds.

The comment explaining why this is needed is helpful for future maintainers.

Replace the @ai-sdk/anthropic + streamText runtime with the official
@anthropic-ai/sdk Messages API. anthropic.ts now drives
client.messages.create directly on both paths; the dead AnthropicProviderV2
(anthropicBaseProvider.ts — no registry entry, no runtime importers) is
deleted. This removes the last @ai-sdk provider-package import from the
providers tree.

Faithful migration — all behavior preserved:

- Auth machinery untouched by construction: OAuth detection/tiers
  (~/.neurolink credentials, ANTHROPIC_OAUTH_TOKEN, scope-based tier
  detection, model downgrade per tier), token refresh, beta headers, and the
  proven createOAuthFetch wrapper (Bearer auth via current-token getter, UA
  spoofing, ?beta=true) now wrap the official client.
- ANTHROPIC_BASE_URL normalization is inverted to match the new SDK: the
  official client appends /v1 itself, so a version-suffixed base URL (the
  form @ai-sdk/anthropic REQUIRED) gets its trailing /vN stripped — both
  historical env forms keep working.
- generate(): getAISDKModel() returns a V3 delegating adapter over
  messages.create, so BaseProvider.generate + middleware + GenerationHandler
  keep working unchanged. Thinking blocks map to V3 reasoning parts
  (result.reasoning / reasoningTokens), cache_read/cache_creation tokens map
  to V3 cache usage, and json responseFormat is emulated with the same
  forced-tool strategy @ai-sdk/anthropic used.
- executeStream(): native Messages streaming loop — text_delta → content
  chunks, thinking_delta → the reasoning chunk channel (from #1073),
  signature_delta captured so thinking blocks replay correctly when tool use
  continues a turn, tool_use accumulation → execution → tool_result user
  turn, up to maxSteps. OTel span keeps the neurolink.provider.streamText
  name for dashboard continuity; tool:end emission + tool-execution storage
  match the old onStepFinish hooks; NoOutput sentinel + capturedProviderError
  wiring match the cohort (and the test:context 6.x audits, which now point
  at providers/anthropic).
- formatProviderError taxonomy unchanged (typed errors only).
- Public API preserved: getAuthHeaders, validateModelAccess, getUsageInfo,
  subscription/auth getters, refreshAuthIfNeeded, getLastResponseMetadata,
  the anthropicModels re-exports, and ANTHROPIC_BETA_HEADERS. The
  rule-violating `export default` declarations are removed (named exports
  only; nothing imported the defaults).

Build: @anthropic-ai/sdk's beta webhooks module imports the optional
standardwebhooks package — stubbed in the browser bundle (server-only
webhook verification, irrelevant in the browser).

The @ai-sdk/anthropic dependency is retained solely for the browser entry's
createAnthropic re-export until the planned breaking browser-surface removal.
@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@Tara-ag Tara-ag 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.

Review Summary

This PR successfully migrates the Anthropic provider from @ai-sdk/anthropic to the official @anthropic-ai/sdk.

✅ Approved - No Blocking Issues

Architecture Compliance:

  • CLAUDE.md Rule 1: Dynamic imports only in registry ✓
  • CLAUDE.md Rule 6: formatProviderError returns errors (never throws) ✓
  • Tool-merge contract respected via BaseProvider.stream() ✓
  • No-output sentinel patterns correctly implemented ✓

Security:

  • No hardcoded secrets or credentials ✓
  • URL credentials properly redacted in logs using redactUrlCredentials() ✓

Backward Compatibility:

  • Public API preserved (getAuthHeaders, validateModelAccess, refreshAuthIfNeeded, etc.) ✓
  • Named exports only (removed rule-violating export default) ✓

Code Quality:

  • Dead code (anthropicBaseProvider.ts) correctly removed ✓
  • Shared utilities properly imported from openaiChatCompletionsClient.ts ✓
  • Cache control preservation fixed per reviewer feedback ✓

Build & Tests:

  • Browser stub correctly added for standardwebhooks ✓
  • Test references updated from anthropicBaseProvider to anthropic ✓

All previously raised review comments have been addressed. The migration follows established patterns in the codebase and maintains dashboard continuity through consistent OTel span naming.

@murdore
murdore merged commit 3aa1553 into release Jun 7, 2026
17 checks passed
@murdore
murdore deleted the refactor/migrate-anthropic-native branch June 7, 2026 21:09
@github-actions

github-actions Bot commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 9.69.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

This branch was successfully deployed

1 active deployment
Preview — f66769a1 Deployed Jun 7, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants