fix: route anthropic through OpenAI-compat endpoint (+ extract shared helper) - #216
Conversation
… helper) Anthropic's native plugin reads a per-agent sqlite auth store that ClawBox's file auth profile doesn't populate, so chats fail with ProviderAuthError 'No API key found' at call time (missing-provider-auth) on 2026.6.8 — the same class as google. Route anthropic through Anthropic's OpenAI-compatible endpoint (api.anthropic.com/v1) with the key inline, like google/openrouter. Now that there are three openai-compat providers, extract the shared writeOpenAICompatProvider() helper (CodeRabbit/simplify flagged the duplication on ID-Robots#215) and refactor openrouter + google to use it. chat/model auto-extend gates on a shared OPENAI_COMPAT_PROVIDERS set (openrouter, google, anthropic). openai-direct (API-key) has the same root cause but is intentionally NOT rerouted here: it's untested (Codex/oauth is the common path) and its native responses/reasoning behavior could degrade under a plain openai-completions shim — a separate follow-up if anyone hits it. Verified on device: api.anthropic.com/v1/chat/completions returns 200 for claude-opus-4-8 with the key; the rerouted provider resolves + runs.
|
Warning Review limit reached
More reviews will be available in 38 minutes and 24 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughAnthropic is added as an OpenAI-compatible provider. A shared ChangesAnthropic OpenAI-compat provider wiring
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/app/setup-api/chat/model/route.ts (1)
361-372:⚠️ Potential issue | 🟠 Major | ⚡ Quick winDo not auto-create partial OpenAI-compatible provider definitions.
When a legacy or failed setup has an auth profile but no complete
models.providers.${providerId}entry, this path writes only.models. For Anthropic, that omits thebaseUrl,api: "openai-completions", and inlineapiKeyrequired by the reroute, so the primary can switch back onto a broken/incomplete provider. Return a clear re-save error instead of mutating a partial provider definition.As per coding guidelines,
src/app/**/route.tshandlers should ensure proper input validation, HTTP status codes, and error responses.Proposed guard for incomplete provider definitions
const providerDef = openclawConfig.models?.providers?.[providerId] as - | { models?: { id?: string; name?: string }[] } + | { + api?: string; + baseUrl?: string; + apiKey?: string; + models?: { id?: string; name?: string }[]; + } | undefined; - const existingModels = providerDef?.models ?? []; + if ( + !providerDef || + providerDef.api !== "openai-completions" || + typeof providerDef.baseUrl !== "string" || + providerDef.baseUrl.length === 0 || + typeof providerDef.apiKey !== "string" || + providerDef.apiKey.length === 0 || + !Array.isArray(providerDef.models) + ) { + return NextResponse.json( + { + error: `${labelForProvider(providerId, providerId)} must be re-saved in Settings before switching to ${requestedModel}.`, + }, + { status: 409 }, + ); + } + const existingModels = providerDef.models; const configuredIds = existingModels .map((m) => m?.id) .filter((id): id is string => typeof id === "string" && id.length > 0);🤖 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/app/setup-api/chat/model/route.ts` around lines 361 - 372, When handling model configuration in this route handler, add validation before appending models to detect incomplete provider definitions. Before the conditional check with configuredIds.includes(parsed.modelId), verify that the providerDef contains all required fields for a complete provider definition (such as baseUrl, api configuration, and apiKey for OpenAI-compatible or Anthropic providers). If the providerDef exists but is incomplete, return a clear error response with an appropriate HTTP status code instead of allowing the code to proceed with writing only partial provider configuration. This prevents mutating incomplete provider definitions that would break subsequent operations.Source: Coding guidelines
🤖 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 `@src/tests/routes/ai-models/configure.test.ts`:
- Around line 806-827: Add a new test case to cover user-selected non-curated
Anthropic models. The current test only verifies the default model behavior.
Create an additional test that calls configurePost with a custom Anthropic model
parameter (not the default curated one) to exercise the extractProviderModelId
path in writeOpenAICompatProvider(). This test should verify that custom Claude
model IDs are properly handled and prevent regressions where a non-registered
custom model could be incorrectly set as the primary model in
models.providers.anthropic.models.
---
Outside diff comments:
In `@src/app/setup-api/chat/model/route.ts`:
- Around line 361-372: When handling model configuration in this route handler,
add validation before appending models to detect incomplete provider
definitions. Before the conditional check with
configuredIds.includes(parsed.modelId), verify that the providerDef contains all
required fields for a complete provider definition (such as baseUrl, api
configuration, and apiKey for OpenAI-compatible or Anthropic providers). If the
providerDef exists but is incomplete, return a clear error response with an
appropriate HTTP status code instead of allowing the code to proceed with
writing only partial provider configuration. This prevents mutating incomplete
provider definitions that would break subsequent operations.
🪄 Autofix (Beta)
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: ASSERTIVE
Plan: Pro
Run ID: dfafbf70-0227-4852-8eef-a3df6492f405
📒 Files selected for processing (3)
src/app/setup-api/ai-models/configure/route.tssrc/app/setup-api/chat/model/route.tssrc/tests/routes/ai-models/configure.test.ts
Address CodeRabbit review on ID-Robots#216: - chat/model auto-extend: if models.providers.<p> exists without an inline apiKey (legacy/partial state), appending only .models leaves an openai-compat provider that can't authenticate. Return 409 'Re-save in Settings' instead of switching the primary onto a broken provider. - configure test: cover a user-picked non-curated model (claude-opus-4-8) — the helper must still seed the pick via defaultModel so the gateway resolves it.
The new 409 guard for half-written providers needs models.providers.<p>.apiKey; the existing 'accepts an arbitrary openrouter slug' mock only had the auth profile (no provider entry), so it 409'd. Add the realistic provider entry (baseUrl/api/apiKey/models) a configured openrouter provider actually has.
CodeRabbit: a complete openai-compat provider entry has baseUrl + api + apiKey (written atomically by ai-models/configure). Check all three before appending a model, so a partially-written entry triggers the 409 re-save instead of leaving the primary on an unusable provider.
Problem
On OpenClaw 2026.6.8, Anthropic chats fail with:
6.8 added a per-agent sqlite auth store, and the native anthropic plugin reads auth from there — but ClawBox writes a file-based auth profile, which doesn't get loaded into it. So even with a valid
api_keyprofile (#214), the call fails "No API key found" at runtime. Same class as the google bug (#215), different symptom.Fix
Route anthropic through Anthropic's OpenAI-compatible endpoint (
api.anthropic.com/v1) with the key inline, exactly like google/openrouter — the gateway then authenticates the call itself.Since this is the third openai-compat provider, also extracted the shared
writeOpenAICompatProvider()helper (flagged on #215) and refactored openrouter + google onto it. The chat/model auto-extend gates on a sharedOPENAI_COMPAT_PROVIDERSset.configure/route.ts:writeOpenAICompatProvider()helper; openrouter/google/anthropic branches use it.chat/model/route.ts: auto-extend now covers anthropic via the shared set./simplifyapplied: helper reuses the testedextractProviderModelId; dropped a redundant guard; corrected a now-wrong comment.Why not openai-direct?
openai-direct (API-key) has the same root cause, but is intentionally not rerouted: it's untested (Codex/oauth is the common path) and OpenAI's native
/responses+ reasoning-effort behavior could degrade under a plain openai-completions shim. Separate follow-up if anyone hits it.Verification
api.anthropic.com/v1/chat/completionsreturns 200 + a real reply forclaude-opus-4-8; the rerouted provider resolves and runs every Claude model, no auth fallback.api_keyprofile).Follow-up (not this PR)
/simplify(reuse + altitude) flagged that "which providers are openai-compat" lives in two places (the configure branches + the chat/model set). A single-source-of-truth record (collapsing the three branches into one data-driven branch) is the clean fix — deferred here to keep the diff's blast radius small.Summary by CodeRabbit
New Features
Tests