feat(gateway): prefix non-Anthropic ids for the Claude Code picker - #483
Draft
yyyr-p wants to merge 3 commits into
Draft
feat(gateway): prefix non-Anthropic ids for the Claude Code picker#483yyyr-p wants to merge 3 commits into
yyyr-p wants to merge 3 commits into
Conversation
4 tasks
yyyr-p
marked this pull request as draft
August 18, 2026 07:28
Collaborator
Author
|
Wait for pipeline refactoring before merging this |
The Claude Code picker prefix only triggered on the standalone CLI's `claude-code/` discovery UA and `claude-cli/` inference UA. The Claude Desktop app embeds the same picker but its HTTP layer is an Electron fetch, so its `/v1/models` and `/v1/messages` requests carry a `Mozilla/5.0 ... Claude/<version> ... Electron/...` UA instead. Those requests fell through to the public OpenAI-Anthropic superset, so every non-Anthropic model was silently dropped by the picker's `claude`/`anthropic` id filter, and a prefixed id picked from the desktop chat would reach the resolver undecoded. Match the desktop app's `Claude/<version>` product token on both the discovery and inference paths so it receives the Anthropic-native catalog with prefixed ids and gets the prefix stripped before resolution. The begins-with ACCEPT predicate is kept (not loosened to the v2.1.223+ contains-anywhere rule) so a single encoding survives both picker generations.
Collaborator
Author
|
Added support for Claude Desktop. This also solves #496 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The Claude Code CLI's gateway-discovery model picker filters
/v1/modelsentries by id: Anthropic documents that it ignores any entry whoseiddoesn't begin withclaudeoranthropic, and the compiledBootstrap Gateway /v1/modelshandler in@anthropic-ai/claude-code@2.1.211matches that verbatim —models.filter(m => /^(claude|anthropic)/i.test(m.id)), then a second pass that drops ids resolving to a built-in Claude family other than Fable. Any non-Anthropic model Floway advertises through discovery is silently dropped from the/modelmenu, so an operator who routes GPT-5 or Gemini through a gateway upstream never sees it selectable.The
/v1/modelshandler now prepends aclaude-code!marker to every non-Anthropic id when the caller is the CLI (claude-code/<version>User-Agent). The picker admits the prefixed id, and because it rendersdisplay_name ?? id, the operator-configured label is still what the user sees — the id rewrite is invisible in the UI. The marker is an encoding prefix rather than a reserved namespace: a raw id that already begins withclaude-code!gains another layer, soM,P+M, andP+P+Mmap toP+M,P+P+M,P+P+P+Mand every advertised id stays unique without reserving!from upstream ids. The catalog is also narrowed to chat models before the rewrite, matching the Codex and Gemini discovery handlers — the picker is a chat surface and embedding/image entries only clutter it.On the Messages path the same id comes back from the CLI's inference User-Agent (
claude-cli/<version>, distinct from theclaude-code/<version>discovery identity), and the serve boundary strips exactly one prefix layer before model resolution, so the generic candidate resolver stays unaware of the compatibility projection. Other clients' ids pass through untouched: the decode is gated on theclaude-cli/User-Agent so a literal upstream id that happens to begin withclaude-code!is preserved rather than truncated.Test Plan
pnpm run verify— the gateway suite is green, including 36 tests acrosshttp_test.tsandserve_test.tscovering the encode/decode round-trip, prefix doubling, the[1m]suffix composition, the chat-only narrow, and the non-Claude-Code passthrough. Fiveapps/webfailures (Copilot device-flow polling, OAuth authorize-url) are pre-existing onupstream/mainand unrelated to this PR —apps/webis unchanged in this branch.gpt-4o) is served asclaude-code!gpt-4oto the CLI and decoded back togpt-4obefore resolution; a literalclaude-code!gpt-4oupstream id round-trips through a doubled prefix to its original form.