feat: native Anthropic API mode for Claude models on GitHub Copilot (#579)
* feat: native Anthropic API mode for Claude models on GitHub Copilot When using Claude models through GitHub Copilot, automatically switch from the OpenAI-compatible shim to Anthropic's native messages API format. The Copilot proxy (api.githubcopilot.com) supports Anthropic's native API for Claude models. This enables cache_control blocks to be sent and honoured, allowing explicit prompt caching control (as opposed to relying solely on server-side auto-caching). Changes: - Add isGithubNativeAnthropicMode() in providers.ts that auto-enables when the resolved model starts with "claude-" and the GitHub provider is active - Create a native Anthropic client in client.ts using the GitHub base URL and Bearer token authentication when native mode is detected - Enable prompt caching in claude.ts for native GitHub mode so cache_control blocks are sent (previously only allowed for firstParty/bedrock/vertex) - CLAUDE_CODE_GITHUB_ANTHROPIC_API=1 env var to force native mode for any model Benefits: - Proper Anthropic message format (no lossy OpenAI translation) - Explicit cache_control blocks for fine-grained caching control - Potentially better Claude model behaviour with native format Related: #515 * fix: scope force flag to Claude models and add isGithubNativeAnthropicMode tests - CLAUDE_CODE_GITHUB_ANTHROPIC_API=1 now returns false for non-Claude models (force flag still useful for aliases like 'github:copilot' with no model resolved yet, where it returns true when model is empty) - Add 7 focused tests covering mode detection: off without GitHub provider, auto-detect via OPENAI_MODEL and resolvedModel, non-Claude model rejection, and force-flag behaviour for claude/non-claude/no-model cases * fix: detect github:copilot:claude- compound format, remove force flag OPENAI_MODEL for GitHub Copilot uses the format 'github:copilot:MODEL' (e.g. 'github:copilot:claude-sonnet-4'), which does not start with 'claude-'. Auto-detection now handles both bare model names and the compound format. The CLAUDE_CODE_GITHUB_ANTHROPIC_API force flag is removed: with proper compound-format detection there is no remaining gap it could fill, and keeping a broad override flag without a concrete use case invites misuse. Tests updated to cover the compound format, generic alias (false), and non-Claude compound model (github:copilot:gpt-4o → false). * fix: use includes('claude-') for model detection, remove force flag Detection was broken for the standard GitHub Copilot compound format 'github:copilot:claude-sonnet-4' which does not start with 'claude-'. Using includes('claude-') handles bare names, compound names, and any future variants without needing updates. The CLAUDE_CODE_GITHUB_ANTHROPIC_API force flag is removed as it was a workaround for the broken detection, not a genuine use case. --------- Co-authored-by: Zartris <14197299+Zartris@users.noreply.github.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import { getSmallFastModel } from 'src/utils/model/model.js'
|
||||
import {
|
||||
getAPIProvider,
|
||||
isFirstPartyAnthropicBaseUrl,
|
||||
isGithubNativeAnthropicMode,
|
||||
} from 'src/utils/model/providers.js'
|
||||
import { getProxyFetchOptions } from 'src/utils/proxy.js'
|
||||
import {
|
||||
@@ -174,6 +175,25 @@ export async function getAnthropicClient({
|
||||
providerOverride,
|
||||
}) as unknown as Anthropic
|
||||
}
|
||||
// GitHub provider in native Anthropic API mode: send requests in Anthropic
|
||||
// format so cache_control blocks are honoured and prompt caching works.
|
||||
// Requires the GitHub endpoint (OPENAI_BASE_URL) to support Anthropic's
|
||||
// messages API — set CLAUDE_CODE_GITHUB_ANTHROPIC_API=1 to opt in.
|
||||
if (isGithubNativeAnthropicMode(model)) {
|
||||
const githubBaseUrl =
|
||||
process.env.OPENAI_BASE_URL?.replace(/\/$/, '') ??
|
||||
'https://api.githubcopilot.com'
|
||||
const githubToken =
|
||||
process.env.GITHUB_TOKEN ?? process.env.GH_TOKEN ?? ''
|
||||
const nativeArgs: ConstructorParameters<typeof Anthropic>[0] = {
|
||||
...ARGS,
|
||||
baseURL: githubBaseUrl,
|
||||
authToken: githubToken,
|
||||
// No apiKey — we authenticate via Bearer token (authToken)
|
||||
apiKey: null,
|
||||
}
|
||||
return new Anthropic(nativeArgs)
|
||||
}
|
||||
if (
|
||||
isEnvTruthy(process.env.CLAUDE_CODE_USE_OPENAI) ||
|
||||
isEnvTruthy(process.env.CLAUDE_CODE_USE_GITHUB) ||
|
||||
|
||||
Reference in New Issue
Block a user