Skip to content

feat: native Anthropic pass-through for Claude models (#38)#48

Merged
HXYerror merged 3 commits into
masterfrom
feat/native-anthropic-passthrough
May 11, 2026
Merged

feat: native Anthropic pass-through for Claude models (#38)#48
HXYerror merged 3 commits into
masterfrom
feat/native-anthropic-passthrough

Conversation

@HXYerror
Copy link
Copy Markdown
Owner

Summary

Route Anthropic /v1/messages requests for Claude models directly to GitHub Copilot's native Anthropic endpoint, bypassing the OpenAI translation layer. This preserves:

  • thinking blocks with signature field (required for multi-turn reasoning)
  • cache_creation_input_tokens in usage
  • top_k parameter
  • cache_control on system/user blocks

Changes

  • src/services/copilot/create-messages-native.ts (new) — POSTs Anthropic payloads directly to ${copilotBaseUrl}/v1/messages; strips openai-intent header; auto-upgrades { type: "enabled" }{ type: "adaptive" } for claude-opus-4.7+ models
  • src/services/copilot/native-models.ts (new) — isNativeAnthropicModel() checks state.models vendor field first, falls back to claude- prefix heuristic
  • src/routes/messages/handler.ts — dispatch logic: Claude → native path, everything else → translation path; manualApprove gate moved before dispatch so both paths are gated
  • src/routes/messages/anthropic-types.tssignature? on AnthropicThinkingBlock; union thinking type for adaptive; output_config; AnthropicImageBlock URL source; AnthropicToolResultBlock.content widened
  • src/routes/messages/non-stream-translation.ts — image source.type === "base64" narrowing; updated comment
  • tests/native-passthrough.test.ts (new) — 19 tests covering buildUpstreamPayload (T1–T6 incl. empty output_config), isNativeAnthropicModel (T5–T9), and isAdaptiveThinkingModel boundaries (B1–B6: 4.6/4.7/4.8, dot/dash separator, non-opus, multi-digit)

Test plan

  • All 61 existing tests pass (bun test)
  • Claude model (claude-sonnet-4-5) request routes to native path
  • Non-Claude model (gpt-4o) routes to translation path
  • Streaming SSE events forwarded verbatim (parse-for-log only, not blocking)
  • claude-opus-4.7+ with legacy thinking auto-upgraded to adaptive format

Closes #38, #44, #45

🤖 Generated with Claude Code

HXYerror and others added 3 commits May 11, 2026 01:50
- H1: Remove dead [DONE] sentinel from native SSE loop (Anthropic terminates via connection close)
- H3: Conditionally set accept: text/event-stream only when streaming
- M1: buildUpstreamPayload returns rest (not payload) when thinking absent, stripping output_config
- M2: Truncate raw SSE data to 200 chars in warn log to prevent log injection
- L2: Remove claude_ underscore prefix heuristic (no known Anthropic model uses it)
- L3: Document >= 7 threshold comment in isAdaptiveThinkingModel
- L4: Replace verbose JSDoc on nativeAnthropicModelIds with concise standard form
- Export buildUpstreamPayload for direct unit testing
- Add tests/native-passthrough.test.ts with T1-T9 covering payload transform and model routing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@HXYerror HXYerror merged commit 9c60f0b into master May 11, 2026
@HXYerror HXYerror deleted the feat/native-anthropic-passthrough branch May 11, 2026 03:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Native Anthropic pass-through for Claude models (no translation)

1 participant