Part of #38. Depends on #39.
Background
The hardcoded NATIVE_ANTHROPIC_MODELS set in #39 will go stale as Copilot adds new Claude models. A better approach: dynamically determine which models support the native /v1/messages path from the /models response.
Current models endpoint response shape (from copilot_models_raw.json)
{
"id": "claude-sonnet-4.5",
"name": "Claude Sonnet 4.5",
"vendor": "Anthropic",
"capabilities": {
"type": "chat",
"supports": {
"tool_calls": true,
"streaming": true,
"vision": true,
"max_thinking_budget": 32000,
"min_thinking_budget": 1024
}
}
}
Detection rule (derived from live testing)
A model supports the native Anthropic path if:
vendor === "Anthropic" (case-insensitive), AND
- The model actually responds to
POST /v1/messages — or we trust vendor=Anthropic as sufficient signal (note: claude-sonnet-4 with vendor=Anthropic does NOT work — it returns 400 model_not_supported)
The safest approach: vendor-based + a runtime probe on startup / on models refresh.
Tasks
Acceptance criteria
- When Copilot adds
claude-haiku-4.7, it appears in state.nativeAnthropicModels automatically after a server restart
claude-sonnet-4 (vendor=Anthropic but runtime-rejected) is excluded if the probe is enabled
- Hardcoded fallback keeps the server working before first
/models fetch completes
File pointers
- Touch:
src/services/copilot/get-models.ts
- Touch:
src/lib/state.ts (add nativeAnthropicModels: Set<string>)
- Touch:
src/services/copilot/create-messages-native.ts (replace hardcoded set)
Part of #38. Depends on #39.
Background
The hardcoded
NATIVE_ANTHROPIC_MODELSset in #39 will go stale as Copilot adds new Claude models. A better approach: dynamically determine which models support the native/v1/messagespath from the/modelsresponse.Current models endpoint response shape (from
copilot_models_raw.json){ "id": "claude-sonnet-4.5", "name": "Claude Sonnet 4.5", "vendor": "Anthropic", "capabilities": { "type": "chat", "supports": { "tool_calls": true, "streaming": true, "vision": true, "max_thinking_budget": 32000, "min_thinking_budget": 1024 } } }Detection rule (derived from live testing)
A model supports the native Anthropic path if:
vendor === "Anthropic"(case-insensitive), ANDPOST /v1/messages— or we trust vendor=Anthropic as sufficient signal (note:claude-sonnet-4withvendor=Anthropicdoes NOT work — it returns 400model_not_supported)The safest approach: vendor-based + a runtime probe on startup / on models refresh.
Tasks
src/services/copilot/get-models.ts: after fetching models, buildstate.nativeAnthropicModels: Set<string>= set of model ids wherevendor.toLowerCase() === "anthropic"HEADor minimal POST to${copilotBaseUrl}/v1/messagesto verify it responds 200 vs 400. Cache result with the model list TTL. Skip probe if--no-probeflag set.NATIVE_ANTHROPIC_MODELSset increate-messages-native.tswithstate.nativeAnthropicModelsvendorto the state models shape if not already storedstate.nativeAnthropicModelsis empty (first boot before models loaded), use the hardcoded set as fallback"Native Anthropic path: claude-sonnet-4.5, claude-sonnet-4.6, claude-opus-4.5, ..."Acceptance criteria
claude-haiku-4.7, it appears instate.nativeAnthropicModelsautomatically after a server restartclaude-sonnet-4(vendor=Anthropic but runtime-rejected) is excluded if the probe is enabled/modelsfetch completesFile pointers
src/services/copilot/get-models.tssrc/lib/state.ts(addnativeAnthropicModels: Set<string>)src/services/copilot/create-messages-native.ts(replace hardcoded set)