fix(cloudflare-ai-gateway): translate dotted Anthropic ids for the Unified route - #44219
Conversation
…ified route
models.dev publishes Anthropic model ids with dot-separated version
numbers (e.g. "claude-haiku-4.5") to match its site-wide display
convention, but Anthropic's real API model slugs use dashes
("claude-haiku-4-5"). The Cloudflare AI Gateway's Unified API forwards
the model id straight through to the upstream provider, so any
unmodified dotted Anthropic id 404s with "model not found" — breaking
unified billing (and BYOK) for every proxied Anthropic model.
Every other proxied provider in the catalog (OpenAI, xAI, Google, ...)
already uses dots as part of its real upstream slug, so the
translation is scoped to the "anthropic/" prefix.
Verified live: constructing the plugin's SDK path directly against a
real Cloudflare AI Gateway (unified billing, no Anthropic key) 404s
with `{"error":{"code":"not_found_error","message":"model:
claude-haiku-4.5"}}` before this change, and succeeds once the id is
translated to "claude-haiku-4-5".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
|
This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window. Feel free to open a new pull request that follows our guidelines. |
|
Reopened as #44251, which meets the contributing guidelines: a short hyphenated branch name ( |
Summary
Unified billing (and BYOK) is broken for every proxied Anthropic model behind
cloudflare-ai-gateway. The Cloudflare AI Gateway's Unified API forwards the requested model id straight through to the upstream provider. models.dev publishes Anthropic ids with dot-separated version numbers to match its site-wide display convention (anthropic/claude-haiku-4.5), but Anthropic's real API model slugs use dashes (claude-haiku-4-5). The unmodified dotted id 404s against Anthropic before the request ever gets a chance to use the gateway's stored/unified-billing credentials.This is scoped to Anthropic — every other proxied provider in the
cloudflare-ai-gatewaycatalog (OpenAI, xAI, Google, Alibaba, DeepSeek, Moonshot AI, Thinking Machines) already uses dots as part of its actual upstream slug (e.g. OpenAI'sgpt-4.1is reallygpt-4.1), so translating dots to dashes only foranthropic/ids is safe and doesn't touch anyone else.Root cause / verification
ai-gateway-provider'screateUnified()(the same call this plugin makes), bypassing opencode's CLI entirely:anthropic/claude-haiku-4.5→APICallError: model: claude-haiku-4.5(not_found_error, straight from Anthropic via the gateway)anthropic/claude-haiku-4-5→ succeeds, billed through the gateway's unified billing with no Anthropic key configured anywherecloudflare-ai-gatewayprovider files for Anthropic models have used the dotted filename/id (withbase_modelpointing at the dashed lab model, e.g.base_model = "anthropic/claude-haiku-4-5") since before the currently open anomalyco/models.dev#4922, and that PR doesn't touch id/filename conventions.base_modelis parse-time-only in models.dev and doesn't propagate into the generated catalog JSON opencode consumes, so the plugin can't recover the native slug from data — it has to derive it./anthropic/v1/messagesroute (not the Unified API) with no upstream Anthropic key succeeds today, confirming unified billing itself is correctly configured account-side; the bug is purely in how the model id reaches the Unified route.Change
packages/core/src/plugin/provider/cloudflare-ai-gateway.ts: addnativeModelId(), which replaces.with-for ids prefixedanthropic/before callingunified(modelID). No-op for every other provider.createUnified, and a non-Anthropic dotted id (OpenAI'sgpt-4.1) passed through unchanged.Test plan
bun testinpackages/core— 1095 pass / 0 fail (includes the 2 new cases)tsgo --noEmit— cleanoxlint— 0 new errors (pre-existing warnings only, unrelated to this file)Marked as a draft since I don't have a way to run this through opencode's own CLI test harness end-to-end from this environment — happy to iterate on review.
🤖 Generated with Claude Code