mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-22 06:42:19 +03:00
Validated on the resolved merge against the current tip (527da656 + the post-#11281 rebaseline): the single conflict was a comment-only collision in providers/[id]/models/route.ts (kept the tip's #10828-ordering note). Focused suites 125/125 across all 13 touched test files (build-sqlite-stub, cc-compatible, copilot-claude-messages, copilot-gemini-route, executor-github, ghe-copilot, github-copilot-discovery-token, github-copilot-model-discovery, noauth-sibling-7620, provider-header-profiles, provider-models-config, request-log-payloads, upstream-error-passthrough), typecheck:core clean, file-size/changelog-integrity OK. Merged --admin over the inherited 2026-08-23 base-red cluster (#9985) — the reds are proven tip failures (CLI catalog cluster + @testing-library allowlist, being drained by #11280), not from this diff. Note: the rebase means several items the body listed (relay x-relay-path SSRF, /v1/search blocked-providers, #10736 rotation fence, #10903, #10865, #10899, #10916) already landed upstream and are NOT in this delta — the delta is: better-sqlite3 build guard + build heap/worker caps + telemetry-off (#10060 re-derived), credential-echo passthrough refusal + OCR/moderation redaction + call-log key redaction, Copilot CLI 1.0.81-6 wire identity + Claude→/v1/messages name-matched routing + discovery token fix, CC model_not_found 400, compat overrides for no-auth aliases (#7620-pinned). The Copilot wire-identity change is the one to watch in production. Thank you @arminanton — and the ported-author credits in the commit history (@rqzbeh, yidecode, the #10899/#10916 authors) are preserved. Your config-posture finding (REQUIRE_API_KEY default vs 0.0.0.0) is noted for a maintainer decision, as you scoped it.
266 lines
7.5 KiB
TypeScript
266 lines
7.5 KiB
TypeScript
import type { RegistryEntry } from "../../shared.ts";
|
|
import {
|
|
GPT_5_5_CODEX_CAPABILITIES,
|
|
getGitHubCopilotChatHeaders,
|
|
resolvePublicCred,
|
|
} from "../../shared.ts";
|
|
|
|
export const githubProvider: RegistryEntry = {
|
|
id: "github",
|
|
alias: "gh",
|
|
format: "openai",
|
|
executor: "github",
|
|
baseUrl: "https://api.githubcopilot.com/chat/completions",
|
|
responsesBaseUrl: "https://api.githubcopilot.com/responses",
|
|
// Anthropic-native shim: the only Copilot endpoint that surfaces prompt-cache
|
|
// token counts (cached_tokens) for Claude models, and avoids round-tripping
|
|
// tool_use/tool_result/thinking content blocks through the OpenAI shape.
|
|
// Routed via each claude-* model's targetFormat: "claude" below (see
|
|
// executors/github.ts buildUrl/buildHeaders). Port of decolua/9router#2608.
|
|
messagesUrl: "https://api.githubcopilot.com/v1/messages",
|
|
authType: "oauth",
|
|
authHeader: "bearer",
|
|
// GitHub Copilot is a public device-flow OAuth client: it has a public client_id but
|
|
// NO client_secret. Populate clientId so token refresh carries it (9router#442) — without
|
|
// it, refresh requests omit/garble client_id and GitHub rejects them. Embedded via
|
|
// resolvePublicCred per Hard Rule #11 (never a string literal).
|
|
oauth: {
|
|
clientIdEnv: "GITHUB_OAUTH_CLIENT_ID",
|
|
clientIdDefault: resolvePublicCred("github_copilot_id"),
|
|
},
|
|
defaultContextLength: 128000,
|
|
headers: getGitHubCopilotChatHeaders(),
|
|
// All claude-* entries below carry targetFormat: "claude" so chatCore.ts
|
|
// translates the request to Anthropic-native shape before the executor ever
|
|
// sees it, and the github executor's buildUrl()/buildHeaders() route them at
|
|
// messagesUrl (/v1/messages) instead of /chat/completions. Port of
|
|
// decolua/9router#2608 (author: yidecode) — see executors/github.ts.
|
|
models: [
|
|
{
|
|
id: "claude-fable-5",
|
|
name: "Claude Fable 5",
|
|
targetFormat: "claude",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
{
|
|
id: "claude-opus-5",
|
|
name: "Claude Opus 5",
|
|
targetFormat: "claude",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
unsupportedParams: ["temperature", "top_p", "top_k"],
|
|
},
|
|
{
|
|
id: "claude-opus-4.8-fast",
|
|
name: "Claude Opus 4.8 (fast mode)",
|
|
targetFormat: "claude",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
unsupportedParams: ["temperature", "top_p", "top_k"],
|
|
},
|
|
{
|
|
id: "claude-opus-4.8",
|
|
name: "Claude Opus 4.8",
|
|
targetFormat: "claude",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
unsupportedParams: ["temperature", "top_p", "top_k"],
|
|
},
|
|
{
|
|
id: "claude-opus-4.7",
|
|
name: "Claude Opus 4.7",
|
|
targetFormat: "claude",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
{
|
|
id: "claude-opus-4.6",
|
|
name: "Claude Opus 4.6",
|
|
targetFormat: "claude",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
{
|
|
id: "claude-sonnet-4.6",
|
|
name: "Claude Sonnet 4.6",
|
|
targetFormat: "claude",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
{
|
|
id: "claude-opus-4.5",
|
|
name: "Claude Opus 4.5",
|
|
targetFormat: "claude",
|
|
contextLength: 200000,
|
|
maxOutputTokens: 32000,
|
|
},
|
|
{
|
|
id: "claude-sonnet-5",
|
|
name: "Claude Sonnet 5",
|
|
targetFormat: "claude",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
{
|
|
id: "claude-sonnet-4.5",
|
|
name: "Claude Sonnet 4.5",
|
|
targetFormat: "claude",
|
|
contextLength: 200000,
|
|
maxOutputTokens: 32000,
|
|
},
|
|
{
|
|
id: "claude-haiku-4.5",
|
|
name: "Claude Haiku 4.5",
|
|
targetFormat: "claude",
|
|
contextLength: 200000,
|
|
maxOutputTokens: 32000,
|
|
},
|
|
// #2911: Gemini on Copilot must use chat/completions, not the Responses API.
|
|
{
|
|
id: "gemini-3.1-pro-preview",
|
|
name: "Gemini 3.1 Pro",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
{
|
|
id: "gemini-3.7-flash",
|
|
name: "Gemini 3.7 Flash",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
{
|
|
id: "gemini-3.6-flash",
|
|
name: "Gemini 3.6 Flash",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
{
|
|
id: "gemini-3.5-flash",
|
|
name: "Gemini 3.5 Flash",
|
|
contextLength: 1000000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
{
|
|
id: "gpt-5.6-sol",
|
|
name: "GPT-5.6 Sol",
|
|
targetFormat: "openai-responses",
|
|
maxOutputTokens: 128000,
|
|
},
|
|
{
|
|
id: "gpt-5.6-terra",
|
|
name: "GPT-5.6 Terra",
|
|
targetFormat: "openai-responses",
|
|
maxOutputTokens: 128000,
|
|
},
|
|
{
|
|
id: "gpt-5.6-luna",
|
|
name: "GPT-5.6 Luna",
|
|
targetFormat: "openai-responses",
|
|
maxOutputTokens: 128000,
|
|
},
|
|
{ id: "gpt-5.5", name: "GPT-5.5", ...GPT_5_5_CODEX_CAPABILITIES, maxOutputTokens: 128000 },
|
|
{
|
|
id: "gpt-5.4",
|
|
name: "GPT-5.4",
|
|
targetFormat: "openai-responses",
|
|
supportsXHighEffort: true,
|
|
contextLength: 1050000,
|
|
maxOutputTokens: 128000,
|
|
},
|
|
{
|
|
id: "gpt-5.4-mini",
|
|
name: "GPT-5.4 mini",
|
|
targetFormat: "openai-responses",
|
|
contextLength: 400000,
|
|
maxOutputTokens: 128000,
|
|
},
|
|
{
|
|
id: "gpt-5.4-nano",
|
|
name: "GPT-5.4 nano",
|
|
targetFormat: "openai-responses",
|
|
contextLength: 400000,
|
|
maxOutputTokens: 128000,
|
|
},
|
|
{
|
|
id: "gpt-5.3-codex",
|
|
name: "GPT-5.3-Codex",
|
|
targetFormat: "openai-responses",
|
|
contextLength: 400000,
|
|
maxOutputTokens: 128000,
|
|
},
|
|
{
|
|
id: "gpt-5-mini",
|
|
name: "GPT-5 mini",
|
|
targetFormat: "openai-responses",
|
|
contextLength: 264000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
{
|
|
id: "gpt-4o-2024-11-20",
|
|
name: "GPT-4o",
|
|
contextLength: 128000,
|
|
maxOutputTokens: 16384,
|
|
},
|
|
{ id: "gpt-4o-mini", name: "GPT-4o mini", contextLength: 128000, maxOutputTokens: 4096 },
|
|
{
|
|
id: "gpt-4-0125-preview",
|
|
name: "GPT 4 Turbo",
|
|
contextLength: 128000,
|
|
maxOutputTokens: 4096,
|
|
},
|
|
{
|
|
id: "kimi-k2.7-code",
|
|
name: "Kimi K2.7 Code",
|
|
contextLength: 256000,
|
|
maxOutputTokens: 32000,
|
|
},
|
|
{
|
|
id: "mai-code-1-flash",
|
|
name: "MAI-Code-1-Flash",
|
|
targetFormat: "openai-responses",
|
|
contextLength: 256000,
|
|
maxOutputTokens: 128000,
|
|
},
|
|
// MAI (Microsoft AI) — /responses-only on Copilot (400 on /chat/completions).
|
|
{
|
|
id: "mai-code-1.1-flash",
|
|
name: "MAI-Code-1.1-Flash",
|
|
targetFormat: "openai-responses",
|
|
contextLength: 256000,
|
|
maxOutputTokens: 128000,
|
|
},
|
|
{
|
|
id: "mai-code-1-flash-picker",
|
|
name: "MAI-Code-1-Flash (picker)",
|
|
targetFormat: "openai-responses",
|
|
contextLength: 256000,
|
|
maxOutputTokens: 128000,
|
|
},
|
|
// xAI Grok on Copilot — /responses-only (supported_endpoints: ["/responses"];
|
|
// 400 on /chat/completions). Distinct from xAI-direct (chat-capable) — see
|
|
// the separate `xai` provider. Live-verified context 500k / output 128k.
|
|
{
|
|
id: "grok-4.6",
|
|
name: "Grok 4.6",
|
|
targetFormat: "openai-responses",
|
|
contextLength: 500000,
|
|
maxOutputTokens: 128000,
|
|
},
|
|
{
|
|
id: "grok-4.5",
|
|
name: "Grok 4.5",
|
|
targetFormat: "openai-responses",
|
|
contextLength: 500000,
|
|
maxOutputTokens: 128000,
|
|
},
|
|
{
|
|
id: "oswe-vscode-prime",
|
|
name: "Raptor mini",
|
|
targetFormat: "openai-responses",
|
|
contextLength: 264000,
|
|
maxOutputTokens: 64000,
|
|
},
|
|
],
|
|
};
|