Approved
Route Anthropic /v1/messages requests for Claude models directly to the GitHub Copilot upstream's native Anthropic endpoint, bypassing the existing OpenAI translation layer. This preserves thinking blocks with signature field, top_k, cache_control, and richer usage stats — none of which survive the current translation round-trip.
GitHub Copilot's upstream (api.enterprise.githubcopilot.com) natively speaks the Anthropic Messages API for all Claude 4.5+ models. The current code path translates Anthropic → OpenAI → sends → translates back, losing:
thinkingblocks (completely dropped)signaturefield on thinking blocks (required for multi-turn reasoning)cache_creation_input_tokensin usagetop_kparametercache_controlon system/user blocks
The fix: detect Claude models by vendor === "Anthropic" from the /models endpoint, and forward requests verbatim to /v1/messages upstream.
create-messages-native.ts— Service client that POSTs Anthropic payloads directly to${copilotBaseUrl}/v1/messageswith correct headers (anthropic-version,anthropic-beta).- Route dispatch —
handler.tschecksisNativeAnthropicModel(model)and branches to native path for Claude, translation path for everything else. native-models.ts—isNativeAnthropicModel(modelId)checksstate.modelsvendor field; falls back toclaude-prefix heuristic before models load.- Type fixes —
anthropic-types.ts:signature?onAnthropicThinkingBlock; unionthinkingtype for adaptive (opus-4.7+);output_config;AnthropicImageBlockURL source;AnthropicToolResultBlock.contentwidened. - Adaptive thinking upgrade —
create-messages-native.tsauto-upgrades{ type: "enabled" }→{ type: "adaptive" }+output_config.effortforclaude-opus-4.7+models. - SSE proxy — Streaming responses from native path forwarded verbatim to client (no re-translation needed).
- Claude models (
vendor === "Anthropic") route to native path; non-Claude models route to translation path. - Thinking blocks with
signaturefield returned to client in both streaming and non-streaming. - Multi-turn conversations with thinking blocks (echoing
signature) work correctly. claude-opus-4.7+with{ type: "enabled" }thinking auto-upgrades to adaptive format; no HTTP 400.- All existing tests pass; new tests cover native vs. translation dispatch.
state.models.data from /models endpoint has vendor: "Anthropic" for all Claude models. isNativeAnthropicModel() checks this first, falls back to startsWith("claude-") heuristic.
anthropic-version: 2023-06-01
anthropic-beta: interleaved-thinking-2025-05-14,prompt-caching-2024-07-31
Plus all standard Copilot headers (auth, editor-version, etc.).
Native upstream sends proper Anthropic SSE events. Parse event.type for logging; forward rawEvent.data verbatim. No translation needed.
If model matches /^claude-opus-4[.-](\d+)/ with minor ≥ 7, auto-upgrade { type: "enabled", budget_tokens: N } → { type: "adaptive" } + output_config: { effort: "medium" }.
New:
src/services/copilot/create-messages-native.tssrc/services/copilot/native-models.ts
Modified:
src/routes/messages/anthropic-types.ts— type fixessrc/routes/messages/handler.ts— dispatch logicsrc/routes/messages/non-stream-translation.ts— remove stale comment; fix image source narrowing
- Unit:
isNativeAnthropicModel()with populated vs emptystate.models - Unit:
buildUpstreamPayload()adaptive thinking upgrade - Integration: handler routes Claude models to native, GPT models to translation
- Existing translation tests must still pass
- Persistent caching of native responses
- URL image sources (rejected by upstream; type kept for fidelity)
- Responses API (#1 epic)