Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
1 line
328 KiB
JSON
1 line
328 KiB
JSON
{"repo": "aj-omanai/1st", "files": {"omniroute/src/shared/constants/providers/apikey/gateways.ts": {"6eea4894299d5371c00c11f1f6dec2f7c0076253": {"t": 1785596390.1589055, "n": 24421, "h": "40c6bbda8e7e5a38", "c": "/**\n * APIKEY provider catalog — gateways family (aggregators, multi-model routers & API marketplaces).\n * Pure data; merged by apikey/index.ts via spread (god-file decomposition; semantic split).\n */\nexport const APIKEY_PROVIDERS_GATEWAYS = {\n \"charm-hyper\": {\n id: \"charm-hyper\",\n alias: \"charm-hyper\",\n name: \"Charm Hyper\",\n icon: \"router\",\n color: \"#7C3AED\",\n textIcon: \"CH\",\n passthroughModels: true,\n website: \"https://hyper.charm.land\",\n hasFree: true,\n freeNote: \"100 free monthly Hypercredits on signup\",\n apiHint: \"Create an API key at https://hyper.charm.land, then paste it here as a Bearer token.\",\n },\n agentrouter: {\n id: \"agentrouter\",\n alias: \"agentrouter\",\n name: \"AgentRouter\",\n icon: \"router\",\n color: \"#10B981\",\n textIcon: \"AR\",\n passthroughModels: true,\n website: \"https://agentrouter.org\",\n hasFree: true,\n freeNote: \"$200 free credits on signup - multi-model routing gateway\",\n apiHint: \"Get $200 free credits at https://agentrouter.org/register — no credit card required.\",\n },\n \"command-code\": {\n id: \"command-code\",\n alias: \"cmd\",\n name: \"Command Code\",\n icon: \"terminal\",\n color: \"#111827\",\n textIcon: \"CC\",\n website: \"https://commandcode.ai/\",\n authHint:\n \"Use a Command Code API key. Requests are sent to Command Code's /alpha/generate endpoint.\",\n apiHint: \"Create or copy an API key from Command Code, then paste it here as a Bearer token.\",\n },\n openrouter: {\n id: \"openrouter\",\n alias: \"openrouter\",\n name: \"OpenRouter\",\n icon: \"router\",\n color: \"#F97316\",\n textIcon: \"OR\",\n passthroughModels: true,\n website: \"https://openrouter.ai\",\n hasFree: true,\n freeNote: \"Free models at $0/token with :free suffix - 20 RPM / 200 RPD\",\n },\n requesty: {\n id: \"requesty\",\n alias: \"requesty\",\n name: \"Requesty\",\n icon: \"router\",\n color: \"#6366F1\",\n textIcon: \"RQ\",\n passthroughModels: true,\n website: \"https://requesty.ai\",\n hasFree: true,\n freeNote: \"Free tier ~200 requests/day - multi-model routing gateway (300+ models)\",\n apiHint:\n \"Create an API key at https://app.requesty.ai, then paste it here as a Bearer token. \" +\n \"OpenAI-compatible endpoint at https://router.requesty.ai/v1, with a live /v1/models catalog.\",\n },\n dgrid: {\n id: \"dgrid\",\n alias: \"dgrid\",\n name: \"DGrid\",\n icon: \"router\",\n color: \"#65A30D\",\n textIcon: \"DG\",\n passthroughModels: true,\n website: \"https://dgrid.ai\",\n hasFree: true,\n freeNote:\n \"DGrid Free Models Router: 10 requests/minute and 100 requests/day. \" +\n \"A $5 lifetime top-up unlocks up to 20 requests/minute and 1,000 requests/day.\",\n apiHint:\n \"Create a DGrid API key at https://dgrid.ai, then use https://api.dgrid.ai/v1 \" +\n \"as the OpenAI-compatible base URL.\",\n },\n qiniu: {\n id: \"qiniu\",\n alias: \"qiniu\",\n name: \"Qiniu\",\n icon: \"cloud\",\n color: \"#1E88E5\",\n textIcon: \"QN\",\n passthroughModels: true,\n website: \"https://www.qiniu.com\",\n apiHint:\n \"Create a Qiniu AI inference API key at https://portal.qiniu.com/ai-inference/api-key, \" +\n \"then paste it here as a Bearer token. OpenAI-compatible endpoint \" +\n \"at https://api.qnaigc.com/v1, proxying DeepSeek, Claude, Kimi and more behind one key.\",\n },\n orcarouter: {\n id: \"orcarouter\",\n alias: \"orcarouter\",\n name: \"OrcaRouter\",\n icon: \"router\",\n color: \"#0891B2\",\n textIcon: \"ORC\",\n passthroughModels: true,\n website: \"https://www.orcarouter.ai\",\n apiHint:\n \"Create an API key (starts with sk-orca-) at https://www.orcarouter.ai, then paste it as a Bearer token. OpenAI-compatible endpoint at https://api.orcarouter.ai/v1.\",\n },\n \"api-airforce\": {\n id: \"api-airforce\",\n alias: \"af\",\n name: \"Api.airforce\",\n icon: \"flight\",\n color: \"#1E3A5F\",\n textIcon: \"AF\",\n website: \"https://api.airforce\",\n hasFree: true,\n freeNote:\n \"55 free tier models including Grok-3, Claude 3.7, Qwen3, Kimi-K2, Gemini 2.5 Flash, DeepSeek-V3\",\n apiHint:\n \"Get your API key from https://panel.api.airforce — OpenAI-compatible endpoint at https://api.airforce/v1\",\n },\n crof: {\n id: \"crof\",\n alias: \"crof\",\n name: \"CrofAI\",\n icon: \"auto_awesome\",\n color: \"#0EA5E9\",\n textIcon: \"CR\",\n website: \"https://crof.ai\",\n },\n bazaarlink: {\n id: \"bazaarlink\",\n alias: \"bzl\",\n name: \"BazaarLink\",\n icon: \"storefront\",\n color: \"#6366F1\",\n textIcon: \"BZ\",\n website: \"https://bazaarlink.ai\",\n hasFree: true,\n freeNote:\n \"Free tier: 4M tokens/day per account with auto:free routing — zero-cost inference, no credit card required.\",\n authHint:\n \"Use your BazaarLink API key (starts with sk-bl-) in Authorization: Bearer <key>. OpenAI SDK works with base URL https://bazaarlink.ai/api/v1. Models use provider/model-name format.\",\n apiHint:\n \"Create a free API key at https://bazaarlink.ai — model 'auto:free' routes to zero-cost inference. All models use the provider/model-name format, e.g. xiaomi/mimo-v2.5-pro.\",\n },\n synthetic: {\n id: \"synthetic\",\n alias: \"synthetic\",\n name: \"Synthetic\",\n icon: \"verified_user\",\n color: \"#6366F1\",\n textIcon: \"SY\",\n website: \"https://synthetic.new\",\n passthroughModels: true,\n },\n \"kilo-gateway\": {\n id: \"kilo-gateway\",\n alias: \"kg\",\n name: \"Kilo Gateway\",\n icon: \"hub\",\n color: \"#617A91\",\n textIcon: \"KG\",\n website: \"https://kilo.ai\",\n passthroughModels: true,\n },\n wafer: {\n id: \"wafer\",\n alias: \"wafer\",\n name: \"Wafer AI\",\n icon: \"layers\",\n color: \"#6366F1\",\n textIcon: \"WF\",\n website: \"https://wafer.ai\",\n apiHint: \"API key from https://wafer.ai\",\n },\n \"opencode-zen\": {\n id: \"opencode-zen\",\n alias: \"opencode-zen\",\n name: \"OpenCode Zen\",\n icon: \"opencode\",\n color: \"#6366f1\",\n website: \"https://opencode.ai/zen\",\n anonymousFallback: true,\n },\n \"opencode-go\": {\n id: \"opencode-go\",\n alias: \"opencode-go\",\n name: \"OpenCode Go\",\n icon: \"opencode\",\n color: \"#6366f1\",\n website: \"https://opencode.ai/go\",\n anonymousFallback: true,\n },\n dahl: {\n id: \"dahl\",\n alias: \"dahl\",\n name: \"Dahl\",\n icon: \"dahl\",\n color: \"#6B7280\",\n textIcon: \"DA\",\n website: \"https://inference.dahl.global\",\n hasFree: true,\n freeNote: \"Free — MiniMax M2.7, Kimi K2.6. Click 'Add Account' to auto-generate a token.\",\n authHint: \"Click 'Add Account' to auto-generate a token.\",\n apiHint: \"No manual API key needed. Click 'Add Account' to auto-generate a token.\",\n apiKeyUrl: \"https://inference.dahl.global/tokens\",\n passthroughModels: false,\n managedAccount: true,\n notice: {\n text: \"Dahl auto-generates tokens via https://inference.dahl.global/tokens. No signup needed. Rate limits apply.\",\n },\n },\n puter: {\n id: \"puter\",\n alias: \"pu\",\n name: \"Puter AI\",\n icon: \"cloud_circle\",\n color: \"#6366F1\",\n textIcon: \"PU\",\n website: \"https://puter.com\",\n hasFree: true,\n freeNote:\n \"500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3...) — Users pay via free Puter account\",\n passthroughModels: true,\n authHint: \"Get token at puter.com/dashboard → Copy Auth Token\",\n },\n uncloseai: {\n id: \"uncloseai\",\n alias: \"unc\",\n name: \"UncloseAI\",\n icon: \"auto_awesome\",\n color: \"#8B5CF6\",\n textIcon: \"UN\",\n website: \"https://uncloseai.com\",\n hasFree: true,\n freeNote: \"Free forever — no signup, no credit card. OpenAI-compatible endpoints.\",\n passthroughModels: true,\n authHint: \"No auth required. API accepts any non-empty string as key for identification.\",\n },\n hackclub: {\n id: \"hackclub\",\n alias: \"hc\",\n name: \"Hackclub AI\",\n icon: \"auto_awesome\",\n color: \"#FF6B00\",\n textIcon: \"HC\",\n website: \"https://ai.hackclub.com\",\n hasFree: true,\n freeNote: \"Free AI for Hack Club members — 30+ models, no credit card.\",\n passthroughModels: true,\n authHint: \"Sign in with your Hack Club account at ai.hackclub.com.\",\n },\n freetheai: {\n id: \"freetheai\",\n alias: \"fta\",\n name: \"FreeTheAi\",\n icon: \"hub\",\n color: \"#22C55E\",\n textIcon: \"FTA\",\n website: \"https://freetheai.xyz\",\n hasFree: true,\n freeNote: \"Free OpenAI-compatible gateway — sign up via Discord for an API key.\",\n passthroughModels: true,\n authHint: \"Join the FreeTheAi Discord to get your free API key.\",\n },\n \"g4f-groq\": {\n id: \"g4f-groq\",\n alias: \"g4fgroq\",\n name: \"g4f.space — Groq\",\n icon: \"bolt\",\n color: \"#F97316\",\n textIcon: \"G4F\",\n website: \"https://g4f.space\",\n hasFree: true,\n freeNote:\n \"Free no-key reverse proxy to Groq (gpt4free project) — rate-limited to 5 req/min.\",\n passthroughModels: true,\n authHint:\n \"No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits.\",\n },\n \"g4f-gemini\": {\n id: \"g4f-gemini\",\n alias: \"g4fgem\",\n name: \"g4f.space — Gemini\",\n icon: \"bolt\",\n color: \"#F97316\",\n textIcon: \"G4F\",\n website: \"https://g4f.space\",\n hasFree: true,\n freeNote:\n \"Free no-key reverse proxy to Gemini (gpt4free project) — rate-limited to 5 req/min.\",\n passthroughModels: true,\n authHint:\n \"No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits.\",\n },\n \"g4f-pollinations\": {\n id: \"g4f-pollinations\",\n alias: \"g4fpol\",\n name: \"g4f.space — Pollinations\",\n icon: \"bolt\",\n color: \"#F97316\",\n textIcon: \"G4F\",\n website: \"https://g4f.space\",\n hasFree: true,\n freeNote:\n \"Free no-key reverse proxy to Pollinations (gpt4free project) — rate-limited to 5 req/min.\",\n passthroughModels: true,\n authHint:\n \"No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits.\",\n },\n \"g4f-ollama\": {\n id: \"g4f-ollama\",\n alias: \"g4foll\",\n name: \"g4f.space — Ollama\",\n icon: \"bolt\",\n color: \"#F97316\",\n textIcon: \"G4F\",\n website: \"https://g4f.space\",\n hasFree: true,\n freeNote:\n \"Free no-key hosted Ollama gateway (gpt4free project) — rate-limited to 5 req/min.\",\n passthroughModels: true,\n authHint:\n \"No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits.\",\n },\n \"g4f-nvidia\": {\n id: \"g4f-nvidia\",\n alias: \"g4fnv\",\n name: \"g4f.space — NVIDIA\",\n icon: \"bolt\",\n color: \"#F97316\",\n textIcon: \"G4F\",\n website: \"https://g4f.space\",\n hasFree: true,\n freeNote:\n \"Free no-key reverse proxy to NVIDIA NIM (gpt4free project) — rate-limited to 5 req/min.\",\n passthroughModels: true,\n authHint:\n \"No auth required. Free tier is limited to 5 requests/minute — sign up at g4f.dev/members.html for higher limits.\",\n },\n \"vercel-ai-gateway\": {\n id: \"vercel-ai-gateway\",\n alias: \"vag\",\n name: \"Vercel AI Gateway\",\n icon: \"route\",\n color: \"#111827\",\n textIcon: \"VAI\",\n website: \"https://vercel.com/docs/ai-gateway\",\n },\n llm7: {\n id: \"llm7\",\n alias: \"llm7\",\n name: \"LLM7.io\",\n icon: \"hub\",\n color: \"#6366F1\",\n textIcon: \"LM\",\n website: \"https://llm7.io\",\n hasFree: true,\n freeNote: \"No signup required - 2 req/s, 20 RPM, 100 req/hr free tier\",\n apiHint:\n \"Works without API key (use 'unused' as key). Get free token at token.llm7.io for higher limits.\",\n },\n llamagate: {\n id: \"llamagate\",\n alias: \"llamagate\",\n name: \"LlamaGate\",\n icon: \"gate\",\n color: \"#16A34A\",\n textIcon: \"LG\",\n website: \"https://llamagate.ai\",\n },\n gitlawb: {\n id: \"gitlawb\",\n alias: \"glb\",\n name: \"Gitlawb Opengateway (MiMo)\",\n icon: \"hub\",\n color: \"#10B981\",\n textIcon: \"GLB\",\n website: \"https://opengateway.gitlawb.com\",\n hasFree: false,\n freeNote:\n \"Free MiMo (xiaomi/mimo-v2.5) revoked 2026-05 — Opengateway is now a pay-as-you-go credit gateway; no recurring free model.\",\n apiHint: \"Get your API key from Gitlawb Opengateway dashboard.\",\n },\n \"gitlawb-gmi\": {\n id: \"gitlawb-gmi\",\n alias: \"glb-gmi\",\n name: \"Gitlawb Opengateway (GMI Cloud)\",\n icon: \"hub\",\n color: \"#10B981\",\n textIcon: \"GMI\",\n website: \"https://opengateway.gitlawb.com\",\n hasFree: false,\n freeNote:\n \"Free Nemotron promo ended 2026-06 — the GMI Cloud route is now pay-as-you-go credit only.\",\n apiHint: \"Get your API key from Gitlawb Opengateway dashboard.\",\n },\n nanogpt: {\n id: \"nanogpt\",\n alias: \"nanogpt\",\n name: \"NanoGPT\",\n icon: \"chat\",\n color: \"#4F46E5\",\n textIcon: \"NG\",\n website: \"https://nano-gpt.com\",\n },\n aimlapi: {\n id: \"aimlapi\",\n alias: \"aiml\",\n name: \"AI/ML API\",\n icon: \"hub\",\n color: \"#6366F1\",\n textIcon: \"AI\",\n website: \"https://aimlapi.com\",\n hasFree: false,\n freeNote:\n \"Free tier paused (2026) — AI/ML API is now pay-as-you-go only (min $20 top-up); no recurring free credits.\",\n passthroughModels: true,\n },\n novita: {\n id: \"novita\",\n alias: \"novita\",\n name: \"Novita AI\",\n icon: \"auto_awesome\",\n color: \"#FF4081\",\n textIcon: \"NV\",\n website: \"https://novita.ai\",\n hasFree: true,\n freeNote: \"$0.50 trial credits on signup (valid about 1 year)\",\n passthroughModels: true,\n },\n piapi: {\n id: \"piapi\",\n alias: \"pi\",\n name: \"PiAPI\",\n icon: \"api\",\n color: \"#7C4DFF\",\n textIcon: \"PI\",\n website: \"https://piapi.ai\",\n passthroughModels: true,\n },\n getgoapi: {\n id: \"getgoapi\",\n alias: \"ggo\",\n name: \"GoAPI\",\n icon: \"rocket_launch\",\n color: \"#FF6D00\",\n textIcon: \"GO\",\n website: \"https://api.getgoapi.com\",\n passthroughModels: true,\n },\n laozhang: {\n id: \"laozhang\",\n alias: \"lz\",\n name: \"LaoZhang AI\",\n icon: \"hub\",\n color: \"#FF1744\",\n textIcon: \"LZ\",\n website: \"https://api.laozhang.ai\",\n passthroughModels: true,\n },\n thebai: {\n id: \"thebai\",\n alias: \"thebai\",\n name: \"TheB.AI\",\n icon: \"hub\",\n color: \"#3B82F6\",\n textIcon: \"TB\",\n website: \"https://theb.ai\",\n authHint: \"Bearer API key for the TheB.AI OpenAI-compatible gateway.\",\n passthroughModels: true,\n },\n bai: {\n id: \"bai\",\n alias: \"bai\",\n name: \"b.ai\",\n icon: \"hub\",\n color: \"#6366F1\",\n textIcon: \"BA\",\n website: \"https://b.ai\",\n authHint:\n \"Bearer API key for the b.ai OpenAI-compatible LLM gateway (distinct from TheB.AI). \" +\n \"Create a key at https://docs.b.ai, then use https://api.b.ai/v1 as the OpenAI-compatible base URL.\",\n passthroughModels: true,\n },\n fenayai: {\n id: \"fenayai\",\n alias: \"fenayai\",\n name: \"FenayAI\",\n icon: \"hub\",\n color: \"#FF9800\",\n textIcon: \"FN\",\n website: \"https://fenayai.com\",\n authHint: \"Bearer API key for the FenayAI OpenAI-compatible gateway.\",\n passthroughModels: true,\n },\n empower: {\n id: \"empower\",\n alias: \"empower\",\n name: \"Empower\",\n icon: \"hub\",\n color: \"#14B8A6\",\n textIcon: \"EM\",\n website: \"https://docs.empower.dev\",\n authHint: \"Bearer API key for the Empower OpenAI-compatible endpoint.\",\n apiHint:\n \"Empower exposes OpenAI-compatible chat on https://app.empower.dev/api/v1 with tool-calling support on empower-functions.\",\n passthroughModels: true,\n },\n poe: {\n id: \"poe\",\n alias: \"poe\",\n name: \"Poe\",\n icon: \"hub\",\n color: \"#F97316\",\n textIcon: \"PO\",\n website: \"https://creator.poe.com/api-reference\",\n authHint: \"Bearer API key for the Poe OpenAI-compatible API.\",\n apiHint:\n \"Poe exposes OpenAI-compatible chat and responses on https://api.poe.com/v1, with authenticated balance checks on /usage/current_balance.\",\n passthroughModels: true,\n },\n chutes: {\n id: \"chutes\",\n alias: \"chutes\",\n name: \"Chutes.ai\",\n icon: \"hub\",\n color: \"#06B6D4\",\n textIcon: \"CH\",\n website: \"https://chutes.ai\",\n hasFree: false,\n freeNote:\n \"No free tier as of 2026 — Chutes moved to pay-as-you-go (free Early Access ended 2026-03).\",\n authHint: \"Bearer API key for the Chutes OpenAI-compatible gateway.\",\n passthroughModels: true,\n },\n // Factory AI (\"Factory Droids\") subscription gateway — the same backend the\n // local `droid` CLI shells into, exposed here as an OpenAI-compatible HTTP\n // endpoint. Auth surface per https://github.com/Factory-AI/droid-sdk-typescript\n // is `FACTORY_API_KEY` (Bearer). Subscription tier uses app.factory.ai quota.\n factory: {\n id: \"factory\",\n alias: \"factory\",\n name: \"Factory\",\n icon: \"smart_toy\",\n color: \"#0F172A\",\n textIcon: \"FA\",\n website: \"https://factory.ai\",\n authHint: \"Bearer API key for the Factory OpenAI-compatible gateway.\",\n apiHint:\n \"Get your Factory API key at https://app.factory.ai/settings/api-keys, then paste it as a Bearer token. OpenAI-compatible endpoint at https://api.factory.ai/v1.\",\n passthroughModels: true,\n },\n bluesminds: {\n id: \"bluesminds\",\n alias: \"bm\",\n name: \"BluesMinds\",\n icon: \"psychology\",\n color: \"#3B82F6\",\n textIcon: \"BM\",\n website: \"https://www.bluesminds.com\",\n hasFree: true,\n freeNote:\n \"Free daily pi credits — supports 200+ models including GPT-4o, GPT-4.1, Claude Sonnet 4.5, Gemini 2.0 Flash, DeepSeek V4, Qwen, Kimi K2\",\n apiHint:\n \"Get your API key at https://www.bluesminds.com — OpenAI-compatible endpoint at https://api.bluesminds.com/v1 with free daily credits. VIP models (Claude Opus 4.5, Gemini 2.5 Pro) consume pi credits.\",\n },\n \"freemodel-dev\": {\n id: \"freemodel-dev\",\n alias: \"fmd\",\n name: \"FreeModel.dev\",\n icon: \"auto_awesome\",\n color: \"#8B5CF6\",\n textIcon: \"FM\",\n website: \"https://freemodel.dev\",\n hasFree: true,\n freeNote:\n \"$300 free credits on signup — no credit card required. Access GPT-5.4 and GPT-5.5 (OpenAI's latest flagship models) through an OpenAI-compatible API.\",\n apiHint:\n \"Get $300 free API credits at https://freemodel.dev — no payment info required. OpenAI-compatible endpoint. GPT-5.4 and GPT-5.5 models available.\",\n },\n freeaiapikey: {\n id: \"freeaiapikey\",\n alias: \"faik\",\n name: \"FreeAIAPIKey\",\n icon: \"vpn_key\",\n color: \"#F59E0B\",\n textIcon: \"FK\",\n website: \"https://freeaiapikey.com\",\n apiHint:\n \"Discounted API proxy for 40+ models including GPT-5, Claude Opus 4.6, Claude Sonnet 4.6, Qwen 3.5. Get your API key at https://freeaiapikey.com/dashboard. Base URL: https://freeaiapikey.com/v1.\",\n },\n zenmux: {\n id: \"zenmux\",\n alias: \"zm\",\n name: \"ZenMux\",\n icon: \"neurology\",\n color: \"#7C3AED\",\n textIcon: \"ZM\",\n website: \"https://zenmux.ai\",\n hasFree: true,\n freeNote:\n \"Free tier includes access to Gemini 3 Flash, DeepSeek V3.2, Grok 4.1 Fast, Mistral Large, and more. Get your API key at https://zenmux.ai.\",\n authHint:\n \"Use your ZenMux API key in Authorization: Bearer <key>. ZenMux is fully OpenAI-compatible. Base URL: https://zenmux.ai/api/v1.\",\n apiHint:\n \"ZenMux exposes an OpenAI-compatible chat completions endpoint at /api/v1/chat/completions, plus Anthropic Messages (/api/anthropic/v1/messages) and Google Gemini (/api/vertex-ai) protocol surfaces. OmniRoute uses the OpenAI protocol.\",\n },\n openadapter: {\n id: \"openadapter\",\n alias: \"oad\",\n name: \"OpenAdapter\",\n icon: \"hub\",\n color: \"#10B981\",\n textIcon: \"OD\",\n website: \"https://openadapter.dev\",\n hasFree: true,\n freeNote:\n \"Free tier with a generous quota and no credit card — 15+ open-source models with daily quota. Get your API key at https://dashboard.openadapter.in.\",\n authHint:\n \"Use your OpenAdapter API key in Authorization: Bearer sk-cv-<key>. Fully OpenAI-compatible. API base URL: https://api.openadapter.in/v1.\",\n apiHint:\n \"OpenAdapter exposes an OpenAI-compatible chat completions endpoint at https://api.openadapter.in/v1/chat/completions, aggregating 70+ open-source models (DeepSeek, Qwen, Kimi, MiniMax, GLM, Llama, Mistral, …). OmniRoute uses the OpenAI protocol.\",\n },\n dit: {\n id: \"dit\",\n alias: \"dai\",\n name: \"DIT.ai\",\n icon: \"hub\",\n color: \"#0EA5E9\",\n textIcon: \"DT\",\n website: \"https://dit.ai\",\n authHint:\n \"Use your dit.ai API key in Authorization: Bearer <key>. Fully OpenAI-compatible — a drop-in replacement, just change the base URL to https://api.dit.ai/v1.\",\n apiHint:\n \"dit.ai (Distributed Intelligence Trade) is an OpenAI-compatible router/gateway with dynamic per-request pricing, exposing /v1/chat/completions at https://api.dit.ai/v1. OmniRoute uses the OpenAI protocol; spend/savings analytics live in the dit.ai dashboard.\",\n },\n tokenrouter: {\n id: \"tokenrouter\",\n alias: \"trk\",\n name: \"TokenRouter\",\n icon: \"hub\",\n color: \"#F59E0B\",\n textIcon: \"TK\",\n website: \"https://tokenrouter.com\",\n hasFree: true,\n freeNote:\n \"Free tier includes the MiniMax 3 model. Get your API key at https://tokenrouter.com.\",\n authHint:\n \"Use your TokenRouter API key in Authorization: Bearer <key>. Fully OpenAI-compatible. API base URL: https://api.tokenrouter.com/v1.\",\n apiHint:\n \"TokenRouter exposes an OpenAI-compatible chat completions endpoint at https://api.tokenrouter.com/v1/chat/completions, plus a working /v1/models catalog. OmniRoute uses the OpenAI protocol.\",\n },\n sumopod: {\n id: \"sumopod\",\n alias: \"sumopod\",\n name: \"SumoPod\",\n icon: \"router\",\n color: \"#2563EB\",\n textIcon: \"SP\",\n passthroughModels: true,\n website: \"https://ai.sumopod.com\",\n authHint:\n \"Use your SumoPod API key (sk-...) in Authorization: Bearer <key>. Fully OpenAI-compatible. API base URL: https://ai.sumopod.com/v1.\",\n apiHint:\n \"SumoPod exposes an OpenAI-compatible chat completions endpoint at https://ai.sumopod.com/v1/chat/completions, plus a live /v1/models catalog. OmniRoute uses the OpenAI protocol and lists models via passthrough.\",\n },\n x5lab: {\n id: \"x5lab\",\n alias: \"x5lab\",\n name: \"X5Lab\",\n icon: \"router\",\n color: \"#7C3AED\",\n textIcon: \"X5\",\n passthroughModels: true,\n website: \"https://x5lab.dev\",\n authHint:\n \"Use your X5Lab API key (x5-...) in Authorization: Bearer <key>. Fully OpenAI-compatible. API base URL: https://api.x5lab.dev/v1.\",\n apiHint:\n \"X5Lab exposes an OpenAI-compatible chat completions endpoint at https://api.x5lab.dev/v1/chat/completions, plus a live /v1/models catalog. OmniRoute uses the OpenAI protocol and lists models via passthrough.\",\n },\n chenzk: {\n id: \"chenzk\",\n alias: \"chenzk\",\n name: \"Chenzk API\",\n icon: \"hub\",\n color: \"#10B981\",\n textIcon: \"CZ\",\n passthroughModels: true,\n website: \"https://chenzk.top\",\n apiHint:\n \"Create an API key at https://chenzk.top/token, then paste it here as a Bearer token. \" +\n \"OpenAI-compatible endpoint at https://chenzk.top/v1, with a live /v1/models catalog.\",\n },\n kenari: {\n id: \"kenari\",\n alias: \"kenari\",\n name: \"Kenari\",\n icon: \"hub\",\n color: \"#B5362A\",\n textIcon: \"KN\",\n passthroughModels: true,\n website: \"https://kenari.id\",\n authHint:\n \"Use your Kenari API key (kn-...) in Authorization: Bearer <key>. Fully OpenAI-compatible. API base URL: https://kenari.id/v1.\",\n apiHint:\n \"Kenari exposes an OpenAI-compatible chat completions endpoint at https://kenari.id/v1/chat/completions, plus a live /v1/models catalog covering Claude, GPT, DeepSeek, GLM, Kimi and more. OmniRoute uses the OpenAI protocol and lists models via passthrough.\",\n },\n navy: {\n id: \"navy\",\n alias: \"navy\",\n name: \"NavyAI\",\n icon: \"hub\",\n color: \"#1E3A8A\",\n textIcon: \"NV\",\n passthroughModels: true,\n website: \"https://api.navy\",\n hasFree: true,\n freeNote:\n \"Free plan is one shared 150K tokens/day pool at 20 RPM. Each model carries a \" +\n \"token multiplier, so heavier models drain the pool faster (grok-4 at 10x is ~15K real tokens/day).\",\n authHint:\n \"Create a free API key from the NavyAI dashboard, then paste it here as a Bearer token.\",\n apiHint:\n \"OpenAI-compatible endpoint at https://api.navy/v1 with a live /v1/models catalog that exposes \" +\n \"per-model token_multiplier and premium flags. Upstream requires an explicit User-Agent header.\",\n },\n};\n"}}, "omniroute/docs/i18n/zh-CN/docs/reference/CLI-TOOLS.md": {"6eea4894299d5371c00c11f1f6dec2f7c0076253": {"t": 1785596434.3110518, "n": 24168, "h": "f2febed5995ea9c8", "c": "---\ntitle: \"CLI 工具 — OmniRoute\"\nversion: 3.8.40\nlastUpdated: 2026-06-28\n---\n\n# CLI 工具 — OmniRoute\n\n最后更新:2026-06-28\n\nOmniRoute 与三类 CLI 工具集成,分布在三个专用的 dashboard 页面中:\n\n| 页面 | 路由 | 概念 | 数量 |\n| ---------------- | ------------------------ | --------------------------------------------------------------------------- | ------------ |\n| **CLI Code's** | `/dashboard/cli-code` | 指向 OmniRoute 的编程工具(客户端 → CLI → OmniRoute → 服务商) | 19 |\n| **CLI Agents** | `/dashboard/cli-agents` | 指向 OmniRoute 的自主代理(相同流程,更广泛的范围) | 6 |\n| **ACP Agents** | `/dashboard/acp-agents` | OmniRoute 通过 stdio/ACP 作为后端启动的 CLI(反向流程) | 见注册表 |\n\n旧路由通过 308 重定向:`/dashboard/cli-tools` → `/dashboard/cli-code`,`/dashboard/agents` → `/dashboard/acp-agents`。\n\n---\n\n## 工作原理\n\n```\nCLI Code's / CLI Agents(消费流程):\nClaude / Codex / OpenCode / Cline / KiloCode / Continue / Hermes Agent / Goose / ...\n │\n ▼ (全部指向 OmniRoute)\n http://YOUR_SERVER:20128/v1\n │\n ▼ (OmniRoute 路由到合适的服务商)\n Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...\n\nACP Agents(反向启动流程):\n 客户端请求 → OmniRoute → 通过 stdio/ACP 启动 CLI → 响应\n```\n\n**优势:**\n\n- 一个 API Key 管理所有工具\n- 在 dashboard 中追踪所有 CLI 的成本\n- 无需重新配置每个工具即可切换模型\n- 在本地和远程服务器(VPS、Docker、Akamai、Cloudflare Tunnel)均可使用\n\n---\n\n## 使用 `setup-*` 自动配置\n\n无需手动编写每个工具的配置。OmniRoute 为每个支持的 CLI 提供对应的 `setup-*` 命令,该命令从运行中的 OmniRoute(本地或远程)读取**实时**模型目录并将工具的配置写入你的机器:\n\n```bash\nomniroute setup-codex omniroute setup-claude omniroute setup-opencode\nomniroute setup-cline omniroute setup-kilo omniroute setup-continue\nomniroute setup-cursor omniroute setup-roo omniroute setup-crush\nomniroute setup-goose omniroute setup-qwen omniroute setup-aider\n```\n\n每个命令接受 `--remote <url> --api-key <key>`(针对远程 OmniRoute 配置本地工具)、`--dry-run`(预览不写入)和 `--port`。不支持模型自动发现的工具(Cline、Kilo、Roo、Goose、Qwen、Aider、Gemini)接受 `--model <id>`(以及用于非交互式运行的 `--yes`)。启动器 `omniroute launch`(Claude Code)和 `omniroute launch-codex`(Codex)在注入正确的环境变量后启动 CLI,不写入任何配置。\n\n> **完整参考:** 主表 — 每个命令写入的内容、所有标志、本地 vs 远程,以及哪些工具需要 `/v1` 后缀 — 在 **[CLI Integrations](../guides/CLI-INTEGRATIONS.md)** 中。\n\n---\n\n## 数据源\n\n统一目录位于 `src/shared/constants/cliTools.ts`,定义为 `CLI_TOOLS: Record<string, CliCatalogEntry>`。\n\n每个条目包含以下字段(定义在 `src/shared/schemas/cliCatalog.ts`):\n\n| 字段 | 类型 | 说明 |\n| ------------------------------------------------ | ------------------------------------------------------------ | -------------------------------------------------------- |\n| `category` | `\"code\" \\| \"agent\"` | 工具显示的页面 |\n| `vendor` | `string` | 工具来源(\"Anthropic\"、\"OSS (P. Gauthier)\") |\n| `acpSpawnable` | `boolean` | 也可作为 ACP Agent 使用(显示徽章) |\n| `baseUrlSupport` | `\"full\" \\| \"partial\" \\| \"none\"` | 自定义端点支持级别。`\"none\"` = MITM 待办列表 |\n| `configType` | `\"env\" \\| \"custom\" \\| \"guide\" \\| \"custom-builder\" \\| \"mitm\"` | 配置机制 |\n| `id`、`name`、`color`、`description`、`docsUrl` | 标准字段 | 核心显示字段 |\n\n`baseUrlSupport: \"none\"` 的条目**不会显示**在 dashboard 页面中 — 它们注册在 MITM 待办列表中,供 plan 11 使用(参见 `_tasks/features-v3.8.6/refactorpages/_orchestration/_plan11-mitm-backlog.md`)。\n\n---\n\n## 1. CLI Code's 目录(19 个工具)\n\n支持自定义 base URL 并出现在 `/dashboard/cli-code` 中的工具:\n\n| id | name | vendor | baseUrlSupport | configType | acpSpawnable |\n|----|------|--------|---------------|-----------|-------------|\n| claude | Claude Code | Anthropic | full | env | true |\n| codex | OpenAI Codex CLI | OpenAI | full | custom | true |\n| cline | Cline | OSS (ex-Claude Dev) | full | custom | true |\n| kilo | Kilo Code | Kilo-Org | full | custom | false |\n| roo | Roo Code | Roo (OSS) | full | guide | false |\n| continue | Continue | continue.dev | full | guide | false |\n| qwen | Qwen Code | Alibaba | full | guide | true |\n| aider | Aider | OSS (P. Gauthier) | full | guide | true |\n| forge | ForgeCode | Antinomy HQ | full | custom | true |\n| jcode | jcode | 1jehuang (OSS) | full | custom | false |\n| deepseek-tui | DeepSeek TUI | Hunter Bown (OSS) | full | custom | false |\n| opencode | OpenCode | Anomaly (ex-SST) | full | guide | true |\n| droid | Factory Droid | Factory AI | partial | guide | false |\n| copilot | GitHub Copilot CLI | GitHub/MS | full | custom | false |\n| cursor-cli | Cursor CLI | Anysphere | partial | guide | true |\n| smelt | Smelt | leonardcser (OSS) | full | custom | false |\n| pi | Pi (pi-coding-agent) | M. Zechner (OSS) | full | custom | false |\n| custom | Custom CLI | — | full | custom-builder | false |\n\n`baseUrlSupport: \"partial\"` 的工具在 dashboard 卡片中显示徽章 \"⚠ Base URL parcial\"。\n\n---\n\n## 2. CLI Agents 目录(6 个工具)\n\n出现在 `/dashboard/cli-agents` 中的自主代理:\n\n| id | name | vendor | baseUrlSupport | acpSpawnable |\n| ------------ | ---------------- | ------------------------ | -------------- | ------------ |\n| hermes-agent | Hermes Agent | Nous Research | full | false |\n| openclaw | OpenClaw | OSS (P. Steinberger) | full | true |\n| goose | Goose | Block / Linux Foundation | full | true |\n| interpreter | Open Interpreter | OSS | full | true |\n| warp | Warp AI | Warp Inc. | partial | true |\n| agent-deck | Agent Deck | asheshgoplani (OSS) | full | false |\n\n---\n\n## 3. ACP Agents(/dashboard/acp-agents)\n\n此页面(从 `/dashboard/agents` 重命名而来)显示 OmniRoute 可以通过 stdio/ACP 协议**启动**为后端执行引擎的 CLI。目录在 `src/lib/acp/registry.ts` 中单独维护,**不同于** `CLI_TOOLS`。\n\n---\n\n## 4. MITM 待办列表(不在 dashboard 中显示)\n\n以下 CLI 原生不支持自定义 base URL,因此**不会**在 CLI Code's 或 CLI Agents 页面中列出。它们是 plan 11 中 MITM 拦截的候选项:\n\n| CLI | 原因 |\n| ------------------- | ------------------------------------------------------------- |\n| windsurf | BYOK 限于部分 Claude 模型 + 企业 URL/Token |\n| amp | 封闭生态系统(Sourcegraph) |\n| amazon-q / kiro-cli | AWS SSO 认证,无自定义 URL |\n| cowork | Anthropic Desktop,无可配置端点 |\n\n完整对照参见 `_tasks/features-v3.8.6/refactorpages/_orchestration/_plan11-mitm-backlog.md`。\n\n---\n\n## 5. 批量检测 API\n\n所有工具检测通过单个端点聚合:\n\n**`GET /api/cli-tools/all-statuses`**\n\n- 认证:`requireCliToolsAuth(request)`(与其他 `/api/cli-tools/` 路由相同)\n- 返回:`Record<toolId, ToolBatchStatus>`(类型:`src/shared/types/cliBatchStatus.ts`)\n- 策略:对全部工具执行 `Promise.all`,每个工具 5 秒超时\n- 缓存:以配置文件 `mtime` 为索引的内存 LRU 缓存。当 mtime 变化时缓存失效。服务器重启时重置。\n\n每个工具的响应结构:\n\n```ts\ninterface ToolBatchStatus {\n detection: {\n installed: boolean;\n runnable: boolean;\n version?: string;\n command?: string;\n commandPath?: string;\n reason?: string;\n };\n config: {\n status: \"configured\" | \"not_configured\" | \"not_installed\" | \"unknown\" | \"other\";\n endpoint?: string | null;\n lastConfiguredAt?: string | null;\n };\n error?: string; // 已脱敏,无堆栈跟踪\n}\n```\n\n---\n\n## 6. 新工具的 Settings 处理器\n\n`configType: \"custom\"` 的新工具具有专用的 settings API 路由:\n\n| 路由 | 工具 |\n| -------------------------------------------- | -------------------------------- |\n| `POST /api/cli-tools/forge-settings` | ForgeCode (.forge.toml) |\n| `POST /api/cli-tools/jcode-settings` | jcode (--base-url 标志) |\n| `POST /api/cli-tools/deepseek-tui-settings` | DeepSeek TUI (OPENAI_BASE_URL) |\n| `POST /api/cli-tools/smelt-settings` | Smelt |\n| `POST /api/cli-tools/pi-settings` | Pi coding agent |\n\n所有路由均使用 `sanitizeErrorMessage()` 处理错误响应(Hard Rule #12)。\n\n---\n\n## 7. Dashboard 页面架构\n\n### CLI Code's(`/dashboard/cli-code`)\n\n- `src/app/(dashboard)/dashboard/cli-code/page.tsx` — 服务端组件\n- `src/app/(dashboard)/dashboard/cli-code/CliCodePageClient.tsx` — 客户端网格\n- `src/app/(dashboard)/dashboard/cli-code/[id]/page.tsx` — 工具详情页\n- `src/app/(dashboard)/dashboard/cli-code/components/` — 12 个专用工具卡片 + `ToolDetailClient.tsx`\n\n### CLI Agents(`/dashboard/cli-agents`)\n\n- `src/app/(dashboard)/dashboard/cli-agents/page.tsx` — 服务端组件\n- `src/app/(dashboard)/dashboard/cli-agents/CliAgentsPageClient.tsx` — 客户端网格\n- `src/app/(dashboard)/dashboard/cli-agents/[id]/page.tsx` — 复用 `ToolDetailClient`\n\n### ACP Agents(`/dashboard/acp-agents`)\n\n- `src/app/(dashboard)/dashboard/acp-agents/page.tsx` — 服务端组件(从 `agents/` 迁移而来)\n\n### 共享 UI 组件(`src/shared/components/cli/`)\n\n| 文件 | 用途 |\n| ------------------------- | --------------------------------------------------- |\n| `CliToolCard.tsx` | 智能状态卡片(检测 + 配置 + 端点) |\n| `CliConceptCard.tsx` | 每页概念说明卡片 |\n| `CliComparisonCard.tsx` | 三类 CLI 对比卡 |\n| `BaseUrlSelect.tsx` | 端点下拉选择(本地/云端/自定义) |\n| `ApiKeySelect.tsx` | API Key 选择器 |\n| `ManualConfigModal.tsx` | 可复制的配置片段弹窗 |\n\n### 共享 Hook(`src/shared/hooks/cli/`)\n\n| 文件 | 用途 |\n| --------------------------- | --------------------------------------------------------------------- |\n| `useToolBatchStatuses.ts` | 获取 `/api/cli-tools/all-statuses`,管理 loading/refresh 状态 |\n\n---\n\n## 8. i18n\n\n在 plan 14 F9 中添加的新命名空间:\n\n| 命名空间 | 用途 |\n| ----------- | ---------------------------------------------------------------------------- |\n| `cliCommon` | 共享字符串(卡片标签、概念/对比文本、详情页标签) |\n| `cliCode` | CLI Code's 页面字符串 |\n| `cliAgents` | CLI Agents 页面字符串 |\n| `acpAgents` | ACP Agents 页面字符串 |\n\n提供完整的 PT-BR 和 EN 翻译。其余 39 个语言环境通过 `src/i18n/request.ts` 中的命名空间级合并自动回退到 EN。\n\n---\n\n## 9. 快速开始\n\n### 步骤 1 — 获取 OmniRoute API Key\n\n1. 打开 `/dashboard/api-manager` → **创建 API Key**\n2. 为其命名(例如 `cli-tools`)并选择所有权限\n3. 复制 Key — 以下所有 CLI 都会用到\n\n> 你的 Key 格式为:`sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`\n\n---\n\n### 步骤 2 — 安装 CLI 工具\n\n所有基于 npm 的工具需要 Node.js 22.22.2+ 或 24.x:\n\n```bash\n# Claude Code (Anthropic)\nnpm install -g @anthropic-ai/claude-code\n\n# OpenAI Codex\nnpm install -g @openai/codex\n\n# OpenCode\nnpm install -g opencode-ai\n\n# Cline\nnpm install -g cline\n\n# KiloCode\nnpm install -g kilocode\n\n# Qwen Code (Alibaba)\nnpm install -g @qwen-code/qwen-code\n\n# Aider\npip install aider-chat\n\n# Smelt\ncargo install smelt # Rust 编写\n\n# Pi coding agent\n# 安装参见 https://github.com/zechnerj/pi-coding-agent\n\n# jcode\n# 安装参见 https://github.com/1jehuang/jcode\n```\n\n---\n\n### 步骤 3 — 通过 Dashboard 配置\n\n1. 访问 `http://localhost:20128/dashboard/cli-code`\n2. 在网格中找到你的工具\n3. 点击卡片进入工具详情页\n4. 选择你的 API Key 和 base URL\n5. 点击**应用配置**或复制手动配置片段\n\n---\n\n### 步骤 4 — 设置全局环境变量\n\n```bash\n# OmniRoute 通用端点\nexport OPENAI_BASE_URL=\"http://localhost:20128/v1\"\nexport OPENAI_API_KEY=\"sk-your-omniroute-key\"\nexport ANTHROPIC_BASE_URL=\"http://localhost:20128\"\nexport ANTHROPIC_AUTH_TOKEN=\"sk-your-omniroute-key\"\nexport GEMINI_BASE_URL=\"http://localhost:20128/v1\"\nexport GEMINI_API_KEY=\"sk-your-omniroute-key\"\n```\n\n> 对于**远程服务器**,将 `localhost:20128` 替换为服务器的 IP 或域名,\n> 例如 `http://<your-server-ip>:20128`。\n\n---\n\n### 步骤 4 — 配置每个工具\n\n#### Claude Code\n\n```bash\n# 创建 ~/.claude/settings.json:\nmkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF\n{\n \"env\": {\n \"ANTHROPIC_BASE_URL\": \"http://localhost:20128\",\n \"ANTHROPIC_AUTH_TOKEN\": \"sk-your-omniroute-key\"\n }\n}\nEOF\n```\n\nClaude Code 使用统一的 Anthropic 网关根路径。不要在这里添加 `/v1`。\n\n**测试:** `claude \"say hello\"`\n\n---\n\n#### OpenAI Codex\n\n```bash\nmkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF\nmodel: auto\napiKey: sk-your-omniroute-key\napiBaseUrl: http://localhost:20128/v1\nEOF\n```\n\n**测试:** `codex \"what is 2+2?\"`\n\n---\n\n#### OpenCode\n\n```bash\nmkdir -p ~/.config/opencode && cat > ~/.config/opencode/opencode.json << EOF\n{\n \"\\$schema\": \"https://opencode.ai/config.json\",\n \"provider\": {\n \"omniroute\": {\n \"npm\": \"@ai-sdk/openai-compatible\",\n \"name\": \"OmniRoute\",\n \"options\": {\n \"baseURL\": \"http://localhost:20128/v1\",\n \"apiKey\": \"sk-your-omniroute-key\"\n },\n \"models\": {\n \"claude-sonnet-4-5\": { \"name\": \"claude-sonnet-4-5\" },\n \"claude-sonnet-4-5-thinking\": { \"name\": \"claude-sonnet-4-5-thinking\" },\n \"gemini-3-flash\": { \"name\": \"gemini-3-flash\" }\n }\n }\n }\n}\nEOF\n```\n\n**测试:** `opencode`\n\n> 使用 `opencode run \"your prompt\" --model omniroute/claude-sonnet-4-5-thinking --variant high`\n> 发送 thinking 变体。\n\n---\n\n#### Cline(CLI 或 VS Code)\n\n**CLI 模式:**\n\n```bash\nmkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF\n{\n \"apiProvider\": \"openai\",\n \"openAiBaseUrl\": \"http://localhost:20128/v1\",\n \"openAiApiKey\": \"sk-your-omniroute-key\"\n}\nEOF\n```\n\n**VS Code 模式:**\nCline 扩展设置 → API Provider:`OpenAI Compatible` → Base URL:`http://localhost:20128/v1`\n\n或使用 OmniRoute dashboard → **CLI Tools → Cline → 应用配置**。\n\n---\n\n#### KiloCode(CLI 或 VS Code)\n\n**CLI 模式:**\n\n```bash\nkilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key\n```\n\n**VS Code 设置:**\n\n```json\n{\n \"kilo-code.openAiBaseUrl\": \"http://localhost:20128/v1\",\n \"kilo-code.apiKey\": \"sk-your-omniroute-key\"\n}\n```\n\n或使用 OmniRoute dashboard → **CLI Tools → KiloCode → 应用配置**。\n\n---\n\n#### Continue(VS Code 扩展)\n\n编辑 `~/.continue/config.yaml`:\n\n```yaml\nmodels:\n - name: OmniRoute\n provider: openai\n model: auto\n apiBase: http://localhost:20128/v1\n apiKey: sk-your-omniroute-key\n default: true\n```\n\n编辑后重启 VS Code。\n\n---\n\n#### VS Code Insiders(`chatLanguageModels.json`)\n\n当 VS Code Insiders 配置了自定义端点模型,且你希望 OmniRoute 在不使用自定义请求头字段的情况下工作时使用。\n\n**推荐位置:**\n\n- Linux:`~/.config/Code - Insiders/User/chatLanguageModels.json`\n- Windows:`%APPDATA%/Code - Insiders/User/chatLanguageModels.json`\n\n**使用 Token 化 OmniRoute 别名的示例:**\n\n```json\n[\n {\n \"vendor\": \"customendpoint\",\n \"id\": \"auto\",\n \"name\": \"OmniRoute Auto\",\n \"family\": \"gpt-4\",\n \"version\": \"1.0.0\",\n \"url\": \"http://localhost:20128/api/v1/vscode/sk-your-omniroute-key/chat/completions\",\n \"modelsUrl\": \"http://localhost:20128/api/v1/vscode/sk-your-omniroute-key/models\",\n \"requestFormat\": \"openai-chat-completions\",\n \"contextWindow\": 256000,\n \"maxOutputTokens\": 32768,\n \"auth\": {\n \"type\": \"none\"\n }\n }\n]\n```\n\n**说明:**\n\n- 将 `sk-your-omniroute-key` 替换为在 OmniRoute 中创建的 API Key。\n- `url` 字段应指向 `/api/v1/vscode/{token}/chat/completions`。\n- `modelsUrl` 字段应指向 `/api/v1/vscode/{token}/models`。\n- 只要客户端支持自定义请求头,应优先使用正常的 `/v1` + Bearer 请求头流程。\n- URL 嵌入的 Token 是兼容性回退方案,可能出现在编辑器日志或代理历史中。\n\n---\n\n#### Kiro CLI(Amazon)\n\n```bash\n# 登录你的 AWS/Kiro 账户:\nkiro-cli login\n\n# CLI 使用自己的认证 — Kiro CLI 本身不需要 OmniRoute 作为后端。\n# 将 kiro-cli 与 OmniRoute 配合用于其他工具。\nkiro-cli status\n```\n\n对于 **Kiro IDE** 桌面应用,使用 OmniRoute 通过 `/dashboard/cli-tools → Kiro` 暴露的 MITM 端点。\n\n---\n\n#### Qwen Code(Alibaba)\n\nQwen Code 通过环境变量或 `settings.json` 支持 OpenAI 兼容的 API 端点。\n\n> Qwen OAuth 免费层已于 2026-04-15 停用。改为使用 OmniRoute 搭配\n> `bailian-coding-plan` / `alibaba` / `alibaba-cn` / `openrouter` / `anthropic` /\n> `gemini` 服务商。\n\n**选项 1:环境变量(`~/.qwen/.env`)**\n\n```bash\nmkdir -p ~/.qwen && cat > ~/.qwen/.env << EOF\nOPENAI_API_KEY=\"sk-your-omniroute-key\"\nOPENAI_BASE_URL=\"http://localhost:20128/v1\"\nOPENAI_MODEL=\"auto\"\nEOF\n```\n\n**选项 2:`settings.json` 配合 `security.auth`**\n\n```json\n// ~/.qwen/settings.json\n{\n \"security\": {\n \"auth\": {\n \"selectedType\": \"openai\",\n \"apiKey\": \"sk-your-omniroute-key\",\n \"baseUrl\": \"http://localhost:20128/v1\"\n }\n },\n \"model\": {\n \"name\": \"claude-sonnet-4-6\"\n }\n}\n```\n\n**选项 3:内联 CLI 标志**\n\n```bash\nOPENAI_BASE_URL=\"http://localhost:20128/v1\" \\\nOPENAI_API_KEY=\"sk-your-omniroute-key\" \\\nOPENAI_MODEL=\"auto\" \\\nqwen\n```\n\n> 对于**远程服务器**,将 `localhost:20128` 替换为服务器的 IP 或域名。\n\n---\n\n## 10. OmniRoute 内置 CLI\n\n`omniroute` 二进制文件提供服务端生命周期、设置、诊断和服务商管理的命令。入口点:`bin/omniroute.mjs`。\n\n```bash\nomniroute # 启动服务器(默认端口 20128)\nomniroute setup # 交互式设置向导\nomniroute doctor # 检查配置、数据库、端口、运行时\nomniroute providers list # 已配置的服务商连接\nomniroute providers test-all # 测试所有活跃连接\nomniroute reset-password # 重置管理员密码\nomniroute logs # 流式输出请求日志\nomniroute health # 详细健康状态(熔断器、缓存、内存)\nomniroute --version # 输出版本号\nomniroute --help # 显示所有命令\n```\n\n### 设置与初始化\n\n```bash\nomniroute setup # 交互式设置向导\nomniroute setup --non-interactive # CI/自动化模式(读取环境变量 + 标志)\nomniroute setup --password '<value>' # 直接设置管理员密码\nomniroute setup --add-provider \\\n --provider openai \\\n --api-key '<value>' \\\n --test-provider # 一步添加并测试服务商\n```\n\n非交互式设置识别的环境变量:\n\n| 变量 | 用途 |\n| ------------------- | ----------------------------------------------------------- |\n| `OMNIROUTE_API_KEY` | 服务商 API Key(通过 Commander `.env()` 绑定到 `--api-key`) |\n| `DATA_DIR` | 覆盖 OmniRoute 数据目录 |\n\n其他所有非交互式输入通过标志传入,而非环境变量:\n`--password`、`--provider`、`--provider-name`、`--provider-base-url`、`--default-model`\n(参见上述 `omniroute setup` 选项)。\n\n### 诊断\n\n```bash\nomniroute doctor # 检查配置、数据库、端口、运行时、内存、存活状态\nomniroute doctor --json # 机器可读的 JSON\nomniroute doctor --no-liveness # 跳过 HTTP 健康探测\nomniroute doctor --host 0.0.0.0 # 覆盖存活探测的主机\nomniroute doctor --liveness-url <url> # 完全覆盖健康端点 URL\n```\n\ndoctor 运行以下检查:`Config`、`Database`、`Storage/encryption`、`Port availability`、`Node runtime`、`Native binary`(better-sqlite3)、`Memory` 和 `Server liveness`。任何检查为 `fail` 时以非零退出码退出。\n\n### 服务商管理\n\n```bash\nomniroute providers available # OmniRoute 服务商目录\nomniroute providers available --search openai # 按 id/name/alias/category 过滤目录\nomniroute providers available --category api-key # 按分类过滤(api-key、oauth、free 等)\nomniroute providers available --json # 机器可读的 JSON\n\nomniroute providers list # 已配置的服务商连接\nomniroute providers list --json\n\nomniroute providers test <id|name> # 测试一个已配置的连接\nomniroute providers test-all # 测试所有活跃连接\nomniroute providers validate # 仅本地结构校验\n```\n\n> `providers available` 读取 OmniRoute 目录;`providers list/test/test-all/validate`\n> 直接读取本地 SQLite 数据库,不需要服务器运行。\n\n### 恢复与重置\n\n```bash\nomniroute reset-password # 重置管理员密码(旧别名仍然可用)\nomniroute reset-encrypted-columns # 显示加密凭证重置的警告 + 干运行\nomniroute reset-encrypted-columns --force # 实际在 SQLite 中将加密凭证设为 null\n```\n\n### 其他子命令\n\n以下命令假定 OmniRoute 服务器正在运行(另有说明除外):\n\n```bash\nomniroute status # 全面的运行时状态\nomniroute logs # 流式输出请求日志(--json、--search、--follow)\nomniroute config show # 显示当前配置\n\nomniroute provider list # 列出可用服务商(providers list 的别名)\nomniroute provider add # 将 OmniRoute 注册为某个工具的服务商\nomniroute keys add | list | remove # 管理 API Key\nomniroute models [provider] # 列出模型(--json、--search)\nomniroute combo list | switch | create | delete\n\nomniroute backup # 快照配置 + 数据库\nomniroute restore # 从之前的快照恢复\n\nomniroute health # 详细健康状态(熔断器、缓存、内存)\nomniroute quota # 服务商配额用量\nomniroute cache # 缓存状态\nomniroute cache clear # 清除语义 + 签名缓存\n\nomniroute mcp status | restart # MCP 服务器状态 / 重启\nomniroute a2a status | card # A2A 服务器状态 / agent card\n\nomniroute tunnel list | create | stop # 管理隧道(cloudflare/tailscale/ngrok)\nomniroute env show | get <k> | set <k> <v> # 检查 / 设置环境变量(临时)\n\nomniroute test # 服务商连通性冒烟测试\nomniroute update # 检查更新\nomniroute completion # 生成 shell 补全\n```\n\n### 通用标志\n\n| 标志 | 说明 |\n| ------------------- | ------------------------------------------------------ |\n| `--no-open` | 启动时不自动打开浏览器 |\n| `--port <n>` | 覆盖 API 端口(默认 20128) |\n| `--mcp` | 以 MCP 服务器通过 stdio 运行(供 IDE 使用) |\n| `--non-interactive` | CI 模式(无交互提示;从 env/flags 读取) |\n| `--json` | 机器可读的 JSON 输出(doctor、providers 等) |\n| `--help`、`-h` | 显示命令特定的帮助 |\n| `--version`、`-v` | 输出版本号 |\n\n---\n\n## 可用 API 端点\n\n| 端点 | 说明 | 用途 |\n| ---------------------------- | ------------------------------ | -------------------------- |\n| `/v1/chat/completions` | 标准聊天(所有服务商) | 所有现代工具 |\n| `/v1/responses` | Responses API(OpenAI 格式) | Codex、代理工作流 |\n| `/v1/completions` | 旧版文本补全 | 使用 `prompt:` 的旧工具 |\n| `/v1/embeddings` | 文本嵌入 | RAG、搜索 |\n| `/v1/images/generations` | 图像生成 | GPT-Image、Flux 等 |\n| `/v1/audio/speech` | 文本转语音 | ElevenLabs、OpenAI TTS |\n| `/v1/audio/transcriptions` | 语音转文本 | Deepgram、AssemblyAI |\n\n可直接粘贴的示例(使用 Token 化 OmniRoute URL):\n\n```txt\nToken 示例:sk-a3ab3c080beaee3a-69f4a4-070d71af\n\n标准 OpenAI base:http://localhost:20128/v1\nVS Code 模型:http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/models\nVS Code 聊天:http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/chat/completions\nVS Code Responses:http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/responses\nOllama 标签:http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/api/tags\nOllama 聊天:http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/api/chat\n```\n\n---\n\n## 故障排除\n\n| 错误 | 原因 | 修复方法 |\n| --------------------------------------------- | ------------------------ | ------------------------------------------------- |\n| `Connection refused` | OmniRoute 未运行 | `omniroute serve` |\n| `401 Unauthorized` | API Key 错误 | 在 `/dashboard/api-manager` 中检查 |\n| `No combo configured` | 无活跃的路由 Combo | 在 `/dashboard/combos` 中设置 |\n| CLI 显示 \"not installed\" | 二进制文件不在 PATH 中 | 检查 `which <command>` |\n| Dashboard 安装后显示 \"not detected\" | 缓存过期 | 点击 dashboard 中的 \"⟳ 刷新检测\" |\n| 旧链接 `/dashboard/cli-tools` | v3.8.6 之前的书签 | 自动重定向到 `/dashboard/cli-code`(308) |\n| 旧链接 `/dashboard/agents` | v3.8.6 之前的书签 | 自动重定向到 `/dashboard/acp-agents`(308) |\n"}, "21dc426d54bc37c5a51ab378ec3abd82813d1521": {"t": 1785764933.65839, "n": 24168, "h": "f2febed5995ea9c8", "c": "---\ntitle: \"CLI 工具 — OmniRoute\"\nversion: 3.8.40\nlastUpdated: 2026-06-28\n---\n\n# CLI 工具 — OmniRoute\n\n最后更新:2026-06-28\n\nOmniRoute 与三类 CLI 工具集成,分布在三个专用的 dashboard 页面中:\n\n| 页面 | 路由 | 概念 | 数量 |\n| ---------------- | ------------------------ | --------------------------------------------------------------------------- | ------------ |\n| **CLI Code's** | `/dashboard/cli-code` | 指向 OmniRoute 的编程工具(客户端 → CLI → OmniRoute → 服务商) | 19 |\n| **CLI Agents** | `/dashboard/cli-agents` | 指向 OmniRoute 的自主代理(相同流程,更广泛的范围) | 6 |\n| **ACP Agents** | `/dashboard/acp-agents` | OmniRoute 通过 stdio/ACP 作为后端启动的 CLI(反向流程) | 见注册表 |\n\n旧路由通过 308 重定向:`/dashboard/cli-tools` → `/dashboard/cli-code`,`/dashboard/agents` → `/dashboard/acp-agents`。\n\n---\n\n## 工作原理\n\n```\nCLI Code's / CLI Agents(消费流程):\nClaude / Codex / OpenCode / Cline / KiloCode / Continue / Hermes Agent / Goose / ...\n │\n ▼ (全部指向 OmniRoute)\n http://YOUR_SERVER:20128/v1\n │\n ▼ (OmniRoute 路由到合适的服务商)\n Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...\n\nACP Agents(反向启动流程):\n 客户端请求 → OmniRoute → 通过 stdio/ACP 启动 CLI → 响应\n```\n\n**优势:**\n\n- 一个 API Key 管理所有工具\n- 在 dashboard 中追踪所有 CLI 的成本\n- 无需重新配置每个工具即可切换模型\n- 在本地和远程服务器(VPS、Docker、Akamai、Cloudflare Tunnel)均可使用\n\n---\n\n## 使用 `setup-*` 自动配置\n\n无需手动编写每个工具的配置。OmniRoute 为每个支持的 CLI 提供对应的 `setup-*` 命令,该命令从运行中的 OmniRoute(本地或远程)读取**实时**模型目录并将工具的配置写入你的机器:\n\n```bash\nomniroute setup-codex omniroute setup-claude omniroute setup-opencode\nomniroute setup-cline omniroute setup-kilo omniroute setup-continue\nomniroute setup-cursor omniroute setup-roo omniroute setup-crush\nomniroute setup-goose omniroute setup-qwen omniroute setup-aider\n```\n\n每个命令接受 `--remote <url> --api-key <key>`(针对远程 OmniRoute 配置本地工具)、`--dry-run`(预览不写入)和 `--port`。不支持模型自动发现的工具(Cline、Kilo、Roo、Goose、Qwen、Aider、Gemini)接受 `--model <id>`(以及用于非交互式运行的 `--yes`)。启动器 `omniroute launch`(Claude Code)和 `omniroute launch-codex`(Codex)在注入正确的环境变量后启动 CLI,不写入任何配置。\n\n> **完整参考:** 主表 — 每个命令写入的内容、所有标志、本地 vs 远程,以及哪些工具需要 `/v1` 后缀 — 在 **[CLI Integrations](../guides/CLI-INTEGRATIONS.md)** 中。\n\n---\n\n## 数据源\n\n统一目录位于 `src/shared/constants/cliTools.ts`,定义为 `CLI_TOOLS: Record<string, CliCatalogEntry>`。\n\n每个条目包含以下字段(定义在 `src/shared/schemas/cliCatalog.ts`):\n\n| 字段 | 类型 | 说明 |\n| ------------------------------------------------ | ------------------------------------------------------------ | -------------------------------------------------------- |\n| `category` | `\"code\" \\| \"agent\"` | 工具显示的页面 |\n| `vendor` | `string` | 工具来源(\"Anthropic\"、\"OSS (P. Gauthier)\") |\n| `acpSpawnable` | `boolean` | 也可作为 ACP Agent 使用(显示徽章) |\n| `baseUrlSupport` | `\"full\" \\| \"partial\" \\| \"none\"` | 自定义端点支持级别。`\"none\"` = MITM 待办列表 |\n| `configType` | `\"env\" \\| \"custom\" \\| \"guide\" \\| \"custom-builder\" \\| \"mitm\"` | 配置机制 |\n| `id`、`name`、`color`、`description`、`docsUrl` | 标准字段 | 核心显示字段 |\n\n`baseUrlSupport: \"none\"` 的条目**不会显示**在 dashboard 页面中 — 它们注册在 MITM 待办列表中,供 plan 11 使用(参见 `_tasks/features-v3.8.6/refactorpages/_orchestration/_plan11-mitm-backlog.md`)。\n\n---\n\n## 1. CLI Code's 目录(19 个工具)\n\n支持自定义 base URL 并出现在 `/dashboard/cli-code` 中的工具:\n\n| id | name | vendor | baseUrlSupport | configType | acpSpawnable |\n|----|------|--------|---------------|-----------|-------------|\n| claude | Claude Code | Anthropic | full | env | true |\n| codex | OpenAI Codex CLI | OpenAI | full | custom | true |\n| cline | Cline | OSS (ex-Claude Dev) | full | custom | true |\n| kilo | Kilo Code | Kilo-Org | full | custom | false |\n| roo | Roo Code | Roo (OSS) | full | guide | false |\n| continue | Continue | continue.dev | full | guide | false |\n| qwen | Qwen Code | Alibaba | full | guide | true |\n| aider | Aider | OSS (P. Gauthier) | full | guide | true |\n| forge | ForgeCode | Antinomy HQ | full | custom | true |\n| jcode | jcode | 1jehuang (OSS) | full | custom | false |\n| deepseek-tui | DeepSeek TUI | Hunter Bown (OSS) | full | custom | false |\n| opencode | OpenCode | Anomaly (ex-SST) | full | guide | true |\n| droid | Factory Droid | Factory AI | partial | guide | false |\n| copilot | GitHub Copilot CLI | GitHub/MS | full | custom | false |\n| cursor-cli | Cursor CLI | Anysphere | partial | guide | true |\n| smelt | Smelt | leonardcser (OSS) | full | custom | false |\n| pi | Pi (pi-coding-agent) | M. Zechner (OSS) | full | custom | false |\n| custom | Custom CLI | — | full | custom-builder | false |\n\n`baseUrlSupport: \"partial\"` 的工具在 dashboard 卡片中显示徽章 \"⚠ Base URL parcial\"。\n\n---\n\n## 2. CLI Agents 目录(6 个工具)\n\n出现在 `/dashboard/cli-agents` 中的自主代理:\n\n| id | name | vendor | baseUrlSupport | acpSpawnable |\n| ------------ | ---------------- | ------------------------ | -------------- | ------------ |\n| hermes-agent | Hermes Agent | Nous Research | full | false |\n| openclaw | OpenClaw | OSS (P. Steinberger) | full | true |\n| goose | Goose | Block / Linux Foundation | full | true |\n| interpreter | Open Interpreter | OSS | full | true |\n| warp | Warp AI | Warp Inc. | partial | true |\n| agent-deck | Agent Deck | asheshgoplani (OSS) | full | false |\n\n---\n\n## 3. ACP Agents(/dashboard/acp-agents)\n\n此页面(从 `/dashboard/agents` 重命名而来)显示 OmniRoute 可以通过 stdio/ACP 协议**启动**为后端执行引擎的 CLI。目录在 `src/lib/acp/registry.ts` 中单独维护,**不同于** `CLI_TOOLS`。\n\n---\n\n## 4. MITM 待办列表(不在 dashboard 中显示)\n\n以下 CLI 原生不支持自定义 base URL,因此**不会**在 CLI Code's 或 CLI Agents 页面中列出。它们是 plan 11 中 MITM 拦截的候选项:\n\n| CLI | 原因 |\n| ------------------- | ------------------------------------------------------------- |\n| windsurf | BYOK 限于部分 Claude 模型 + 企业 URL/Token |\n| amp | 封闭生态系统(Sourcegraph) |\n| amazon-q / kiro-cli | AWS SSO 认证,无自定义 URL |\n| cowork | Anthropic Desktop,无可配置端点 |\n\n完整对照参见 `_tasks/features-v3.8.6/refactorpages/_orchestration/_plan11-mitm-backlog.md`。\n\n---\n\n## 5. 批量检测 API\n\n所有工具检测通过单个端点聚合:\n\n**`GET /api/cli-tools/all-statuses`**\n\n- 认证:`requireCliToolsAuth(request)`(与其他 `/api/cli-tools/` 路由相同)\n- 返回:`Record<toolId, ToolBatchStatus>`(类型:`src/shared/types/cliBatchStatus.ts`)\n- 策略:对全部工具执行 `Promise.all`,每个工具 5 秒超时\n- 缓存:以配置文件 `mtime` 为索引的内存 LRU 缓存。当 mtime 变化时缓存失效。服务器重启时重置。\n\n每个工具的响应结构:\n\n```ts\ninterface ToolBatchStatus {\n detection: {\n installed: boolean;\n runnable: boolean;\n version?: string;\n command?: string;\n commandPath?: string;\n reason?: string;\n };\n config: {\n status: \"configured\" | \"not_configured\" | \"not_installed\" | \"unknown\" | \"other\";\n endpoint?: string | null;\n lastConfiguredAt?: string | null;\n };\n error?: string; // 已脱敏,无堆栈跟踪\n}\n```\n\n---\n\n## 6. 新工具的 Settings 处理器\n\n`configType: \"custom\"` 的新工具具有专用的 settings API 路由:\n\n| 路由 | 工具 |\n| -------------------------------------------- | -------------------------------- |\n| `POST /api/cli-tools/forge-settings` | ForgeCode (.forge.toml) |\n| `POST /api/cli-tools/jcode-settings` | jcode (--base-url 标志) |\n| `POST /api/cli-tools/deepseek-tui-settings` | DeepSeek TUI (OPENAI_BASE_URL) |\n| `POST /api/cli-tools/smelt-settings` | Smelt |\n| `POST /api/cli-tools/pi-settings` | Pi coding agent |\n\n所有路由均使用 `sanitizeErrorMessage()` 处理错误响应(Hard Rule #12)。\n\n---\n\n## 7. Dashboard 页面架构\n\n### CLI Code's(`/dashboard/cli-code`)\n\n- `src/app/(dashboard)/dashboard/cli-code/page.tsx` — 服务端组件\n- `src/app/(dashboard)/dashboard/cli-code/CliCodePageClient.tsx` — 客户端网格\n- `src/app/(dashboard)/dashboard/cli-code/[id]/page.tsx` — 工具详情页\n- `src/app/(dashboard)/dashboard/cli-code/components/` — 12 个专用工具卡片 + `ToolDetailClient.tsx`\n\n### CLI Agents(`/dashboard/cli-agents`)\n\n- `src/app/(dashboard)/dashboard/cli-agents/page.tsx` — 服务端组件\n- `src/app/(dashboard)/dashboard/cli-agents/CliAgentsPageClient.tsx` — 客户端网格\n- `src/app/(dashboard)/dashboard/cli-agents/[id]/page.tsx` — 复用 `ToolDetailClient`\n\n### ACP Agents(`/dashboard/acp-agents`)\n\n- `src/app/(dashboard)/dashboard/acp-agents/page.tsx` — 服务端组件(从 `agents/` 迁移而来)\n\n### 共享 UI 组件(`src/shared/components/cli/`)\n\n| 文件 | 用途 |\n| ------------------------- | --------------------------------------------------- |\n| `CliToolCard.tsx` | 智能状态卡片(检测 + 配置 + 端点) |\n| `CliConceptCard.tsx` | 每页概念说明卡片 |\n| `CliComparisonCard.tsx` | 三类 CLI 对比卡 |\n| `BaseUrlSelect.tsx` | 端点下拉选择(本地/云端/自定义) |\n| `ApiKeySelect.tsx` | API Key 选择器 |\n| `ManualConfigModal.tsx` | 可复制的配置片段弹窗 |\n\n### 共享 Hook(`src/shared/hooks/cli/`)\n\n| 文件 | 用途 |\n| --------------------------- | --------------------------------------------------------------------- |\n| `useToolBatchStatuses.ts` | 获取 `/api/cli-tools/all-statuses`,管理 loading/refresh 状态 |\n\n---\n\n## 8. i18n\n\n在 plan 14 F9 中添加的新命名空间:\n\n| 命名空间 | 用途 |\n| ----------- | ---------------------------------------------------------------------------- |\n| `cliCommon` | 共享字符串(卡片标签、概念/对比文本、详情页标签) |\n| `cliCode` | CLI Code's 页面字符串 |\n| `cliAgents` | CLI Agents 页面字符串 |\n| `acpAgents` | ACP Agents 页面字符串 |\n\n提供完整的 PT-BR 和 EN 翻译。其余 39 个语言环境通过 `src/i18n/request.ts` 中的命名空间级合并自动回退到 EN。\n\n---\n\n## 9. 快速开始\n\n### 步骤 1 — 获取 OmniRoute API Key\n\n1. 打开 `/dashboard/api-manager` → **创建 API Key**\n2. 为其命名(例如 `cli-tools`)并选择所有权限\n3. 复制 Key — 以下所有 CLI 都会用到\n\n> 你的 Key 格式为:`sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`\n\n---\n\n### 步骤 2 — 安装 CLI 工具\n\n所有基于 npm 的工具需要 Node.js 22.22.2+ 或 24.x:\n\n```bash\n# Claude Code (Anthropic)\nnpm install -g @anthropic-ai/claude-code\n\n# OpenAI Codex\nnpm install -g @openai/codex\n\n# OpenCode\nnpm install -g opencode-ai\n\n# Cline\nnpm install -g cline\n\n# KiloCode\nnpm install -g kilocode\n\n# Qwen Code (Alibaba)\nnpm install -g @qwen-code/qwen-code\n\n# Aider\npip install aider-chat\n\n# Smelt\ncargo install smelt # Rust 编写\n\n# Pi coding agent\n# 安装参见 https://github.com/zechnerj/pi-coding-agent\n\n# jcode\n# 安装参见 https://github.com/1jehuang/jcode\n```\n\n---\n\n### 步骤 3 — 通过 Dashboard 配置\n\n1. 访问 `http://localhost:20128/dashboard/cli-code`\n2. 在网格中找到你的工具\n3. 点击卡片进入工具详情页\n4. 选择你的 API Key 和 base URL\n5. 点击**应用配置**或复制手动配置片段\n\n---\n\n### 步骤 4 — 设置全局环境变量\n\n```bash\n# OmniRoute 通用端点\nexport OPENAI_BASE_URL=\"http://localhost:20128/v1\"\nexport OPENAI_API_KEY=\"sk-your-omniroute-key\"\nexport ANTHROPIC_BASE_URL=\"http://localhost:20128\"\nexport ANTHROPIC_AUTH_TOKEN=\"sk-your-omniroute-key\"\nexport GEMINI_BASE_URL=\"http://localhost:20128/v1\"\nexport GEMINI_API_KEY=\"sk-your-omniroute-key\"\n```\n\n> 对于**远程服务器**,将 `localhost:20128` 替换为服务器的 IP 或域名,\n> 例如 `http://<your-server-ip>:20128`。\n\n---\n\n### 步骤 4 — 配置每个工具\n\n#### Claude Code\n\n```bash\n# 创建 ~/.claude/settings.json:\nmkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF\n{\n \"env\": {\n \"ANTHROPIC_BASE_URL\": \"http://localhost:20128\",\n \"ANTHROPIC_AUTH_TOKEN\": \"sk-your-omniroute-key\"\n }\n}\nEOF\n```\n\nClaude Code 使用统一的 Anthropic 网关根路径。不要在这里添加 `/v1`。\n\n**测试:** `claude \"say hello\"`\n\n---\n\n#### OpenAI Codex\n\n```bash\nmkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF\nmodel: auto\napiKey: sk-your-omniroute-key\napiBaseUrl: http://localhost:20128/v1\nEOF\n```\n\n**测试:** `codex \"what is 2+2?\"`\n\n---\n\n#### OpenCode\n\n```bash\nmkdir -p ~/.config/opencode && cat > ~/.config/opencode/opencode.json << EOF\n{\n \"\\$schema\": \"https://opencode.ai/config.json\",\n \"provider\": {\n \"omniroute\": {\n \"npm\": \"@ai-sdk/openai-compatible\",\n \"name\": \"OmniRoute\",\n \"options\": {\n \"baseURL\": \"http://localhost:20128/v1\",\n \"apiKey\": \"sk-your-omniroute-key\"\n },\n \"models\": {\n \"claude-sonnet-4-5\": { \"name\": \"claude-sonnet-4-5\" },\n \"claude-sonnet-4-5-thinking\": { \"name\": \"claude-sonnet-4-5-thinking\" },\n \"gemini-3-flash\": { \"name\": \"gemini-3-flash\" }\n }\n }\n }\n}\nEOF\n```\n\n**测试:** `opencode`\n\n> 使用 `opencode run \"your prompt\" --model omniroute/claude-sonnet-4-5-thinking --variant high`\n> 发送 thinking 变体。\n\n---\n\n#### Cline(CLI 或 VS Code)\n\n**CLI 模式:**\n\n```bash\nmkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF\n{\n \"apiProvider\": \"openai\",\n \"openAiBaseUrl\": \"http://localhost:20128/v1\",\n \"openAiApiKey\": \"sk-your-omniroute-key\"\n}\nEOF\n```\n\n**VS Code 模式:**\nCline 扩展设置 → API Provider:`OpenAI Compatible` → Base URL:`http://localhost:20128/v1`\n\n或使用 OmniRoute dashboard → **CLI Tools → Cline → 应用配置**。\n\n---\n\n#### KiloCode(CLI 或 VS Code)\n\n**CLI 模式:**\n\n```bash\nkilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key\n```\n\n**VS Code 设置:**\n\n```json\n{\n \"kilo-code.openAiBaseUrl\": \"http://localhost:20128/v1\",\n \"kilo-code.apiKey\": \"sk-your-omniroute-key\"\n}\n```\n\n或使用 OmniRoute dashboard → **CLI Tools → KiloCode → 应用配置**。\n\n---\n\n#### Continue(VS Code 扩展)\n\n编辑 `~/.continue/config.yaml`:\n\n```yaml\nmodels:\n - name: OmniRoute\n provider: openai\n model: auto\n apiBase: http://localhost:20128/v1\n apiKey: sk-your-omniroute-key\n default: true\n```\n\n编辑后重启 VS Code。\n\n---\n\n#### VS Code Insiders(`chatLanguageModels.json`)\n\n当 VS Code Insiders 配置了自定义端点模型,且你希望 OmniRoute 在不使用自定义请求头字段的情况下工作时使用。\n\n**推荐位置:**\n\n- Linux:`~/.config/Code - Insiders/User/chatLanguageModels.json`\n- Windows:`%APPDATA%/Code - Insiders/User/chatLanguageModels.json`\n\n**使用 Token 化 OmniRoute 别名的示例:**\n\n```json\n[\n {\n \"vendor\": \"customendpoint\",\n \"id\": \"auto\",\n \"name\": \"OmniRoute Auto\",\n \"family\": \"gpt-4\",\n \"version\": \"1.0.0\",\n \"url\": \"http://localhost:20128/api/v1/vscode/sk-your-omniroute-key/chat/completions\",\n \"modelsUrl\": \"http://localhost:20128/api/v1/vscode/sk-your-omniroute-key/models\",\n \"requestFormat\": \"openai-chat-completions\",\n \"contextWindow\": 256000,\n \"maxOutputTokens\": 32768,\n \"auth\": {\n \"type\": \"none\"\n }\n }\n]\n```\n\n**说明:**\n\n- 将 `sk-your-omniroute-key` 替换为在 OmniRoute 中创建的 API Key。\n- `url` 字段应指向 `/api/v1/vscode/{token}/chat/completions`。\n- `modelsUrl` 字段应指向 `/api/v1/vscode/{token}/models`。\n- 只要客户端支持自定义请求头,应优先使用正常的 `/v1` + Bearer 请求头流程。\n- URL 嵌入的 Token 是兼容性回退方案,可能出现在编辑器日志或代理历史中。\n\n---\n\n#### Kiro CLI(Amazon)\n\n```bash\n# 登录你的 AWS/Kiro 账户:\nkiro-cli login\n\n# CLI 使用自己的认证 — Kiro CLI 本身不需要 OmniRoute 作为后端。\n# 将 kiro-cli 与 OmniRoute 配合用于其他工具。\nkiro-cli status\n```\n\n对于 **Kiro IDE** 桌面应用,使用 OmniRoute 通过 `/dashboard/cli-tools → Kiro` 暴露的 MITM 端点。\n\n---\n\n#### Qwen Code(Alibaba)\n\nQwen Code 通过环境变量或 `settings.json` 支持 OpenAI 兼容的 API 端点。\n\n> Qwen OAuth 免费层已于 2026-04-15 停用。改为使用 OmniRoute 搭配\n> `bailian-coding-plan` / `alibaba` / `alibaba-cn` / `openrouter` / `anthropic` /\n> `gemini` 服务商。\n\n**选项 1:环境变量(`~/.qwen/.env`)**\n\n```bash\nmkdir -p ~/.qwen && cat > ~/.qwen/.env << EOF\nOPENAI_API_KEY=\"sk-your-omniroute-key\"\nOPENAI_BASE_URL=\"http://localhost:20128/v1\"\nOPENAI_MODEL=\"auto\"\nEOF\n```\n\n**选项 2:`settings.json` 配合 `security.auth`**\n\n```json\n// ~/.qwen/settings.json\n{\n \"security\": {\n \"auth\": {\n \"selectedType\": \"openai\",\n \"apiKey\": \"sk-your-omniroute-key\",\n \"baseUrl\": \"http://localhost:20128/v1\"\n }\n },\n \"model\": {\n \"name\": \"claude-sonnet-4-6\"\n }\n}\n```\n\n**选项 3:内联 CLI 标志**\n\n```bash\nOPENAI_BASE_URL=\"http://localhost:20128/v1\" \\\nOPENAI_API_KEY=\"sk-your-omniroute-key\" \\\nOPENAI_MODEL=\"auto\" \\\nqwen\n```\n\n> 对于**远程服务器**,将 `localhost:20128` 替换为服务器的 IP 或域名。\n\n---\n\n## 10. OmniRoute 内置 CLI\n\n`omniroute` 二进制文件提供服务端生命周期、设置、诊断和服务商管理的命令。入口点:`bin/omniroute.mjs`。\n\n```bash\nomniroute # 启动服务器(默认端口 20128)\nomniroute setup # 交互式设置向导\nomniroute doctor # 检查配置、数据库、端口、运行时\nomniroute providers list # 已配置的服务商连接\nomniroute providers test-all # 测试所有活跃连接\nomniroute reset-password # 重置管理员密码\nomniroute logs # 流式输出请求日志\nomniroute health # 详细健康状态(熔断器、缓存、内存)\nomniroute --version # 输出版本号\nomniroute --help # 显示所有命令\n```\n\n### 设置与初始化\n\n```bash\nomniroute setup # 交互式设置向导\nomniroute setup --non-interactive # CI/自动化模式(读取环境变量 + 标志)\nomniroute setup --password '<value>' # 直接设置管理员密码\nomniroute setup --add-provider \\\n --provider openai \\\n --api-key '<value>' \\\n --test-provider # 一步添加并测试服务商\n```\n\n非交互式设置识别的环境变量:\n\n| 变量 | 用途 |\n| ------------------- | ----------------------------------------------------------- |\n| `OMNIROUTE_API_KEY` | 服务商 API Key(通过 Commander `.env()` 绑定到 `--api-key`) |\n| `DATA_DIR` | 覆盖 OmniRoute 数据目录 |\n\n其他所有非交互式输入通过标志传入,而非环境变量:\n`--password`、`--provider`、`--provider-name`、`--provider-base-url`、`--default-model`\n(参见上述 `omniroute setup` 选项)。\n\n### 诊断\n\n```bash\nomniroute doctor # 检查配置、数据库、端口、运行时、内存、存活状态\nomniroute doctor --json # 机器可读的 JSON\nomniroute doctor --no-liveness # 跳过 HTTP 健康探测\nomniroute doctor --host 0.0.0.0 # 覆盖存活探测的主机\nomniroute doctor --liveness-url <url> # 完全覆盖健康端点 URL\n```\n\ndoctor 运行以下检查:`Config`、`Database`、`Storage/encryption`、`Port availability`、`Node runtime`、`Native binary`(better-sqlite3)、`Memory` 和 `Server liveness`。任何检查为 `fail` 时以非零退出码退出。\n\n### 服务商管理\n\n```bash\nomniroute providers available # OmniRoute 服务商目录\nomniroute providers available --search openai # 按 id/name/alias/category 过滤目录\nomniroute providers available --category api-key # 按分类过滤(api-key、oauth、free 等)\nomniroute providers available --json # 机器可读的 JSON\n\nomniroute providers list # 已配置的服务商连接\nomniroute providers list --json\n\nomniroute providers test <id|name> # 测试一个已配置的连接\nomniroute providers test-all # 测试所有活跃连接\nomniroute providers validate # 仅本地结构校验\n```\n\n> `providers available` 读取 OmniRoute 目录;`providers list/test/test-all/validate`\n> 直接读取本地 SQLite 数据库,不需要服务器运行。\n\n### 恢复与重置\n\n```bash\nomniroute reset-password # 重置管理员密码(旧别名仍然可用)\nomniroute reset-encrypted-columns # 显示加密凭证重置的警告 + 干运行\nomniroute reset-encrypted-columns --force # 实际在 SQLite 中将加密凭证设为 null\n```\n\n### 其他子命令\n\n以下命令假定 OmniRoute 服务器正在运行(另有说明除外):\n\n```bash\nomniroute status # 全面的运行时状态\nomniroute logs # 流式输出请求日志(--json、--search、--follow)\nomniroute config show # 显示当前配置\n\nomniroute provider list # 列出可用服务商(providers list 的别名)\nomniroute provider add # 将 OmniRoute 注册为某个工具的服务商\nomniroute keys add | list | remove # 管理 API Key\nomniroute models [provider] # 列出模型(--json、--search)\nomniroute combo list | switch | create | delete\n\nomniroute backup # 快照配置 + 数据库\nomniroute restore # 从之前的快照恢复\n\nomniroute health # 详细健康状态(熔断器、缓存、内存)\nomniroute quota # 服务商配额用量\nomniroute cache # 缓存状态\nomniroute cache clear # 清除语义 + 签名缓存\n\nomniroute mcp status | restart # MCP 服务器状态 / 重启\nomniroute a2a status | card # A2A 服务器状态 / agent card\n\nomniroute tunnel list | create | stop # 管理隧道(cloudflare/tailscale/ngrok)\nomniroute env show | get <k> | set <k> <v> # 检查 / 设置环境变量(临时)\n\nomniroute test # 服务商连通性冒烟测试\nomniroute update # 检查更新\nomniroute completion # 生成 shell 补全\n```\n\n### 通用标志\n\n| 标志 | 说明 |\n| ------------------- | ------------------------------------------------------ |\n| `--no-open` | 启动时不自动打开浏览器 |\n| `--port <n>` | 覆盖 API 端口(默认 20128) |\n| `--mcp` | 以 MCP 服务器通过 stdio 运行(供 IDE 使用) |\n| `--non-interactive` | CI 模式(无交互提示;从 env/flags 读取) |\n| `--json` | 机器可读的 JSON 输出(doctor、providers 等) |\n| `--help`、`-h` | 显示命令特定的帮助 |\n| `--version`、`-v` | 输出版本号 |\n\n---\n\n## 可用 API 端点\n\n| 端点 | 说明 | 用途 |\n| ---------------------------- | ------------------------------ | -------------------------- |\n| `/v1/chat/completions` | 标准聊天(所有服务商) | 所有现代工具 |\n| `/v1/responses` | Responses API(OpenAI 格式) | Codex、代理工作流 |\n| `/v1/completions` | 旧版文本补全 | 使用 `prompt:` 的旧工具 |\n| `/v1/embeddings` | 文本嵌入 | RAG、搜索 |\n| `/v1/images/generations` | 图像生成 | GPT-Image、Flux 等 |\n| `/v1/audio/speech` | 文本转语音 | ElevenLabs、OpenAI TTS |\n| `/v1/audio/transcriptions` | 语音转文本 | Deepgram、AssemblyAI |\n\n可直接粘贴的示例(使用 Token 化 OmniRoute URL):\n\n```txt\nToken 示例:sk-a3ab3c080beaee3a-69f4a4-070d71af\n\n标准 OpenAI base:http://localhost:20128/v1\nVS Code 模型:http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/models\nVS Code 聊天:http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/chat/completions\nVS Code Responses:http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/responses\nOllama 标签:http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/api/tags\nOllama 聊天:http://localhost:20128/api/v1/vscode/sk-a3ab3c080beaee3a-69f4a4-070d71af/api/chat\n```\n\n---\n\n## 故障排除\n\n| 错误 | 原因 | 修复方法 |\n| --------------------------------------------- | ------------------------ | ------------------------------------------------- |\n| `Connection refused` | OmniRoute 未运行 | `omniroute serve` |\n| `401 Unauthorized` | API Key 错误 | 在 `/dashboard/api-manager` 中检查 |\n| `No combo configured` | 无活跃的路由 Combo | 在 `/dashboard/combos` 中设置 |\n| CLI 显示 \"not installed\" | 二进制文件不在 PATH 中 | 检查 `which <command>` |\n| Dashboard 安装后显示 \"not detected\" | 缓存过期 | 点击 dashboard 中的 \"⟳ 刷新检测\" |\n| 旧链接 `/dashboard/cli-tools` | v3.8.6 之前的书签 | 自动重定向到 `/dashboard/cli-code`(308) |\n| 旧链接 `/dashboard/agents` | v3.8.6 之前的书签 | 自动重定向到 `/dashboard/acp-agents`(308) |\n"}}, "omniroute/tests/snapshots/provider/translate-path.json": {"6eea4894299d5371c00c11f1f6dec2f7c0076253": {"t": 1785674321.649731, "n": 143630, "h": "b099a5061026b5ec", "c": "{\n \"adapta-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://agent.adapta.one/api/chat/stream/v1\",\n \"stream\": \"https://agent.adapta.one/api/chat/stream/v1\"\n }\n },\n \"agentrouter\": {\n \"format\": \"claude\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"claude-cli/2.1.207 (external, sdk-cli)\",\n \"X-Stainless-Arch\": \"<ARCH>\",\n \"X-Stainless-Lang\": \"js\",\n \"X-Stainless-OS\": \"MacOS\",\n \"X-Stainless-Package-Version\": \"0.94.0\",\n \"X-Stainless-Retry-Count\": \"0\",\n \"X-Stainless-Runtime\": \"node\",\n \"X-Stainless-Runtime-Version\": \"v24.3.0\",\n \"X-Stainless-Timeout\": \"600\",\n \"accept-encoding\": \"gzip, deflate, br, zstd\",\n \"anthropic-beta\": \"claude-code-20250219,interleaved-thinking-2025-05-14,effort-2025-11-24\",\n \"anthropic-dangerous-direct-browser-access\": \"true\",\n \"anthropic-version\": \"2023-06-01\",\n \"x-api-key\": \"<CRED>\",\n \"x-app\": \"cli\"\n },\n \"nonStream\": {\n \"Accept\": \"application/json\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"claude-cli/2.1.207 (external, sdk-cli)\",\n \"X-Stainless-Arch\": \"<ARCH>\",\n \"X-Stainless-Lang\": \"js\",\n \"X-Stainless-OS\": \"MacOS\",\n \"X-Stainless-Package-Version\": \"0.94.0\",\n \"X-Stainless-Retry-Count\": \"0\",\n \"X-Stainless-Runtime\": \"node\",\n \"X-Stainless-Runtime-Version\": \"v24.3.0\",\n \"X-Stainless-Timeout\": \"600\",\n \"accept-encoding\": \"gzip, deflate, br, zstd\",\n \"anthropic-beta\": \"claude-code-20250219,interleaved-thinking-2025-05-14,effort-2025-11-24\",\n \"anthropic-dangerous-direct-browser-access\": \"true\",\n \"anthropic-version\": \"2023-06-01\",\n \"x-api-key\": \"<CRED>\",\n \"x-app\": \"cli\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"claude-cli/2.1.207 (external, sdk-cli)\",\n \"X-Stainless-Arch\": \"<ARCH>\",\n \"X-Stainless-Lang\": \"js\",\n \"X-Stainless-OS\": \"MacOS\",\n \"X-Stainless-Package-Version\": \"0.94.0\",\n \"X-Stainless-Retry-Count\": \"0\",\n \"X-Stainless-Runtime\": \"node\",\n \"X-Stainless-Runtime-Version\": \"v24.3.0\",\n \"X-Stainless-Timeout\": \"600\",\n \"accept-encoding\": \"gzip, deflate, br, zstd\",\n \"anthropic-beta\": \"claude-code-20250219,interleaved-thinking-2025-05-14,effort-2025-11-24\",\n \"anthropic-dangerous-direct-browser-access\": \"true\",\n \"anthropic-version\": \"2023-06-01\",\n \"x-api-key\": \"<CRED>\",\n \"x-app\": \"cli\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://agentrouter.org/v1/messages?beta=true\",\n \"stream\": \"https://agentrouter.org/v1/messages?beta=true\"\n }\n },\n \"agnes\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://apihub.agnes-ai.com/v1/chat/completions\",\n \"stream\": \"https://apihub.agnes-ai.com/v1/chat/completions\"\n }\n },\n \"agy\": {\n \"format\": \"antigravity\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Antigravity/4.2.0 (<PLATFORM>) Chrome/142.0.7444.175 Electron/39.2.3\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Antigravity/4.2.0 (<PLATFORM>) Chrome/142.0.7444.175 Electron/39.2.3\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Antigravity/4.2.0 (<PLATFORM>) Chrome/142.0.7444.175 Electron/39.2.3\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://daily-cloudcode-pa.googleapis.com/v1internal:generateContent\",\n \"stream\": \"https://daily-cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse\"\n }\n },\n \"ai21\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.ai21.com/studio/v1/chat/completions\",\n \"stream\": \"https://api.ai21.com/studio/v1/chat/completions\"\n }\n },\n \"aihorde\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://oai.aihorde.net/v1/chat/completions\",\n \"stream\": \"https://oai.aihorde.net/v1/chat/completions\"\n }\n },\n \"aimlapi\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.aimlapi.com/v1/chat/completions\",\n \"stream\": \"https://api.aimlapi.com/v1/chat/completions\"\n }\n },\n \"alibaba\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions\",\n \"stream\": \"https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions\"\n }\n },\n \"alibaba-cn\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n \"stream\": \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\"\n }\n },\n \"anthropic\": {\n \"format\": \"claude\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Beta\": \"claude-code-20250219,interleaved-thinking-2025-05-14,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advanced-tool-use-2025-11-20,effort-2025-11-24,structured-outputs-2025-12-15,fast-mode-2026-02-01,redact-thinking-2026-02-12,token-efficient-tools-2026-03-28,advisor-tool-2026-03-01,extended-cache-ttl-2025-04-11,cache-diagnosis-2026-04-07\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"nonStream\": {\n \"Anthropic-Beta\": \"claude-code-20250219,interleaved-thinking-2025-05-14,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advanced-tool-use-2025-11-20,effort-2025-11-24,structured-outputs-2025-12-15,fast-mode-2026-02-01,redact-thinking-2026-02-12,token-efficient-tools-2026-03-28,advisor-tool-2026-03-01,extended-cache-ttl-2025-04-11,cache-diagnosis-2026-04-07\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Beta\": \"claude-code-20250219,interleaved-thinking-2025-05-14,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advanced-tool-use-2025-11-20,effort-2025-11-24,structured-outputs-2025-12-15,fast-mode-2026-02-01,redact-thinking-2026-02-12,token-efficient-tools-2026-03-28,advisor-tool-2026-03-01,extended-cache-ttl-2025-04-11,cache-diagnosis-2026-04-07\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.anthropic.com/v1/messages?beta=true\",\n \"stream\": \"https://api.anthropic.com/v1/messages?beta=true\"\n }\n },\n \"antigravity\": {\n \"format\": \"antigravity\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Antigravity/4.2.0 (<PLATFORM>) Chrome/142.0.7444.175 Electron/39.2.3\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Antigravity/4.2.0 (<PLATFORM>) Chrome/142.0.7444.175 Electron/39.2.3\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Antigravity/4.2.0 (<PLATFORM>) Chrome/142.0.7444.175 Electron/39.2.3\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://daily-cloudcode-pa.googleapis.com/v1internal:generateContent\",\n \"stream\": \"https://daily-cloudcode-pa.googleapis.com/v1internal:streamGenerateContent?alt=sse\"\n }\n },\n \"api-airforce\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://endpoint-proxy.local\",\n \"X-Title\": \"Endpoint Proxy\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://endpoint-proxy.local\",\n \"X-Title\": \"Endpoint Proxy\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://endpoint-proxy.local\",\n \"X-Title\": \"Endpoint Proxy\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.airforce/v1/chat/completions\",\n \"stream\": \"https://api.airforce/v1/chat/completions\"\n }\n },\n \"auggie\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"auggie://cli/stdio\",\n \"stream\": \"auggie://cli/stdio\"\n }\n },\n \"bai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.b.ai/v1/chat/completions\",\n \"stream\": \"https://api.b.ai/v1/chat/completions\"\n }\n },\n \"baichuan\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.baichuan-ai.com/v1/chat/completions\",\n \"stream\": \"https://api.baichuan-ai.com/v1/chat/completions\"\n }\n },\n \"baidu\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://qianfan.baidubce.com/v2/chat/completions\",\n \"stream\": \"https://qianfan.baidubce.com/v2/chat/completions\"\n }\n },\n \"bailian-coding-plan\": {\n \"format\": \"claude\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"nonStream\": {\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1\",\n \"stream\": \"https://coding-intl.dashscope.aliyuncs.com/apps/anthropic/v1\"\n }\n },\n \"baseten\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://inference.baseten.co/v1/chat/completions\",\n \"stream\": \"https://inference.baseten.co/v1/chat/completions\"\n }\n },\n \"bazaarlink\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://bazaarlink.ai/api/v1/chat/completions\",\n \"stream\": \"https://bazaarlink.ai/api/v1/chat/completions\"\n }\n },\n \"bedrock\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {}\n },\n \"blackbox\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.blackbox.ai/v1/chat/completions\",\n \"stream\": \"https://api.blackbox.ai/v1/chat/completions\"\n }\n },\n \"blackbox-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://app.blackbox.ai/api/chat\",\n \"stream\": \"https://app.blackbox.ai/api/chat\"\n }\n },\n \"bluesminds\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.bluesminds.com/v1/chat/completions\",\n \"stream\": \"https://api.bluesminds.com/v1/chat/completions\"\n }\n },\n \"byteplus\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://ark.ap-southeast.bytepluses.com/api/v3/chat/completions\",\n \"stream\": \"https://ark.ap-southeast.bytepluses.com/api/v3/chat/completions\"\n }\n },\n \"bytez\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.bytez.com/models/v2/openai/v1/chat/completions\",\n \"stream\": \"https://api.bytez.com/models/v2/openai/v1/chat/completions\"\n }\n },\n \"cerebras\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.cerebras.ai/v1/chat/completions\",\n \"stream\": \"https://api.cerebras.ai/v1/chat/completions\"\n }\n },\n \"charm-hyper\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://hyper.charm.land/v1/chat/completions\",\n \"stream\": \"https://hyper.charm.land/v1/chat/completions\"\n }\n },\n \"chatgpt-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://chatgpt.com/backend-api/conversation\",\n \"stream\": \"https://chatgpt.com/backend-api/conversation\"\n }\n },\n \"chenzk\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://chenzk.top/v1/chat/completions\",\n \"stream\": \"https://chenzk.top/v1/chat/completions\"\n }\n },\n \"chipotle\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://amelia.chipotle.com\",\n \"stream\": \"https://amelia.chipotle.com\"\n }\n },\n \"chutes\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://llm.chutes.ai/v1/chat/completions\",\n \"stream\": \"https://llm.chutes.ai/v1/chat/completions\"\n }\n },\n \"claude\": {\n \"format\": \"claude\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Beta\": \"claude-code-20250219,oauth-2025-04-20,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advanced-tool-use-2025-11-20,effort-2025-11-24,structured-outputs-2025-12-15,fast-mode-2026-02-01,redact-thinking-2026-02-12,token-efficient-tools-2026-03-28,advisor-tool-2026-03-01,extended-cache-ttl-2025-04-11,cache-diagnosis-2026-04-07\",\n \"Anthropic-Dangerous-Direct-Browser-Access\": \"true\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"claude-cli/2.1.207 (external, cli)\",\n \"X-App\": \"cli\",\n \"X-Stainless-Arch\": \"<ARCH>\",\n \"X-Stainless-Helper-Method\": \"stream\",\n \"X-Stainless-Lang\": \"js\",\n \"X-Stainless-Os\": \"<OS>\",\n \"X-Stainless-Package-Version\": \"0.94.0\",\n \"X-Stainless-Retry-Count\": \"0\",\n \"X-Stainless-Runtime\": \"node\",\n \"X-Stainless-Runtime-Version\": \"v24.3.0\",\n \"X-Stainless-Timeout\": \"600\",\n \"x-api-key\": \"<CRED>\"\n },\n \"nonStream\": {\n \"Anthropic-Beta\": \"claude-code-20250219,oauth-2025-04-20,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advanced-tool-use-2025-11-20,effort-2025-11-24,structured-outputs-2025-12-15,fast-mode-2026-02-01,redact-thinking-2026-02-12,token-efficient-tools-2026-03-28,advisor-tool-2026-03-01,extended-cache-ttl-2025-04-11,cache-diagnosis-2026-04-07\",\n \"Anthropic-Dangerous-Direct-Browser-Access\": \"true\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"claude-cli/2.1.207 (external, cli)\",\n \"X-App\": \"cli\",\n \"X-Stainless-Arch\": \"<ARCH>\",\n \"X-Stainless-Helper-Method\": \"stream\",\n \"X-Stainless-Lang\": \"js\",\n \"X-Stainless-Os\": \"<OS>\",\n \"X-Stainless-Package-Version\": \"0.94.0\",\n \"X-Stainless-Retry-Count\": \"0\",\n \"X-Stainless-Runtime\": \"node\",\n \"X-Stainless-Runtime-Version\": \"v24.3.0\",\n \"X-Stainless-Timeout\": \"600\",\n \"x-api-key\": \"<CRED>\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Beta\": \"claude-code-20250219,oauth-2025-04-20,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advanced-tool-use-2025-11-20,effort-2025-11-24,structured-outputs-2025-12-15,fast-mode-2026-02-01,redact-thinking-2026-02-12,token-efficient-tools-2026-03-28,advisor-tool-2026-03-01,extended-cache-ttl-2025-04-11,cache-diagnosis-2026-04-07\",\n \"Anthropic-Dangerous-Direct-Browser-Access\": \"true\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"claude-cli/2.1.207 (external, cli)\",\n \"X-App\": \"cli\",\n \"X-Stainless-Arch\": \"<ARCH>\",\n \"X-Stainless-Helper-Method\": \"stream\",\n \"X-Stainless-Lang\": \"js\",\n \"X-Stainless-Os\": \"<OS>\",\n \"X-Stainless-Package-Version\": \"0.94.0\",\n \"X-Stainless-Retry-Count\": \"0\",\n \"X-Stainless-Runtime\": \"node\",\n \"X-Stainless-Runtime-Version\": \"v24.3.0\",\n \"X-Stainless-Timeout\": \"600\",\n \"x-api-key\": \"<CRED>\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.anthropic.com/v1/messages?beta=true\",\n \"stream\": \"https://api.anthropic.com/v1/messages?beta=true\"\n }\n },\n \"claude-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://claude.ai/api/organizations\",\n \"stream\": \"https://claude.ai/api/organizations\"\n }\n },\n \"cline\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://cline.bot\",\n \"User-Agent\": \"OmniRoute/<APP>\",\n \"X-CLIENT-TYPE\": \"omniroute\",\n \"X-CLIENT-VERSION\": \"<APP>\",\n \"X-CORE-VERSION\": \"<APP>\",\n \"X-IS-MULTIROOT\": \"false\",\n \"X-PLATFORM\": \"<PLATFORM>\",\n \"X-PLATFORM-VERSION\": \"<NODE>\",\n \"X-Title\": \"Cline\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://cline.bot\",\n \"User-Agent\": \"OmniRoute/<APP>\",\n \"X-CLIENT-TYPE\": \"omniroute\",\n \"X-CLIENT-VERSION\": \"<APP>\",\n \"X-CORE-VERSION\": \"<APP>\",\n \"X-IS-MULTIROOT\": \"false\",\n \"X-PLATFORM\": \"<PLATFORM>\",\n \"X-PLATFORM-VERSION\": \"<NODE>\",\n \"X-Title\": \"Cline\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://cline.bot\",\n \"User-Agent\": \"OmniRoute/<APP>\",\n \"X-CLIENT-TYPE\": \"omniroute\",\n \"X-CLIENT-VERSION\": \"<APP>\",\n \"X-CORE-VERSION\": \"<APP>\",\n \"X-IS-MULTIROOT\": \"false\",\n \"X-PLATFORM\": \"<PLATFORM>\",\n \"X-PLATFORM-VERSION\": \"<NODE>\",\n \"X-Title\": \"Cline\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.cline.bot/api/v1/chat/completions\",\n \"stream\": \"https://api.cline.bot/api/v1/chat/completions\"\n }\n },\n \"clinepass\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://cline.bot\",\n \"X-Title\": \"Cline\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://cline.bot\",\n \"X-Title\": \"Cline\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://cline.bot\",\n \"X-Title\": \"Cline\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.cline.bot/api/v1/chat/completions\",\n \"stream\": \"https://api.cline.bot/api/v1/chat/completions\"\n }\n },\n \"cloudflare-ai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.cloudflare.com/client/v4/accounts\",\n \"stream\": \"https://api.cloudflare.com/client/v4/accounts\"\n }\n },\n \"codebuddy-cn\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"CLI/2.108.1 CodeBuddy/2.108.1\",\n \"X-IDE-Name\": \"CLI\",\n \"X-IDE-Type\": \"CLI\",\n \"X-Product\": \"SaaS\",\n \"x-codebuddy-request\": \"1\",\n \"x-requested-with\": \"XMLHttpRequest\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"CLI/2.108.1 CodeBuddy/2.108.1\",\n \"X-IDE-Name\": \"CLI\",\n \"X-IDE-Type\": \"CLI\",\n \"X-Product\": \"SaaS\",\n \"x-codebuddy-request\": \"1\",\n \"x-requested-with\": \"XMLHttpRequest\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"CLI/2.108.1 CodeBuddy/2.108.1\",\n \"X-IDE-Name\": \"CLI\",\n \"X-IDE-Type\": \"CLI\",\n \"X-Product\": \"SaaS\",\n \"x-codebuddy-request\": \"1\",\n \"x-requested-with\": \"XMLHttpRequest\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://copilot.tencent.com/v2/chat/completions\",\n \"stream\": \"https://copilot.tencent.com/v2/chat/completions\"\n }\n },\n \"codestral\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://codestral.mistral.ai/v1/chat/completions\",\n \"stream\": \"https://codestral.mistral.ai/v1/chat/completions\"\n }\n },\n \"codex\": {\n \"format\": \"openai-responses\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"Openai-Beta\": \"responses=experimental\",\n \"User-Agent\": \"codex-cli/0.144.1 (<OS>; <ARCH>)\",\n \"Version\": \"0.144.1\",\n \"X-Codex-Beta-Features\": \"responses_websockets\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"Openai-Beta\": \"responses=experimental\",\n \"User-Agent\": \"codex-cli/0.144.1 (<OS>; <ARCH>)\",\n \"Version\": \"0.144.1\",\n \"X-Codex-Beta-Features\": \"responses_websockets\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"Openai-Beta\": \"responses=experimental\",\n \"User-Agent\": \"codex-cli/0.144.1 (<OS>; <ARCH>)\",\n \"Version\": \"0.144.1\",\n \"X-Codex-Beta-Features\": \"responses_websockets\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://chatgpt.com/backend-api/codex/responses\",\n \"stream\": \"https://chatgpt.com/backend-api/codex/responses\"\n }\n },\n \"cohere\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.cohere.com/compatibility/v1/chat/completions\",\n \"stream\": \"https://api.cohere.com/compatibility/v1/chat/completions\"\n }\n },\n \"command-code\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.commandcode.ai\",\n \"stream\": \"https://api.commandcode.ai\"\n }\n },\n \"copilot-m365-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"wss://substrate.office.com/m365Copilot/Chathub\",\n \"stream\": \"wss://substrate.office.com/m365Copilot/Chathub\"\n }\n },\n \"copilot-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"wss://copilot.microsoft.com/c/api/chat?api-version=2\",\n \"stream\": \"wss://copilot.microsoft.com/c/api/chat?api-version=2\"\n }\n },\n \"coze\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.coze.com/v1/chat/completions\",\n \"stream\": \"https://api.coze.com/v1/chat/completions\"\n }\n },\n \"crof\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://crof.ai/v1/chat/completions\",\n \"stream\": \"https://crof.ai/v1/chat/completions\"\n }\n },\n \"cursor\": {\n \"format\": \"cursor\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/connect+proto\",\n \"User-Agent\": \"Cursor/3.9\",\n \"connect-accept-encoding\": \"gzip\",\n \"connect-protocol-version\": \"1\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/connect+proto\",\n \"User-Agent\": \"Cursor/3.9\",\n \"connect-accept-encoding\": \"gzip\",\n \"connect-protocol-version\": \"1\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/connect+proto\",\n \"User-Agent\": \"Cursor/3.9\",\n \"connect-accept-encoding\": \"gzip\",\n \"connect-protocol-version\": \"1\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api2.cursor.sh\",\n \"stream\": \"https://api2.cursor.sh\"\n }\n },\n \"dahl\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://inference.dahl.global/v1/chat/completions\",\n \"stream\": \"https://inference.dahl.global/v1/chat/completions\"\n }\n },\n \"databricks\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://adb-0000000000000000.0.azuredatabricks.net/serving-endpoints\",\n \"stream\": \"https://adb-0000000000000000.0.azuredatabricks.net/serving-endpoints\"\n }\n },\n \"deepinfra\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.deepinfra.com/v1/openai/chat/completions\",\n \"stream\": \"https://api.deepinfra.com/v1/openai/chat/completions\"\n }\n },\n \"deepseek\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.deepseek.com/v1/chat/completions\",\n \"stream\": \"https://api.deepseek.com/v1/chat/completions\"\n }\n },\n \"deepseek-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://chat.deepseek.com/api/v0/chat/completion\",\n \"stream\": \"https://chat.deepseek.com/api/v0/chat/completion\"\n }\n },\n \"devin-cli\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"devin://acp/stdio\",\n \"stream\": \"devin://acp/stdio\"\n }\n },\n \"dgrid\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.dgrid.ai/v1/chat/completions\",\n \"stream\": \"https://api.dgrid.ai/v1/chat/completions\"\n }\n },\n \"dify\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.dify.ai/v1/chat/completions\",\n \"stream\": \"https://api.dify.ai/v1/chat/completions\"\n }\n },\n \"digitalocean\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://inference.do-ai.run/v1/chat/completions\",\n \"stream\": \"https://inference.do-ai.run/v1/chat/completions\"\n }\n },\n \"dit\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.dit.ai/v1/chat/completions\",\n \"stream\": \"https://api.dit.ai/v1/chat/completions\"\n }\n },\n \"doubao\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n \"stream\": \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\"\n }\n },\n \"doubao-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://www.dola.com/chat/completion\",\n \"stream\": \"https://www.dola.com/chat/completion\"\n }\n },\n \"duckduckgo-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://duckduckgo.com/duckchat/v1/chat\",\n \"stream\": \"https://duckduckgo.com/duckchat/v1/chat\"\n }\n },\n \"factory\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.factory.ai/v1/chat/completions\",\n \"stream\": \"https://api.factory.ai/v1/chat/completions\"\n }\n },\n \"featherless-ai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.featherless.ai/v1/chat/completions\",\n \"stream\": \"https://api.featherless.ai/v1/chat/completions\"\n }\n },\n \"felo-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://felo.ai/api-proxy/main/search/threads\",\n \"stream\": \"https://felo.ai/api-proxy/main/search/threads\"\n }\n },\n \"fireworks\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.fireworks.ai/inference/v1/chat/completions\",\n \"stream\": \"https://api.fireworks.ai/inference/v1/chat/completions\"\n }\n },\n \"freeaiapikey\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://freeaiapikey.com/v1/chat/completions\",\n \"stream\": \"https://freeaiapikey.com/v1/chat/completions\"\n }\n },\n \"freemodel-dev\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.freemodel.dev/v1/chat/completions\",\n \"stream\": \"https://api.freemodel.dev/v1/chat/completions\"\n }\n },\n \"freetheai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.freetheai.xyz/v1/chat/completions\",\n \"stream\": \"https://api.freetheai.xyz/v1/chat/completions\"\n }\n },\n \"friendliai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.friendli.ai/serverless/v1/chat/completions\",\n \"stream\": \"https://api.friendli.ai/serverless/v1/chat/completions\"\n }\n },\n \"g4f-gemini\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://g4f.space/api/gemini/v1/chat/completions\",\n \"stream\": \"https://g4f.space/api/gemini/v1/chat/completions\"\n }\n },\n \"g4f-groq\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://g4f.space/api/groq/v1/chat/completions\",\n \"stream\": \"https://g4f.space/api/groq/v1/chat/completions\"\n }\n },\n \"g4f-nvidia\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://g4f.space/api/nvidia/v1/chat/completions\",\n \"stream\": \"https://g4f.space/api/nvidia/v1/chat/completions\"\n }\n },\n \"g4f-ollama\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://g4f.space/api/ollama/v1/chat/completions\",\n \"stream\": \"https://g4f.space/api/ollama/v1/chat/completions\"\n }\n },\n \"g4f-pollinations\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://g4f.space/api/pollinations/v1/chat/completions\",\n \"stream\": \"https://g4f.space/api/pollinations/v1/chat/completions\"\n }\n },\n \"galadriel\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.galadriel.ai/v1/chat/completions\",\n \"stream\": \"https://api.galadriel.ai/v1/chat/completions\"\n }\n },\n \"gemini\": {\n \"format\": \"gemini\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": \"<CRED>\"\n },\n \"nonStream\": {\n \"Content-Type\": \"application/json\",\n \"x-goog-api-key\": \"<CRED>\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://generativelanguage.googleapis.com/v1beta/models/test-model:generateContent\",\n \"stream\": \"https://generativelanguage.googleapis.com/v1beta/models/test-model:streamGenerateContent?alt=sse\"\n }\n },\n \"gemini-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://gemini.google.com/app\",\n \"stream\": \"https://gemini.google.com/app\"\n }\n },\n \"ghe-copilot\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-Initiator\": \"user\",\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-plugin-version\": \"copilot-chat/0.54.0\",\n \"editor-version\": \"vscode/1.126.0\",\n \"openai-intent\": \"conversation-panel\",\n \"user-agent\": \"GitHubCopilotChat/0.54.0\",\n \"x-github-api-version\": \"2026-06-01\",\n \"x-vscode-user-agent-library-version\": \"electron-fetch\"\n },\n \"nonStream\": {\n \"Accept\": \"application/json\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-Initiator\": \"user\",\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-plugin-version\": \"copilot-chat/0.54.0\",\n \"editor-version\": \"vscode/1.126.0\",\n \"openai-intent\": \"conversation-panel\",\n \"user-agent\": \"GitHubCopilotChat/0.54.0\",\n \"x-github-api-version\": \"2026-06-01\",\n \"x-vscode-user-agent-library-version\": \"electron-fetch\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-Initiator\": \"user\",\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-plugin-version\": \"copilot-chat/0.54.0\",\n \"editor-version\": \"vscode/1.126.0\",\n \"openai-intent\": \"conversation-panel\",\n \"user-agent\": \"GitHubCopilotChat/0.54.0\",\n \"x-github-api-version\": \"2026-06-01\",\n \"x-vscode-user-agent-library-version\": \"electron-fetch\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.githubcopilot.com/chat/completions\",\n \"stream\": \"https://api.githubcopilot.com/chat/completions\"\n }\n },\n \"gigachat\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://gigachat.devices.sberbank.ru/api/v1\",\n \"stream\": \"https://gigachat.devices.sberbank.ru/api/v1\"\n }\n },\n \"github\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-Initiator\": \"user\",\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-plugin-version\": \"copilot-chat/0.54.0\",\n \"editor-version\": \"vscode/1.126.0\",\n \"openai-intent\": \"conversation-panel\",\n \"user-agent\": \"GitHubCopilotChat/0.54.0\",\n \"x-github-api-version\": \"2026-06-01\",\n \"x-request-id\": \"<UUID>\",\n \"x-vscode-user-agent-library-version\": \"electron-fetch\"\n },\n \"nonStream\": {\n \"Accept\": \"application/json\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-Initiator\": \"user\",\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-plugin-version\": \"copilot-chat/0.54.0\",\n \"editor-version\": \"vscode/1.126.0\",\n \"openai-intent\": \"conversation-panel\",\n \"user-agent\": \"GitHubCopilotChat/0.54.0\",\n \"x-github-api-version\": \"2026-06-01\",\n \"x-request-id\": \"<UUID>\",\n \"x-vscode-user-agent-library-version\": \"electron-fetch\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-Initiator\": \"user\",\n \"copilot-integration-id\": \"vscode-chat\",\n \"editor-plugin-version\": \"copilot-chat/0.54.0\",\n \"editor-version\": \"vscode/1.126.0\",\n \"openai-intent\": \"conversation-panel\",\n \"user-agent\": \"GitHubCopilotChat/0.54.0\",\n \"x-github-api-version\": \"2026-06-01\",\n \"x-request-id\": \"<UUID>\",\n \"x-vscode-user-agent-library-version\": \"electron-fetch\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.githubcopilot.com/chat/completions\",\n \"stream\": \"https://api.githubcopilot.com/chat/completions\"\n }\n },\n \"github-models\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\"\n },\n \"nonStream\": {\n \"Accept\": \"application/vnd.github+json\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://models.github.ai/inference/chat/completions\",\n \"stream\": \"https://models.github.ai/inference/chat/completions\"\n }\n },\n \"gitlab-duo\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://gitlab.com/api/v4/code_suggestions/completions\",\n \"stream\": \"https://gitlab.com/api/v4/code_suggestions/completions\"\n }\n },\n \"gitlawb\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://github.com/Gitlawb/openclaude\",\n \"User-Agent\": \"OpenClaude/1.0 (<OS>; <ARCH>)\",\n \"X-Title\": \"OpenClaude CLI\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://github.com/Gitlawb/openclaude\",\n \"User-Agent\": \"OpenClaude/1.0 (<OS>; <ARCH>)\",\n \"X-Title\": \"OpenClaude CLI\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://github.com/Gitlawb/openclaude\",\n \"User-Agent\": \"OpenClaude/1.0 (<OS>; <ARCH>)\",\n \"X-Title\": \"OpenClaude CLI\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://opengateway.gitlawb.com/v1/xiaomi-mimo\",\n \"stream\": \"https://opengateway.gitlawb.com/v1/xiaomi-mimo\"\n }\n },\n \"gitlawb-gmi\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://github.com/Gitlawb/openclaude\",\n \"User-Agent\": \"OpenClaude/1.0 (<OS>; <ARCH>)\",\n \"X-Title\": \"OpenClaude CLI\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://github.com/Gitlawb/openclaude\",\n \"User-Agent\": \"OpenClaude/1.0 (<OS>; <ARCH>)\",\n \"X-Title\": \"OpenClaude CLI\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://github.com/Gitlawb/openclaude\",\n \"User-Agent\": \"OpenClaude/1.0 (<OS>; <ARCH>)\",\n \"X-Title\": \"OpenClaude CLI\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://opengateway.gitlawb.com/v1/gmi-cloud\",\n \"stream\": \"https://opengateway.gitlawb.com/v1/gmi-cloud\"\n }\n },\n \"glm\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.z.ai/api/coding/paas/v4/chat/completions\",\n \"stream\": \"https://api.z.ai/api/coding/paas/v4/chat/completions\"\n }\n },\n \"glm-cn\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://open.bigmodel.cn/api/coding/paas/v4/chat/completions\",\n \"stream\": \"https://open.bigmodel.cn/api/coding/paas/v4/chat/completions\"\n }\n },\n \"glmt\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.z.ai/api/coding/paas/v4/chat/completions\",\n \"stream\": \"https://api.z.ai/api/coding/paas/v4/chat/completions\"\n }\n },\n \"grok-cli\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://cli-chat-proxy.grok.com/v1/chat/completions\",\n \"stream\": \"https://cli-chat-proxy.grok.com/v1/chat/completions\"\n }\n },\n \"grok-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://grok.com/rest/app-chat/conversations/new\",\n \"stream\": \"https://grok.com/rest/app-chat/conversations/new\"\n }\n },\n \"groq\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.groq.com/openai/v1/chat/completions\",\n \"stream\": \"https://api.groq.com/openai/v1/chat/completions\"\n }\n },\n \"hackclub\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://ai.hackclub.com/proxy/v1/chat/completions\",\n \"stream\": \"https://ai.hackclub.com/proxy/v1/chat/completions\"\n }\n },\n \"haiper\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.haiper.ai/v1\",\n \"stream\": \"https://api.haiper.ai/v1\"\n }\n },\n \"hcnsec\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.hcnsec.cn/v1/chat/completions\",\n \"stream\": \"https://api.hcnsec.cn/v1/chat/completions\"\n }\n },\n \"heroku\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://us.inference.heroku.com/v1/chat/completions\",\n \"stream\": \"https://us.inference.heroku.com/v1/chat/completions\"\n }\n },\n \"huggingchat\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://huggingface.co/chat/conversation\",\n \"stream\": \"https://huggingface.co/chat/conversation\"\n }\n },\n \"huggingface\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://router.huggingface.co/v1/chat/completions\",\n \"stream\": \"https://router.huggingface.co/v1/chat/completions\"\n }\n },\n \"hyperbolic\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.hyperbolic.xyz/v1/chat/completions\",\n \"stream\": \"https://api.hyperbolic.xyz/v1/chat/completions\"\n }\n },\n \"ideogram\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.ideogram.ai\",\n \"stream\": \"https://api.ideogram.ai\"\n }\n },\n \"iflytek\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://spark-api.xf-yun.com/v1/chat/completions\",\n \"stream\": \"https://spark-api.xf-yun.com/v1/chat/completions\"\n }\n },\n \"inference-net\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.inference.net/v1/chat/completions\",\n \"stream\": \"https://api.inference.net/v1/chat/completions\"\n }\n },\n \"inner-ai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://chatapi.innerai.com/chat\",\n \"stream\": \"https://chatapi.innerai.com/chat\"\n }\n },\n \"kenari\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://kenari.id/v1/chat/completions\",\n \"stream\": \"https://kenari.id/v1/chat/completions\"\n }\n },\n \"kie\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.kie.ai/v1/chat/completions\",\n \"stream\": \"https://api.kie.ai/v1/chat/completions\"\n }\n },\n \"kilo-gateway\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.kilo.ai/api/gateway/chat/completions\",\n \"stream\": \"https://api.kilo.ai/api/gateway/chat/completions\"\n }\n },\n \"kilocode\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-KILOCODE-EDITORNAME\": \"OmniRoute\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-KILOCODE-EDITORNAME\": \"OmniRoute\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"X-KILOCODE-EDITORNAME\": \"OmniRoute\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.kilo.ai/api/openrouter/chat/completions\",\n \"stream\": \"https://api.kilo.ai/api/openrouter/chat/completions\"\n }\n },\n \"kimi\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.moonshot.ai/v1/chat/completions\",\n \"stream\": \"https://api.moonshot.ai/v1/chat/completions\"\n }\n },\n \"kimi-coding\": {\n \"format\": \"claude\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"nonStream\": {\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.kimi.com/coding/v1/messages?beta=true\",\n \"stream\": \"https://api.kimi.com/coding/v1/messages?beta=true\"\n }\n },\n \"kimi-coding-apikey\": {\n \"format\": \"claude\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"nonStream\": {\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.kimi.com/coding/v1/messages?beta=true\",\n \"stream\": \"https://api.kimi.com/coding/v1/messages?beta=true\"\n }\n },\n \"kimi-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://www.kimi.com\",\n \"stream\": \"https://www.kimi.com\"\n }\n },\n \"kiro\": {\n \"format\": \"kiro\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"AWS-SDK-JS/3.0.0 kiro-ide/1.0.0\",\n \"X-Amz-Target\": \"AmazonCodeWhispererStreamingService.GenerateAssistantResponse\",\n \"X-Amz-User-Agent\": \"aws-sdk-js/3.0.0 kiro-ide/1.0.0\"\n },\n \"nonStream\": {\n \"Accept\": \"application/vnd.amazon.eventstream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"AWS-SDK-JS/3.0.0 kiro-ide/1.0.0\",\n \"X-Amz-Target\": \"AmazonCodeWhispererStreamingService.GenerateAssistantResponse\",\n \"X-Amz-User-Agent\": \"aws-sdk-js/3.0.0 kiro-ide/1.0.0\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"AWS-SDK-JS/3.0.0 kiro-ide/1.0.0\",\n \"X-Amz-Target\": \"AmazonCodeWhispererStreamingService.GenerateAssistantResponse\",\n \"X-Amz-User-Agent\": \"aws-sdk-js/3.0.0 kiro-ide/1.0.0\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://codewhisperer.us-east-1.amazonaws.com/generateAssistantResponse\",\n \"stream\": \"https://codewhisperer.us-east-1.amazonaws.com/generateAssistantResponse\"\n }\n },\n \"lambda-ai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.lambda.ai/v1/chat/completions\",\n \"stream\": \"https://api.lambda.ai/v1/chat/completions\"\n }\n },\n \"leonardo\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://cloud.leonardo.ai/api/rest/v1\",\n \"stream\": \"https://cloud.leonardo.ai/api/rest/v1\"\n }\n },\n \"liquid\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://inference.liquid.ai/v1/chat/completions\",\n \"stream\": \"https://inference.liquid.ai/v1/chat/completions\"\n }\n },\n \"llamagate\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://llamagate.ai/v1/chat/completions\",\n \"stream\": \"https://llamagate.ai/v1/chat/completions\"\n }\n },\n \"llm7\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.llm7.io/v1/chat/completions\",\n \"stream\": \"https://api.llm7.io/v1/chat/completions\"\n }\n },\n \"lmarena\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://arena.ai/nextjs-api/stream/create-evaluation\",\n \"stream\": \"https://arena.ai/nextjs-api/stream/create-evaluation\"\n }\n },\n \"longcat\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.longcat.chat/openai/v1/chat/completions\",\n \"stream\": \"https://api.longcat.chat/openai/v1/chat/completions\"\n }\n },\n \"maritalk\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Key <CRED>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Key <CRED>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Key <CRED>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://chat.maritaca.ai/api\",\n \"stream\": \"https://chat.maritaca.ai/api\"\n }\n },\n \"meta-llama\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.llama.com/compat/v1/chat/completions\",\n \"stream\": \"https://api.llama.com/compat/v1/chat/completions\"\n }\n },\n \"mimocode\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.xiaomimimo.com\",\n \"stream\": \"https://api.xiaomimimo.com\"\n }\n },\n \"minimax\": {\n \"format\": \"claude\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Anthropic-Version\": \"2023-06-01\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.minimax.io/anthropic/v1/messages?beta=true\",\n \"stream\": \"https://api.minimax.io/anthropic/v1/messages?beta=true\"\n }\n },\n \"minimax-cn\": {\n \"format\": \"claude\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Anthropic-Version\": \"2023-06-01\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.minimaxi.com/anthropic/v1/messages?beta=true\",\n \"stream\": \"https://api.minimaxi.com/anthropic/v1/messages?beta=true\"\n }\n },\n \"mistral\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.mistral.ai/v1/chat/completions\",\n \"stream\": \"https://api.mistral.ai/v1/chat/completions\"\n }\n },\n \"modal\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.modal.ai/v1/chat/completions\",\n \"stream\": \"https://api.modal.ai/v1/chat/completions\"\n }\n },\n \"modelscope\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api-inference.modelscope.cn/v1/chat/completions\",\n \"stream\": \"https://api-inference.modelscope.cn/v1/chat/completions\"\n }\n },\n \"monsterapi\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.monsterapi.ai/v1/chat/completions\",\n \"stream\": \"https://api.monsterapi.ai/v1/chat/completions\"\n }\n },\n \"moonshot\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.moonshot.ai/v1/chat/completions\",\n \"stream\": \"https://api.moonshot.ai/v1/chat/completions\"\n }\n },\n \"morph\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.morphllm.com/v1/chat/completions\",\n \"stream\": \"https://api.morphllm.com/v1/chat/completions\"\n }\n },\n \"muse-spark-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://www.meta.ai/api/graphql\",\n \"stream\": \"https://www.meta.ai/api/graphql\"\n }\n },\n \"nanogpt\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://nano-gpt.com/api/v1/chat/completions\",\n \"stream\": \"https://nano-gpt.com/api/v1/chat/completions\"\n }\n },\n \"navy\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"OmniRoute/1.0\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"OmniRoute/1.0\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"OmniRoute/1.0\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.navy/v1/chat/completions\",\n \"stream\": \"https://api.navy/v1/chat/completions\"\n }\n },\n \"nebius\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.tokenfactory.nebius.com/v1/chat/completions\",\n \"stream\": \"https://api.tokenfactory.nebius.com/v1/chat/completions\"\n }\n },\n \"nlpcloud\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.nlpcloud.io/v1/chat/completions\",\n \"stream\": \"https://api.nlpcloud.io/v1/chat/completions\"\n }\n },\n \"notion-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://app.notion.com/api/v3/runInferenceTranscript\",\n \"stream\": \"https://app.notion.com/api/v3/runInferenceTranscript\"\n }\n },\n \"nous-research\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://inference-api.nousresearch.com/v1/chat/completions\",\n \"stream\": \"https://inference-api.nousresearch.com/v1/chat/completions\"\n }\n },\n \"novita\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.novita.ai/openai/v1/chat/completions\",\n \"stream\": \"https://api.novita.ai/openai/v1/chat/completions\"\n }\n },\n \"nscale\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://inference.api.nscale.com/v1/chat/completions\",\n \"stream\": \"https://inference.api.nscale.com/v1/chat/completions\"\n }\n },\n \"nube\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://ai.nube.sh/api/v1/chat/completions\",\n \"stream\": \"https://ai.nube.sh/api/v1/chat/completions\"\n }\n },\n \"nvidia\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://integrate.api.nvidia.com/v1/chat/completions\",\n \"stream\": \"https://integrate.api.nvidia.com/v1/chat/completions\"\n }\n },\n \"ollama-cloud\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://ollama.com/v1/chat/completions\",\n \"stream\": \"https://ollama.com/v1/chat/completions\"\n }\n },\n \"openadapter\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.openadapter.in/v1/chat/completions\",\n \"stream\": \"https://api.openadapter.in/v1/chat/completions\"\n }\n },\n \"openai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.openai.com/v1/chat/completions\",\n \"stream\": \"https://api.openai.com/v1/chat/completions\"\n }\n },\n \"opencode\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://opencode.ai/zen/v1\",\n \"stream\": \"https://opencode.ai/zen/v1\"\n }\n },\n \"opencode-go\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://opencode.ai/zen/go/v1\",\n \"stream\": \"https://opencode.ai/zen/go/v1\"\n }\n },\n \"opencode-zen\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://opencode.ai/zen/v1\",\n \"stream\": \"https://opencode.ai/zen/v1\"\n }\n },\n \"openrouter\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://endpoint-proxy.local\",\n \"X-Title\": \"Endpoint Proxy\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://endpoint-proxy.local\",\n \"X-Title\": \"Endpoint Proxy\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://endpoint-proxy.local\",\n \"X-Title\": \"Endpoint Proxy\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://openrouter.ai/api/v1/chat/completions\",\n \"stream\": \"https://openrouter.ai/api/v1/chat/completions\"\n }\n },\n \"openvecta\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.openvecta.com/v1/chat/completions\",\n \"stream\": \"https://api.openvecta.com/v1/chat/completions\"\n }\n },\n \"orcarouter\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://endpoint-proxy.local\",\n \"X-Title\": \"Endpoint Proxy\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://endpoint-proxy.local\",\n \"X-Title\": \"Endpoint Proxy\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"HTTP-Referer\": \"https://endpoint-proxy.local\",\n \"X-Title\": \"Endpoint Proxy\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.orcarouter.ai/v1\",\n \"stream\": \"https://api.orcarouter.ai/v1\"\n }\n },\n \"ovhcloud\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://oai.endpoints.kepler.ai.cloud.ovh.net/v1/chat/completions\",\n \"stream\": \"https://oai.endpoints.kepler.ai.cloud.ovh.net/v1/chat/completions\"\n }\n },\n \"perplexity\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.perplexity.ai/chat/completions\",\n \"stream\": \"https://api.perplexity.ai/chat/completions\"\n }\n },\n \"perplexity-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://www.perplexity.ai/rest/sse/perplexity_ask\",\n \"stream\": \"https://www.perplexity.ai/rest/sse/perplexity_ask\"\n }\n },\n \"pioneer\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"nonStream\": {\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.pioneer.ai/v1/chat/completions\",\n \"stream\": \"https://api.pioneer.ai/v1/chat/completions\"\n }\n },\n \"pollinations\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://gen.pollinations.ai/v1/chat/completions\",\n \"stream\": \"https://gen.pollinations.ai/v1/chat/completions\"\n }\n },\n \"predibase\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://serving.app.predibase.com/v1/chat/completions\",\n \"stream\": \"https://serving.app.predibase.com/v1/chat/completions\"\n }\n },\n \"publicai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.publicai.co/v1/chat/completions\",\n \"stream\": \"https://api.publicai.co/v1/chat/completions\"\n }\n },\n \"puter\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.puter.com/puterai/openai/v1/chat/completions\",\n \"stream\": \"https://api.puter.com/puterai/openai/v1/chat/completions\"\n }\n },\n \"qianfan\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://qianfan.baidubce.com/v2/chat/completions\",\n \"stream\": \"https://qianfan.baidubce.com/v2/chat/completions\"\n }\n },\n \"qiniu\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.qnaigc.com/v1/chat/completions\",\n \"stream\": \"https://api.qnaigc.com/v1/chat/completions\"\n }\n },\n \"qoder\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Qoder-Cli\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Qoder-Cli\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"Qoder-Cli\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.qoder.com/v1/chat/completions\",\n \"stream\": \"https://api.qoder.com/v1/chat/completions\"\n }\n },\n \"qwen-cloud\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions\",\n \"stream\": \"https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions\"\n }\n },\n \"qwen-cloud-token-plan\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1/chat/completions\",\n \"stream\": \"https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1/chat/completions\"\n }\n },\n \"qwen-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://chat.qwen.ai/api/v2/chat/completions\",\n \"stream\": \"https://chat.qwen.ai/api/v2/chat/completions\"\n }\n },\n \"reka\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.reka.ai/v1/chat/completions\",\n \"stream\": \"https://api.reka.ai/v1/chat/completions\"\n }\n },\n \"requesty\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://router.requesty.ai/v1/chat/completions\",\n \"stream\": \"https://router.requesty.ai/v1/chat/completions\"\n }\n },\n \"sambanova\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.sambanova.ai/v1/chat/completions\",\n \"stream\": \"https://api.sambanova.ai/v1/chat/completions\"\n }\n },\n \"scaleway\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.scaleway.ai/v1/chat/completions\",\n \"stream\": \"https://api.scaleway.ai/v1/chat/completions\"\n }\n },\n \"sensenova\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://token.sensenova.cn/v1/chat/completions\",\n \"stream\": \"https://token.sensenova.cn/v1/chat/completions\"\n }\n },\n \"siliconflow\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.siliconflow.com/v1/chat/completions\",\n \"stream\": \"https://api.siliconflow.com/v1/chat/completions\"\n }\n },\n \"snowflake\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://{account}.snowflakecomputing.com/api/v2\",\n \"stream\": \"https://{account}.snowflakecomputing.com/api/v2\"\n }\n },\n \"sparkdesk\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://spark-api.xf-yun.com/v3.1/chat/completions\",\n \"stream\": \"https://spark-api.xf-yun.com/v3.1/chat/completions\"\n }\n },\n \"stepfun\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.stepfun.com/v1/chat/completions\",\n \"stream\": \"https://api.stepfun.com/v1/chat/completions\"\n }\n },\n \"sumopod\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://ai.sumopod.com/v1/chat/completions\",\n \"stream\": \"https://ai.sumopod.com/v1/chat/completions\"\n }\n },\n \"suno\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://studio-api.suno.ai/api/generate/v2/\",\n \"stream\": \"https://studio-api.suno.ai/api/generate/v2/\"\n }\n },\n \"synthetic\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.synthetic.new/openai/v1/chat/completions\",\n \"stream\": \"https://api.synthetic.new/openai/v1/chat/completions\"\n }\n },\n \"t3-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://t3.chat/api/chat\",\n \"stream\": \"https://t3.chat/api/chat\"\n }\n },\n \"tencent\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n \"stream\": \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\"\n }\n },\n \"theoldllm\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://theoldllm.vercel.app/api/chatgpt\",\n \"stream\": \"https://theoldllm.vercel.app/api/chatgpt\"\n }\n },\n \"together\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.together.xyz/v1/chat/completions\",\n \"stream\": \"https://api.together.xyz/v1/chat/completions\"\n }\n },\n \"tokenrouter\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.tokenrouter.com/v1/chat/completions\",\n \"stream\": \"https://api.tokenrouter.com/v1/chat/completions\"\n }\n },\n \"trae\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://core-normal.trae.ai/api/remote/v1\",\n \"stream\": \"https://core-normal.trae.ai/api/remote/v1\"\n }\n },\n \"udio\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://www.udio.com/api/generate-proxy\",\n \"stream\": \"https://www.udio.com/api/generate-proxy\"\n }\n },\n \"uncloseai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://hermes.ai.unturf.com/v1/chat/completions\",\n \"stream\": \"https://hermes.ai.unturf.com/v1/chat/completions\"\n }\n },\n \"upstage\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.upstage.ai/v1/chat/completions\",\n \"stream\": \"https://api.upstage.ai/v1/chat/completions\"\n }\n },\n \"v0-vercel\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.v0.dev/v1/chat/completions\",\n \"stream\": \"https://api.v0.dev/v1/chat/completions\"\n }\n },\n \"venice\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.venice.ai/api/v1/chat/completions\",\n \"stream\": \"https://api.venice.ai/api/v1/chat/completions\"\n }\n },\n \"veoaifree-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://veoaifree.com/wp-admin/admin-ajax.php\",\n \"stream\": \"https://veoaifree.com/wp-admin/admin-ajax.php\"\n }\n },\n \"vercel-ai-gateway\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://ai-gateway.vercel.sh/v1/chat/completions\",\n \"stream\": \"https://ai-gateway.vercel.sh/v1/chat/completions\"\n }\n },\n \"vertex\": {\n \"format\": \"gemini\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://generativelanguage.googleapis.com/v1beta/models/test-model:generateContent\",\n \"stream\": \"https://generativelanguage.googleapis.com/v1beta/models/test-model:streamGenerateContent?alt=sse\"\n }\n },\n \"vertex-partner\": {\n \"format\": \"gemini\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://us-central1-aiplatform.googleapis.com/v1/projects\",\n \"stream\": \"https://us-central1-aiplatform.googleapis.com/v1/projects\"\n }\n },\n \"volcengine\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n \"stream\": \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\"\n }\n },\n \"wafer\": {\n \"format\": \"claude\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Anthropic-Version\": \"2023-06-01\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://pass.wafer.ai/v1/messages\",\n \"stream\": \"https://pass.wafer.ai/v1/messages\"\n }\n },\n \"wandb\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.inference.wandb.ai/v1/chat/completions\",\n \"stream\": \"https://api.inference.wandb.ai/v1/chat/completions\"\n }\n },\n \"windsurf\": {\n \"format\": \"windsurf\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://server.self-serve.windsurf.com\",\n \"stream\": \"https://server.self-serve.windsurf.com\"\n }\n },\n \"x5lab\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.x5lab.dev/v1/chat/completions\",\n \"stream\": \"https://api.x5lab.dev/v1/chat/completions\"\n }\n },\n \"xai\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.x.ai/v1/chat/completions\",\n \"stream\": \"https://api.x.ai/v1/chat/completions\"\n }\n },\n \"xai-oauth\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.x.ai/v1/chat/completions\",\n \"stream\": \"https://api.x.ai/v1/chat/completions\"\n }\n },\n \"xiaomi-mimo\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.xiaomimimo.com/v1\",\n \"stream\": \"https://api.xiaomimimo.com/v1\"\n }\n },\n \"yi\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.lingyiwanwu.com/v1/chat/completions\",\n \"stream\": \"https://api.lingyiwanwu.com/v1/chat/completions\"\n }\n },\n \"yuanbao-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://yuanbao.tencent.com/api/chat\",\n \"stream\": \"https://yuanbao.tencent.com/api/chat\"\n }\n },\n \"zai\": {\n \"format\": \"claude\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"nonStream\": {\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Anthropic-Version\": \"2023-06-01\",\n \"Content-Type\": \"application/json\",\n \"x-api-key\": \"<CRED>\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://api.z.ai/api/anthropic/v1/messages?beta=true\",\n \"stream\": \"https://api.z.ai/api/anthropic/v1/messages?beta=true\"\n }\n },\n \"zai-web\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://chat.z.ai\",\n \"stream\": \"https://chat.z.ai\"\n }\n },\n \"zed-hosted\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://cloud.zed.dev/completions\",\n \"stream\": \"https://cloud.zed.dev/completions\"\n }\n },\n \"zenmux\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://zenmux.ai/api/v1/chat/completions\",\n \"stream\": \"https://zenmux.ai/api/v1/chat/completions\"\n }\n },\n \"zenmux-free\": {\n \"format\": \"openai\",\n \"headers\": {\n \"apiKey\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"nonStream\": {\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n },\n \"oauth\": {\n \"Accept\": \"text/event-stream\",\n \"Authorization\": \"Bearer <TOK>\",\n \"Content-Type\": \"application/json\"\n }\n },\n \"url\": {\n \"nonStream\": \"https://zenmux.ai/api/anthropic/v1/messages\",\n \"stream\": \"https://zenmux.ai/api/anthropic/v1/messages\"\n }\n }\n}\n"}}, "strix/strix/config/models.py": {"6eea4894299d5371c00c11f1f6dec2f7c0076253": {"t": 1785746493.6189537, "n": 14904, "h": "5f2600dc1a7f4774", "c": "\"\"\"SDK model configuration helpers.\"\"\"\n\nfrom __future__ import annotations\n\nimport contextlib\nimport inspect\nimport os\nfrom typing import TYPE_CHECKING, Any\n\nfrom agents import (\n set_default_openai_api,\n set_default_openai_key,\n set_tracing_disabled,\n)\nfrom agents.model_settings import ModelSettings\nfrom agents.models.multi_provider import MultiProvider\nfrom agents.models.openai_responses import OpenAIResponsesModel\nfrom agents.retry import (\n ModelRetryBackoffSettings,\n ModelRetrySettings,\n RetryPolicyContext,\n retry_policies,\n)\nfrom openai.types.shared import Reasoning\n\nfrom strix.config import codex\nfrom strix.config.loader import load_settings\n\n\nif TYPE_CHECKING:\n from collections.abc import AsyncIterator\n\n from agents.models.interface import Model, ModelProvider\n from openai import AsyncOpenAI\n\n from strix.config.settings import ReasoningEffort, Settings\n\n\ndef request_timeout_extra_args(timeout_s: float | None) -> dict[str, float] | None:\n \"\"\"Per-request model timeout; a plain float so ``ModelSettings.to_json_dict()`` stays serializable.\"\"\" # noqa: E501\n if not timeout_s or timeout_s <= 0:\n return None\n return {\"timeout\": timeout_s}\n\n\ndef _retry_statusless_provider_errors(context: RetryPolicyContext) -> bool:\n \"\"\"Retry statusless provider errors (e.g. mid-stream quota/billing), but not aborts.\"\"\"\n normalized = context.normalized\n if normalized.is_abort:\n return False\n if codex.is_content_guardrail_error(context.error):\n return False\n return normalized.status_code is None\n\n\nclass _CodexResponsesModel(OpenAIResponsesModel):\n \"\"\"Responses model for the ChatGPT subscription backend (always streamed, stateless).\"\"\"\n\n def __init__(\n self,\n model: str,\n openai_client: AsyncOpenAI,\n *,\n reasoning_effort: ReasoningEffort | None = None,\n ) -> None:\n super().__init__(model, openai_client)\n self._reasoning_effort = reasoning_effort\n\n def _codex_settings(self, model_settings: ModelSettings) -> ModelSettings:\n overrides = ModelSettings(store=False, response_include=[\"reasoning.encrypted_content\"])\n effort = self._reasoning_effort\n if effort and effort != \"none\":\n # Clamp to efforts the backend accepts.\n if effort == \"minimal\":\n effort = \"low\"\n elif effort == \"xhigh\":\n effort = \"high\"\n overrides = overrides.resolve(ModelSettings(reasoning=Reasoning(effort=effort)))\n return model_settings.resolve(overrides)\n\n async def _fetch_response(self, *args: Any, stream: bool = False, **kwargs: Any) -> Any:\n if len(args) >= 3: # model_settings is positional arg 2\n args = (*args[:2], self._codex_settings(args[2]), *args[3:])\n try:\n events = await super()._fetch_response(*args, stream=True, **kwargs) # type: ignore[call-overload]\n except Exception as exc:\n guardrail = self._as_guardrail(exc)\n if guardrail is not None:\n raise guardrail from exc\n raise\n guarded = self._guarded(events)\n if stream:\n return guarded\n final_response = None\n async for event in guarded:\n if getattr(event, \"type\", None) == \"response.completed\":\n final_response = event.response\n if final_response is None:\n msg = \"ChatGPT backend stream ended without a completed response\"\n raise RuntimeError(msg)\n return final_response\n\n def _as_guardrail(self, exc: BaseException) -> codex.CodexContentGuardrailError | None:\n if isinstance(exc, codex.CodexContentGuardrailError):\n return exc\n if codex.is_content_guardrail_error(exc):\n return codex.CodexContentGuardrailError(self.model, exc)\n return None\n\n async def _guarded(self, events: Any) -> AsyncIterator[Any]:\n \"\"\"Convert mid-stream guardrail rejections and close the stream on exit.\"\"\"\n try:\n async for event in events:\n yield event\n except Exception as exc:\n guardrail = self._as_guardrail(exc)\n if guardrail is not None:\n raise guardrail from exc\n raise\n finally:\n await self._aclose(events)\n\n @staticmethod\n async def _aclose(events: Any) -> None:\n aclose = getattr(events, \"aclose\", None)\n if callable(aclose):\n with contextlib.suppress(Exception):\n await aclose()\n return\n close = getattr(events, \"close\", None)\n if callable(close):\n with contextlib.suppress(Exception):\n result = close()\n if inspect.isawaitable(result):\n await result\n\n\nclass StrixProvider(MultiProvider):\n \"\"\"Route any non-OpenAI prefix through LiteLLM with the prefix preserved,\n so users type ``deepseek/deepseek-chat`` rather than\n ``litellm/deepseek/deepseek-chat``.\n \"\"\"\n\n def _resolve_prefixed_model(\n self,\n *,\n original_model_name: str,\n prefix: str,\n stripped_model_name: str | None,\n ) -> tuple[ModelProvider, str | None]:\n if prefix in {\"openai\", \"litellm\", \"any-llm\"}:\n return super()._resolve_prefixed_model(\n original_model_name=original_model_name,\n prefix=prefix,\n stripped_model_name=stripped_model_name,\n )\n if prefix == \"ollama\" and stripped_model_name:\n return self._get_fallback_provider(\"litellm\"), f\"ollama_chat/{stripped_model_name}\"\n return self._get_fallback_provider(\"litellm\"), original_model_name\n\n def get_model(self, model_name: str | None) -> Model:\n slug = codex.subscription_model(model_name)\n if slug:\n return _CodexResponsesModel(\n slug,\n codex.get_subscription_client(),\n reasoning_effort=load_settings().llm.reasoning_effort,\n )\n return super().get_model(model_name)\n\n\nDEFAULT_MODEL_RETRY = ModelRetrySettings(\n max_retries=5,\n backoff=ModelRetryBackoffSettings(\n initial_delay=2.0,\n max_delay=90.0,\n multiplier=2.0,\n jitter=False,\n ),\n policy=retry_policies.any(\n retry_policies.provider_suggested(),\n retry_policies.network_error(),\n retry_policies.http_status((429, 500, 502, 503, 504)),\n _retry_statusless_provider_errors,\n ),\n)\n\nRECOMMENDED_MODEL_NAMES = (\n \"openai/gpt-5.6-sol\",\n \"openai/gpt-5.6-terra\",\n \"openai/gpt-5.6-luna\",\n \"openai/gpt-5.6\",\n \"openai/gpt-5.5-pro\",\n \"openai/gpt-5.5\",\n \"openai/gpt-5.4\",\n \"openai/gpt-5.3-codex\",\n \"anthropic/claude-fable-5\",\n \"anthropic/claude-opus-5\",\n \"anthropic/claude-opus-4-8\",\n \"anthropic/claude-sonnet-5\",\n \"anthropic/claude-sonnet-4-6\",\n \"vertex_ai/gemini-3.1-pro-preview\",\n \"gemini/gemini-3.1-pro-preview\",\n \"gemini/gemini-3.6-flash\",\n \"deepseek/deepseek-v4-pro\",\n \"deepseek/deepseek-v4-flash\",\n \"dashscope/qwen3.8-max\",\n \"dashscope/qwen3.7-max-2026-06-08\",\n \"moonshot/kimi-k3\",\n \"moonshot/kimi-k2.7-code\",\n)\n\n_RECOMMENDED_MODEL_NAME_SET = frozenset(name.lower() for name in RECOMMENDED_MODEL_NAMES)\n\nFRONTIER_MODEL_FAMILIES = (\n ((\"azure\", \"azure_ai\", \"bedrock_mantle\", \"chatgpt\", \"openai\"), (\"gpt-5\",)),\n (\n (\"anthropic\", \"azure_ai\", \"bedrock\", \"claude\", \"databricks\", \"snowflake\", \"vertex_ai\"),\n (\"claude-fable-5\", \"claude-opus-5\", \"claude-opus-4\", \"claude-sonnet-5\", \"claude-sonnet-4\"),\n ),\n ((\"google\", \"gemini\", \"vertex_ai\"), (\"gemini-3\",)),\n ((\"deepseek\",), (\"deepseek-v4\", \"deepseek-r1\", \"deepseek-reasoner\")),\n ((\"alibaba\", \"dashscope\", \"qwen\"), (\"qwen3.8\", \"qwen3.7\", \"qwen3-max\")),\n ((\"moonshot\", \"moonshotai\", \"kimi\"), (\"kimi-k3\", \"kimi-k2.7\", \"kimi-k2.6\")),\n)\n\n\ndef configure_sdk_model_defaults(settings: Settings) -> None:\n \"\"\"Apply Strix config to SDK-native defaults.\"\"\"\n llm = settings.llm\n set_tracing_disabled(True)\n if codex.subscription_model(llm.model):\n return\n _configure_litellm_compatibility()\n _configure_openrouter_attribution(llm.model)\n if llm.api_key:\n set_default_openai_key(llm.api_key, use_for_tracing=False)\n _configure_litellm_default(\"api_key\", llm.api_key)\n _mirror_api_key_to_provider_env(llm.model, llm.api_key)\n if llm.api_base:\n os.environ[\"OPENAI_BASE_URL\"] = llm.api_base\n _configure_litellm_default(\"api_base\", llm.api_base)\n set_default_openai_api(\"chat_completions\")\n else:\n set_default_openai_api(\"responses\")\n\n\ndef _mirror_api_key_to_provider_env(model_name: str | None, api_key: str) -> None:\n if not model_name:\n return\n import litellm\n\n name = model_name.strip()\n for prefix in (\"litellm/\", \"any-llm/\"):\n if name.lower().startswith(prefix):\n name = name[len(prefix) :]\n break\n try:\n report = litellm.validate_environment(model=name.lower())\n except Exception: # noqa: BLE001\n return\n for env_key in report.get(\"missing_keys\") or []:\n if env_key.endswith(\"_API_KEY\"):\n os.environ.setdefault(env_key, api_key)\n\n\ndef _configure_litellm_compatibility() -> None:\n \"\"\"Apply LiteLLM compatibility, privacy, and callback settings.\"\"\"\n import litellm\n\n litellm.drop_params = True\n litellm.modify_params = True\n litellm.turn_off_message_logging = True\n # Strix uses LiteLLM's success callback to capture provider-reported cost.\n # Disabling streaming logging also disables that callback for streamed calls.\n litellm.disable_streaming_logging = False\n litellm.suppress_debug_info = True\n\n _register_litellm_cost_callback()\n\n\n_OPENROUTER_ATTRIBUTION_HEADERS = {\n \"HTTP-Referer\": \"https://strix.ai\",\n \"X-Title\": \"Strix\",\n \"X-OpenRouter-Categories\": \"cli-agent\",\n}\n\n\ndef _configure_openrouter_attribution(model_name: str | None) -> None:\n import litellm\n\n current: object = litellm.headers\n existing: dict[str, str] = current if isinstance(current, dict) else {}\n if not model_name or \"openrouter/\" not in model_name.strip().lower():\n if any(key in existing for key in _OPENROUTER_ATTRIBUTION_HEADERS):\n remaining = {\n k: v for k, v in existing.items() if k not in _OPENROUTER_ATTRIBUTION_HEADERS\n }\n litellm.headers = remaining or None # type: ignore[assignment]\n return\n\n litellm.headers = {**existing, **_OPENROUTER_ATTRIBUTION_HEADERS} # type: ignore[assignment]\n\n\ndef _register_litellm_cost_callback() -> None:\n import litellm\n\n from strix.report.state import litellm_cost_callback\n\n for bucket_name in (\"success_callback\", \"_async_success_callback\"):\n bucket = getattr(litellm, bucket_name, None)\n if not isinstance(bucket, list):\n continue\n if litellm_cost_callback in bucket:\n continue\n bucket.append(litellm_cost_callback)\n\n\ndef _configure_litellm_default(name: str, value: str) -> None:\n \"\"\"Set LiteLLM's module-level defaults without adding a provider wrapper.\"\"\"\n import litellm\n\n setattr(litellm, name, value)\n\n\ndef uses_chat_completions_tool_schema(model_name: str, settings: Settings) -> bool:\n \"\"\"Return whether the resolved SDK route can only receive JSON function tools.\"\"\"\n if codex.subscription_model(model_name):\n return False\n model = model_name.strip().lower()\n if \"/\" in model and not model.startswith(\"openai/\"):\n return True\n if settings.llm.api_base:\n return True\n return not model_supports_reasoning(model_name)\n\n\ndef model_supports_reasoning(model_name: str) -> bool:\n import litellm\n\n name = model_name.strip().lower()\n for prefix in (\"litellm/\", \"any-llm/\", \"openai/\"):\n if name.startswith(prefix):\n name = name[len(prefix) :]\n break\n entry = litellm.model_cost.get(name)\n if entry is None and \"/\" in name:\n entry = litellm.model_cost.get(name.rsplit(\"/\", 1)[1])\n return bool(entry and entry.get(\"supports_reasoning\"))\n\n\ndef is_recommended_or_frontier_model(model_name: str) -> bool:\n \"\"\"Return whether a model is recommended or in a frontier model family.\"\"\"\n name = _normalized_model_name(model_name)\n if not name:\n return False\n if name in _RECOMMENDED_MODEL_NAME_SET:\n return True\n provider_name, bare_model_name = _split_model_provider(name)\n return any(\n _matches_frontier_family(provider_name, bare_model_name, provider_markers, prefixes)\n for provider_markers, prefixes in FRONTIER_MODEL_FAMILIES\n )\n\n\ndef _normalized_model_name(model_name: str) -> str:\n name = model_name.strip().lower()\n for prefix in (\"litellm/\", \"any-llm/\"):\n if name.startswith(prefix):\n name = name[len(prefix) :]\n break\n return name\n\n\ndef _split_model_provider(model_name: str) -> tuple[str | None, str]:\n if \"/\" not in model_name:\n return None, model_name\n provider_name, bare_model_name = model_name.rsplit(\"/\", 1)\n return provider_name, bare_model_name\n\n\ndef _matches_frontier_family(\n provider_name: str | None,\n model_name: str,\n provider_markers: tuple[str, ...],\n model_prefixes: tuple[str, ...],\n) -> bool:\n if not _matches_model_prefix(model_name, model_prefixes):\n return False\n if provider_name is None:\n return True\n return _contains_provider_marker(\n provider_name, provider_markers, split_compound_names=True\n ) or _contains_provider_marker(model_name, provider_markers)\n\n\ndef _matches_model_prefix(model_name: str, model_prefixes: tuple[str, ...]) -> bool:\n return any(\n candidate.startswith(prefix)\n for candidate in _model_name_candidates(model_name)\n for prefix in model_prefixes\n )\n\n\ndef _model_name_candidates(model_name: str) -> tuple[str, ...]:\n if \".\" not in model_name:\n return (model_name,)\n suffixes = tuple(\n model_name.split(\".\", index)[-1] for index in range(1, model_name.count(\".\") + 1)\n )\n return (model_name, *suffixes)\n\n\ndef _contains_provider_marker(\n value: str, provider_markers: tuple[str, ...], *, split_compound_names: bool = False\n) -> bool:\n parts = set(value.replace(\".\", \"/\").split(\"/\"))\n if split_compound_names:\n for separator in (\"_\", \"-\"):\n parts.update(piece for part in tuple(parts) for piece in part.split(separator))\n return any(marker in parts for marker in provider_markers)\n\n\ndef is_known_openai_bare_model(model_name: str) -> bool:\n import litellm\n\n name = model_name.strip().lower()\n if not name or \"/\" in name:\n return False\n entry = litellm.model_cost.get(name)\n return bool(entry and entry.get(\"litellm_provider\") == \"openai\")\n"}, "1b7ecdf30a0be97010c251d8d48da182226b5715": {"t": 1785764933.321273, "n": 14904, "h": "5f2600dc1a7f4774", "c": "\"\"\"SDK model configuration helpers.\"\"\"\n\nfrom __future__ import annotations\n\nimport contextlib\nimport inspect\nimport os\nfrom typing import TYPE_CHECKING, Any\n\nfrom agents import (\n set_default_openai_api,\n set_default_openai_key,\n set_tracing_disabled,\n)\nfrom agents.model_settings import ModelSettings\nfrom agents.models.multi_provider import MultiProvider\nfrom agents.models.openai_responses import OpenAIResponsesModel\nfrom agents.retry import (\n ModelRetryBackoffSettings,\n ModelRetrySettings,\n RetryPolicyContext,\n retry_policies,\n)\nfrom openai.types.shared import Reasoning\n\nfrom strix.config import codex\nfrom strix.config.loader import load_settings\n\n\nif TYPE_CHECKING:\n from collections.abc import AsyncIterator\n\n from agents.models.interface import Model, ModelProvider\n from openai import AsyncOpenAI\n\n from strix.config.settings import ReasoningEffort, Settings\n\n\ndef request_timeout_extra_args(timeout_s: float | None) -> dict[str, float] | None:\n \"\"\"Per-request model timeout; a plain float so ``ModelSettings.to_json_dict()`` stays serializable.\"\"\" # noqa: E501\n if not timeout_s or timeout_s <= 0:\n return None\n return {\"timeout\": timeout_s}\n\n\ndef _retry_statusless_provider_errors(context: RetryPolicyContext) -> bool:\n \"\"\"Retry statusless provider errors (e.g. mid-stream quota/billing), but not aborts.\"\"\"\n normalized = context.normalized\n if normalized.is_abort:\n return False\n if codex.is_content_guardrail_error(context.error):\n return False\n return normalized.status_code is None\n\n\nclass _CodexResponsesModel(OpenAIResponsesModel):\n \"\"\"Responses model for the ChatGPT subscription backend (always streamed, stateless).\"\"\"\n\n def __init__(\n self,\n model: str,\n openai_client: AsyncOpenAI,\n *,\n reasoning_effort: ReasoningEffort | None = None,\n ) -> None:\n super().__init__(model, openai_client)\n self._reasoning_effort = reasoning_effort\n\n def _codex_settings(self, model_settings: ModelSettings) -> ModelSettings:\n overrides = ModelSettings(store=False, response_include=[\"reasoning.encrypted_content\"])\n effort = self._reasoning_effort\n if effort and effort != \"none\":\n # Clamp to efforts the backend accepts.\n if effort == \"minimal\":\n effort = \"low\"\n elif effort == \"xhigh\":\n effort = \"high\"\n overrides = overrides.resolve(ModelSettings(reasoning=Reasoning(effort=effort)))\n return model_settings.resolve(overrides)\n\n async def _fetch_response(self, *args: Any, stream: bool = False, **kwargs: Any) -> Any:\n if len(args) >= 3: # model_settings is positional arg 2\n args = (*args[:2], self._codex_settings(args[2]), *args[3:])\n try:\n events = await super()._fetch_response(*args, stream=True, **kwargs) # type: ignore[call-overload]\n except Exception as exc:\n guardrail = self._as_guardrail(exc)\n if guardrail is not None:\n raise guardrail from exc\n raise\n guarded = self._guarded(events)\n if stream:\n return guarded\n final_response = None\n async for event in guarded:\n if getattr(event, \"type\", None) == \"response.completed\":\n final_response = event.response\n if final_response is None:\n msg = \"ChatGPT backend stream ended without a completed response\"\n raise RuntimeError(msg)\n return final_response\n\n def _as_guardrail(self, exc: BaseException) -> codex.CodexContentGuardrailError | None:\n if isinstance(exc, codex.CodexContentGuardrailError):\n return exc\n if codex.is_content_guardrail_error(exc):\n return codex.CodexContentGuardrailError(self.model, exc)\n return None\n\n async def _guarded(self, events: Any) -> AsyncIterator[Any]:\n \"\"\"Convert mid-stream guardrail rejections and close the stream on exit.\"\"\"\n try:\n async for event in events:\n yield event\n except Exception as exc:\n guardrail = self._as_guardrail(exc)\n if guardrail is not None:\n raise guardrail from exc\n raise\n finally:\n await self._aclose(events)\n\n @staticmethod\n async def _aclose(events: Any) -> None:\n aclose = getattr(events, \"aclose\", None)\n if callable(aclose):\n with contextlib.suppress(Exception):\n await aclose()\n return\n close = getattr(events, \"close\", None)\n if callable(close):\n with contextlib.suppress(Exception):\n result = close()\n if inspect.isawaitable(result):\n await result\n\n\nclass StrixProvider(MultiProvider):\n \"\"\"Route any non-OpenAI prefix through LiteLLM with the prefix preserved,\n so users type ``deepseek/deepseek-chat`` rather than\n ``litellm/deepseek/deepseek-chat``.\n \"\"\"\n\n def _resolve_prefixed_model(\n self,\n *,\n original_model_name: str,\n prefix: str,\n stripped_model_name: str | None,\n ) -> tuple[ModelProvider, str | None]:\n if prefix in {\"openai\", \"litellm\", \"any-llm\"}:\n return super()._resolve_prefixed_model(\n original_model_name=original_model_name,\n prefix=prefix,\n stripped_model_name=stripped_model_name,\n )\n if prefix == \"ollama\" and stripped_model_name:\n return self._get_fallback_provider(\"litellm\"), f\"ollama_chat/{stripped_model_name}\"\n return self._get_fallback_provider(\"litellm\"), original_model_name\n\n def get_model(self, model_name: str | None) -> Model:\n slug = codex.subscription_model(model_name)\n if slug:\n return _CodexResponsesModel(\n slug,\n codex.get_subscription_client(),\n reasoning_effort=load_settings().llm.reasoning_effort,\n )\n return super().get_model(model_name)\n\n\nDEFAULT_MODEL_RETRY = ModelRetrySettings(\n max_retries=5,\n backoff=ModelRetryBackoffSettings(\n initial_delay=2.0,\n max_delay=90.0,\n multiplier=2.0,\n jitter=False,\n ),\n policy=retry_policies.any(\n retry_policies.provider_suggested(),\n retry_policies.network_error(),\n retry_policies.http_status((429, 500, 502, 503, 504)),\n _retry_statusless_provider_errors,\n ),\n)\n\nRECOMMENDED_MODEL_NAMES = (\n \"openai/gpt-5.6-sol\",\n \"openai/gpt-5.6-terra\",\n \"openai/gpt-5.6-luna\",\n \"openai/gpt-5.6\",\n \"openai/gpt-5.5-pro\",\n \"openai/gpt-5.5\",\n \"openai/gpt-5.4\",\n \"openai/gpt-5.3-codex\",\n \"anthropic/claude-fable-5\",\n \"anthropic/claude-opus-5\",\n \"anthropic/claude-opus-4-8\",\n \"anthropic/claude-sonnet-5\",\n \"anthropic/claude-sonnet-4-6\",\n \"vertex_ai/gemini-3.1-pro-preview\",\n \"gemini/gemini-3.1-pro-preview\",\n \"gemini/gemini-3.6-flash\",\n \"deepseek/deepseek-v4-pro\",\n \"deepseek/deepseek-v4-flash\",\n \"dashscope/qwen3.8-max\",\n \"dashscope/qwen3.7-max-2026-06-08\",\n \"moonshot/kimi-k3\",\n \"moonshot/kimi-k2.7-code\",\n)\n\n_RECOMMENDED_MODEL_NAME_SET = frozenset(name.lower() for name in RECOMMENDED_MODEL_NAMES)\n\nFRONTIER_MODEL_FAMILIES = (\n ((\"azure\", \"azure_ai\", \"bedrock_mantle\", \"chatgpt\", \"openai\"), (\"gpt-5\",)),\n (\n (\"anthropic\", \"azure_ai\", \"bedrock\", \"claude\", \"databricks\", \"snowflake\", \"vertex_ai\"),\n (\"claude-fable-5\", \"claude-opus-5\", \"claude-opus-4\", \"claude-sonnet-5\", \"claude-sonnet-4\"),\n ),\n ((\"google\", \"gemini\", \"vertex_ai\"), (\"gemini-3\",)),\n ((\"deepseek\",), (\"deepseek-v4\", \"deepseek-r1\", \"deepseek-reasoner\")),\n ((\"alibaba\", \"dashscope\", \"qwen\"), (\"qwen3.8\", \"qwen3.7\", \"qwen3-max\")),\n ((\"moonshot\", \"moonshotai\", \"kimi\"), (\"kimi-k3\", \"kimi-k2.7\", \"kimi-k2.6\")),\n)\n\n\ndef configure_sdk_model_defaults(settings: Settings) -> None:\n \"\"\"Apply Strix config to SDK-native defaults.\"\"\"\n llm = settings.llm\n set_tracing_disabled(True)\n if codex.subscription_model(llm.model):\n return\n _configure_litellm_compatibility()\n _configure_openrouter_attribution(llm.model)\n if llm.api_key:\n set_default_openai_key(llm.api_key, use_for_tracing=False)\n _configure_litellm_default(\"api_key\", llm.api_key)\n _mirror_api_key_to_provider_env(llm.model, llm.api_key)\n if llm.api_base:\n os.environ[\"OPENAI_BASE_URL\"] = llm.api_base\n _configure_litellm_default(\"api_base\", llm.api_base)\n set_default_openai_api(\"chat_completions\")\n else:\n set_default_openai_api(\"responses\")\n\n\ndef _mirror_api_key_to_provider_env(model_name: str | None, api_key: str) -> None:\n if not model_name:\n return\n import litellm\n\n name = model_name.strip()\n for prefix in (\"litellm/\", \"any-llm/\"):\n if name.lower().startswith(prefix):\n name = name[len(prefix) :]\n break\n try:\n report = litellm.validate_environment(model=name.lower())\n except Exception: # noqa: BLE001\n return\n for env_key in report.get(\"missing_keys\") or []:\n if env_key.endswith(\"_API_KEY\"):\n os.environ.setdefault(env_key, api_key)\n\n\ndef _configure_litellm_compatibility() -> None:\n \"\"\"Apply LiteLLM compatibility, privacy, and callback settings.\"\"\"\n import litellm\n\n litellm.drop_params = True\n litellm.modify_params = True\n litellm.turn_off_message_logging = True\n # Strix uses LiteLLM's success callback to capture provider-reported cost.\n # Disabling streaming logging also disables that callback for streamed calls.\n litellm.disable_streaming_logging = False\n litellm.suppress_debug_info = True\n\n _register_litellm_cost_callback()\n\n\n_OPENROUTER_ATTRIBUTION_HEADERS = {\n \"HTTP-Referer\": \"https://strix.ai\",\n \"X-Title\": \"Strix\",\n \"X-OpenRouter-Categories\": \"cli-agent\",\n}\n\n\ndef _configure_openrouter_attribution(model_name: str | None) -> None:\n import litellm\n\n current: object = litellm.headers\n existing: dict[str, str] = current if isinstance(current, dict) else {}\n if not model_name or \"openrouter/\" not in model_name.strip().lower():\n if any(key in existing for key in _OPENROUTER_ATTRIBUTION_HEADERS):\n remaining = {\n k: v for k, v in existing.items() if k not in _OPENROUTER_ATTRIBUTION_HEADERS\n }\n litellm.headers = remaining or None # type: ignore[assignment]\n return\n\n litellm.headers = {**existing, **_OPENROUTER_ATTRIBUTION_HEADERS} # type: ignore[assignment]\n\n\ndef _register_litellm_cost_callback() -> None:\n import litellm\n\n from strix.report.state import litellm_cost_callback\n\n for bucket_name in (\"success_callback\", \"_async_success_callback\"):\n bucket = getattr(litellm, bucket_name, None)\n if not isinstance(bucket, list):\n continue\n if litellm_cost_callback in bucket:\n continue\n bucket.append(litellm_cost_callback)\n\n\ndef _configure_litellm_default(name: str, value: str) -> None:\n \"\"\"Set LiteLLM's module-level defaults without adding a provider wrapper.\"\"\"\n import litellm\n\n setattr(litellm, name, value)\n\n\ndef uses_chat_completions_tool_schema(model_name: str, settings: Settings) -> bool:\n \"\"\"Return whether the resolved SDK route can only receive JSON function tools.\"\"\"\n if codex.subscription_model(model_name):\n return False\n model = model_name.strip().lower()\n if \"/\" in model and not model.startswith(\"openai/\"):\n return True\n if settings.llm.api_base:\n return True\n return not model_supports_reasoning(model_name)\n\n\ndef model_supports_reasoning(model_name: str) -> bool:\n import litellm\n\n name = model_name.strip().lower()\n for prefix in (\"litellm/\", \"any-llm/\", \"openai/\"):\n if name.startswith(prefix):\n name = name[len(prefix) :]\n break\n entry = litellm.model_cost.get(name)\n if entry is None and \"/\" in name:\n entry = litellm.model_cost.get(name.rsplit(\"/\", 1)[1])\n return bool(entry and entry.get(\"supports_reasoning\"))\n\n\ndef is_recommended_or_frontier_model(model_name: str) -> bool:\n \"\"\"Return whether a model is recommended or in a frontier model family.\"\"\"\n name = _normalized_model_name(model_name)\n if not name:\n return False\n if name in _RECOMMENDED_MODEL_NAME_SET:\n return True\n provider_name, bare_model_name = _split_model_provider(name)\n return any(\n _matches_frontier_family(provider_name, bare_model_name, provider_markers, prefixes)\n for provider_markers, prefixes in FRONTIER_MODEL_FAMILIES\n )\n\n\ndef _normalized_model_name(model_name: str) -> str:\n name = model_name.strip().lower()\n for prefix in (\"litellm/\", \"any-llm/\"):\n if name.startswith(prefix):\n name = name[len(prefix) :]\n break\n return name\n\n\ndef _split_model_provider(model_name: str) -> tuple[str | None, str]:\n if \"/\" not in model_name:\n return None, model_name\n provider_name, bare_model_name = model_name.rsplit(\"/\", 1)\n return provider_name, bare_model_name\n\n\ndef _matches_frontier_family(\n provider_name: str | None,\n model_name: str,\n provider_markers: tuple[str, ...],\n model_prefixes: tuple[str, ...],\n) -> bool:\n if not _matches_model_prefix(model_name, model_prefixes):\n return False\n if provider_name is None:\n return True\n return _contains_provider_marker(\n provider_name, provider_markers, split_compound_names=True\n ) or _contains_provider_marker(model_name, provider_markers)\n\n\ndef _matches_model_prefix(model_name: str, model_prefixes: tuple[str, ...]) -> bool:\n return any(\n candidate.startswith(prefix)\n for candidate in _model_name_candidates(model_name)\n for prefix in model_prefixes\n )\n\n\ndef _model_name_candidates(model_name: str) -> tuple[str, ...]:\n if \".\" not in model_name:\n return (model_name,)\n suffixes = tuple(\n model_name.split(\".\", index)[-1] for index in range(1, model_name.count(\".\") + 1)\n )\n return (model_name, *suffixes)\n\n\ndef _contains_provider_marker(\n value: str, provider_markers: tuple[str, ...], *, split_compound_names: bool = False\n) -> bool:\n parts = set(value.replace(\".\", \"/\").split(\"/\"))\n if split_compound_names:\n for separator in (\"_\", \"-\"):\n parts.update(piece for part in tuple(parts) for piece in part.split(separator))\n return any(marker in parts for marker in provider_markers)\n\n\ndef is_known_openai_bare_model(model_name: str) -> bool:\n import litellm\n\n name = model_name.strip().lower()\n if not name or \"/\" in name:\n return False\n entry = litellm.model_cost.get(name)\n return bool(entry and entry.get(\"litellm_provider\") == \"openai\")\n"}}, "omniroute/tests/unit/modelsDevSync.test.ts": {"6eea4894299d5371c00c11f1f6dec2f7c0076253": {"t": 1786068275.652702, "n": 14938, "h": "abfef5578fcecee2", "c": "/**\n * Unit tests for modelsDevSync.ts\n *\n * Tests: fetch, transform (pricing + capabilities), provider mapping,\n * DB save/retrieve, and resolution order.\n */\n\nimport { describe, it, before, after } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport {\n transformModelsDevToPricing,\n transformModelsDevToCapabilities,\n mapProviderId,\n fetchModelsDev,\n} from \"../../src/lib/modelsDevSync.ts\";\n\n// ─── Mock data ───────────────────────────────────────────\n\nconst MOCK_MODELS_DEV_DATA = {\n openai: {\n id: \"openai\",\n name: \"OpenAI\",\n npm: \"@ai-sdk/openai\",\n env: [\"OPENAI_API_KEY\"],\n doc: \"https://platform.openai.com/docs/models\",\n models: {\n \"gpt-4o\": {\n id: \"gpt-4o\",\n name: \"GPT-4o\",\n family: \"gpt-4\",\n attachment: true,\n reasoning: false,\n tool_call: true,\n structured_output: true,\n temperature: true,\n knowledge: \"2024-10\",\n release_date: \"2024-05-13\",\n last_updated: \"2024-10-01\",\n open_weights: false,\n cost: {\n input: 2.5,\n output: 10.0,\n cache_read: 1.25,\n cache_write: 2.5,\n },\n limit: {\n context: 128000,\n input: 128000,\n output: 16384,\n },\n modalities: {\n input: [\"text\", \"image\"],\n output: [\"text\"],\n },\n },\n \"o3-mini\": {\n id: \"o3-mini\",\n name: \"o3-mini\",\n family: \"o3\",\n attachment: false,\n reasoning: true,\n tool_call: true,\n structured_output: true,\n temperature: false,\n release_date: \"2025-01-31\",\n last_updated: \"2025-01-31\",\n open_weights: false,\n cost: {\n input: 1.1,\n output: 4.4,\n reasoning: 4.4,\n },\n limit: {\n context: 200000,\n output: 100000,\n },\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n },\n },\n },\n anthropic: {\n id: \"anthropic\",\n name: \"Anthropic\",\n npm: \"@ai-sdk/anthropic\",\n env: [\"ANTHROPIC_API_KEY\"],\n doc: \"https://docs.anthropic.com/en/docs/about-claud/models\",\n models: {\n \"claude-sonnet-4-20250514\": {\n id: \"claude-sonnet-4-20250514\",\n name: \"Claude Sonnet 4\",\n family: \"claude-4\",\n attachment: true,\n reasoning: false,\n tool_call: true,\n structured_output: true,\n temperature: true,\n release_date: \"2025-05-14\",\n last_updated: \"2025-05-14\",\n open_weights: false,\n cost: {\n input: 3.0,\n output: 15.0,\n cache_read: 0.3,\n cache_write: 3.75,\n },\n limit: {\n context: 200000,\n output: 64000,\n },\n modalities: {\n input: [\"text\", \"image\"],\n output: [\"text\"],\n },\n },\n },\n },\n deepseek: {\n id: \"deepseek\",\n name: \"DeepSeek\",\n npm: \"@ai-sdk/openai-compatible\",\n api: \"https://api.deepseek.com/v1\",\n env: [\"DEEPSEEK_API_KEY\"],\n doc: \"https://api-docs.deepseek.com/\",\n models: {\n \"deepseek-chat\": {\n id: \"deepseek-chat\",\n name: \"DeepSeek V3\",\n family: \"deepseek-v3\",\n attachment: false,\n reasoning: false,\n tool_call: true,\n temperature: true,\n release_date: \"2024-12-26\",\n last_updated: \"2025-01-20\",\n open_weights: true,\n cost: {\n input: 0.27,\n output: 1.1,\n cache_read: 0.07,\n },\n limit: {\n context: 64000,\n output: 8192,\n },\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n },\n },\n },\n \"unknown-provider\": {\n id: \"unknown-provider\",\n name: \"Unknown\",\n npm: \"@ai-sdk/openai-compatible\",\n api: \"https://api.unknown.com/v1\",\n env: [\"UNKNOWN_API_KEY\"],\n models: {\n \"some-model\": {\n id: \"some-model\",\n name: \"Some Model\",\n attachment: false,\n reasoning: false,\n tool_call: false,\n release_date: \"2025-01-01\",\n last_updated: \"2025-01-01\",\n open_weights: false,\n cost: {\n input: 1.0,\n output: 2.0,\n },\n limit: {\n context: 32000,\n output: 4096,\n },\n modalities: {\n input: [\"text\"],\n output: [\"text\"],\n },\n },\n },\n },\n};\n\n// ─── Tests ───────────────────────────────────────────────\n\ndescribe(\"modelsDevSync — transformModelsDevToPricing\", () => {\n it(\"transforms pricing data correctly for openai provider\", () => {\n const pricing = transformModelsDevToPricing(MOCK_MODELS_DEV_DATA);\n\n // openai maps to [\"openai\", \"cx\"]\n assert.ok(pricing.openai, \"openai provider should exist\");\n assert.ok(pricing.openai[\"gpt-4o\"], \"gpt-4o pricing should exist\");\n assert.equal(pricing.openai[\"gpt-4o\"].input, 2.5);\n assert.equal(pricing.openai[\"gpt-4o\"].output, 10.0);\n assert.equal(pricing.openai[\"gpt-4o\"].cached, 1.25);\n assert.equal(pricing.openai[\"gpt-4o\"].cache_creation, 2.5);\n\n // cx (Codex alias) should also have the same pricing\n assert.ok(pricing.cx, \"cx provider should exist\");\n assert.ok(pricing.cx[\"gpt-4o\"], \"gpt-4o pricing in cx should exist\");\n assert.equal(pricing.cx[\"gpt-4o\"].input, 2.5);\n });\n\n it(\"maps reasoning cost correctly\", () => {\n const pricing = transformModelsDevToPricing(MOCK_MODELS_DEV_DATA);\n\n assert.ok(pricing.openai[\"o3-mini\"], \"o3-mini pricing should exist\");\n assert.equal(pricing.openai[\"o3-mini\"].input, 1.1);\n assert.equal(pricing.openai[\"o3-mini\"].output, 4.4);\n assert.equal(pricing.openai[\"o3-mini\"].reasoning, 4.4);\n // o3-mini has no cache_read/cache_write\n assert.equal(pricing.openai[\"o3-mini\"].cached, undefined);\n assert.equal(pricing.openai[\"o3-mini\"].cache_creation, undefined);\n });\n\n it(\"maps deepseek to both deepseek and if (Qoder) providers\", () => {\n const pricing = transformModelsDevToPricing(MOCK_MODELS_DEV_DATA);\n\n assert.ok(pricing.deepseek, \"deepseek provider should exist\");\n assert.ok(pricing.if, \"if (Qoder) provider should exist\");\n assert.equal(pricing.deepseek[\"deepseek-chat\"].input, 0.27);\n assert.equal(pricing.deepseek[\"deepseek-chat\"].output, 1.1);\n assert.equal(pricing.deepseek[\"deepseek-chat\"].cached, 0.07);\n // Should be same in if provider\n assert.equal(pricing.if[\"deepseek-chat\"].input, 0.27);\n });\n\n it(\"handles unknown providers by using the models.dev ID as-is\", () => {\n const pricing = transformModelsDevToPricing(MOCK_MODELS_DEV_DATA);\n\n assert.ok(pricing[\"unknown-provider\"], \"unknown-provider should exist\");\n assert.equal(pricing[\"unknown-provider\"][\"some-model\"].input, 1.0);\n assert.equal(pricing[\"unknown-provider\"][\"some-model\"].output, 2.0);\n });\n\n it(\"skips models without cost data\", () => {\n const dataWithNoCost = {\n testprovider: {\n id: \"testprovider\",\n models: {\n \"no-cost-model\": {\n id: \"no-cost-model\",\n name: \"No Cost Model\",\n attachment: false,\n reasoning: false,\n tool_call: false,\n release_date: \"2025-01-01\",\n last_updated: \"2025-01-01\",\n open_weights: false,\n // No cost field\n limit: { context: 4096, output: 2048 },\n modalities: { input: [\"text\"], output: [\"text\"] },\n },\n },\n },\n };\n const pricing = transformModelsDevToPricing(dataWithNoCost);\n assert.equal(pricing.testprovider, undefined, \"provider without cost should not exist\");\n });\n\n it(\"counts pricing entries correctly\", () => {\n const pricing = transformModelsDevToPricing(MOCK_MODELS_DEV_DATA);\n const totalModels = Object.values(pricing).reduce(\n (sum, models) => sum + Object.keys(models).length,\n 0\n );\n // openai: 2 models × 2 providers (openai, cx) = 4\n // anthropic: 1 model × 2 providers (anthropic, cc) = 2\n // deepseek: 1 model × 2 providers (deepseek, if) = 2\n // unknown-provider: 1 model × 1 provider = 1\n assert.equal(totalModels, 9);\n });\n});\n\ndescribe(\"modelsDevSync — transformModelsDevToCapabilities\", () => {\n it(\"transforms capability data correctly\", () => {\n const caps = transformModelsDevToCapabilities(MOCK_MODELS_DEV_DATA);\n\n assert.ok(caps.openai, \"openai capabilities should exist\");\n assert.ok(caps.openai[\"gpt-4o\"], \"gpt-4o capabilities should exist\");\n\n const gpt4o = caps.openai[\"gpt-4o\"];\n assert.equal(gpt4o.tool_call, true);\n assert.equal(gpt4o.reasoning, false);\n assert.equal(gpt4o.attachment, true);\n assert.equal(gpt4o.structured_output, true);\n assert.equal(gpt4o.temperature, true);\n assert.equal(gpt4o.limit_context, 128000);\n assert.equal(gpt4o.limit_output, 16384);\n assert.equal(gpt4o.status, null); // not set in mock\n assert.equal(gpt4o.family, \"gpt-4\");\n assert.equal(gpt4o.open_weights, false);\n assert.equal(JSON.parse(gpt4o.modalities_input).length, 2);\n assert.equal(JSON.parse(gpt4o.modalities_output).length, 1);\n });\n\n it(\"handles interleaved reasoning field\", () => {\n const dataWithInterleaved = {\n testprovider: {\n id: \"testprovider\",\n models: {\n \"reasoning-model\": {\n id: \"reasoning-model\",\n name: \"Reasoning Model\",\n attachment: false,\n reasoning: true,\n tool_call: true,\n release_date: \"2025-01-01\",\n last_updated: \"2025-01-01\",\n open_weights: true,\n interleaved: { field: \"reasoning_content\" },\n limit: { context: 200000, output: 64000 },\n modalities: { input: [\"text\"], output: [\"text\"] },\n },\n },\n },\n };\n const caps = transformModelsDevToCapabilities(dataWithInterleaved);\n assert.equal(caps.testprovider[\"reasoning-model\"].interleaved_field, \"reasoning_content\");\n });\n\n it(\"handles interleaved as boolean true\", () => {\n const dataWithBoolInterleaved = {\n testprovider: {\n id: \"testprovider\",\n models: {\n \"bool-model\": {\n id: \"bool-model\",\n name: \"Bool Model\",\n attachment: false,\n reasoning: true,\n tool_call: true,\n release_date: \"2025-01-01\",\n last_updated: \"2025-01-01\",\n open_weights: false,\n interleaved: true,\n limit: { context: 100000, output: 32000 },\n modalities: { input: [\"text\"], output: [\"text\"] },\n },\n },\n },\n };\n const caps = transformModelsDevToCapabilities(dataWithBoolInterleaved);\n assert.equal(caps.testprovider[\"bool-model\"].interleaved_field, \"reasoning_content\");\n });\n\n it(\"handles null/missing optional fields\", () => {\n const dataWithMinimal = {\n minimal: {\n id: \"minimal\",\n models: {\n \"minimal-model\": {\n id: \"minimal-model\",\n name: \"Minimal\",\n attachment: false,\n reasoning: false,\n tool_call: false,\n release_date: \"2025-01-01\",\n last_updated: \"2025-01-01\",\n open_weights: false,\n // No cost, no interleaved, no status, no family\n limit: { context: 4096, output: 2048 },\n modalities: { input: [\"text\"], output: [\"text\"] },\n },\n },\n },\n };\n const caps = transformModelsDevToCapabilities(dataWithMinimal);\n const m = caps.minimal[\"minimal-model\"];\n assert.equal(m.tool_call, false);\n assert.equal(m.reasoning, false);\n assert.equal(m.attachment, false);\n assert.equal(m.structured_output, null);\n assert.equal(m.temperature, null);\n assert.equal(m.knowledge_cutoff, null);\n assert.equal(m.status, null);\n assert.equal(m.family, null);\n assert.equal(m.interleaved_field, null);\n assert.equal(m.limit_context, 4096);\n });\n});\n\ndescribe(\"modelsDevSync — mapProviderId\", () => {\n it(\"maps openai to [openai, cx]\", () => {\n assert.deepEqual(mapProviderId(\"openai\"), [\"openai\", \"cx\"]);\n });\n\n it(\"maps anthropic to [anthropic, cc]\", () => {\n assert.deepEqual(mapProviderId(\"anthropic\"), [\"anthropic\", \"cc\"]);\n });\n\n it(\"maps google to [gemini]\", () => {\n assert.deepEqual(mapProviderId(\"google\"), [\"gemini\"]);\n });\n\n it(\"maps deepseek to [deepseek, if]\", () => {\n assert.deepEqual(mapProviderId(\"deepseek\"), [\"deepseek\", \"if\"]);\n });\n\n it(\"falls back to original ID for unmapped providers\", () => {\n assert.deepEqual(mapProviderId(\"some-new-provider\"), [\"some-new-provider\"]);\n });\n\n it(\"maps bedrock to [kiro, kr]\", () => {\n assert.deepEqual(mapProviderId(\"bedrock\"), [\"kiro\", \"kr\"]);\n });\n\n it(\"maps moonshot to the canonical provider plus Kimi aliases\", () => {\n assert.deepEqual(mapProviderId(\"moonshot\"), [\"moonshot\", \"kimi\", \"kimi-coding\", \"kmc\", \"kmca\"]);\n });\n\n it(\"maps current models.dev provider IDs used by OmniRoute-compatible providers\", () => {\n assert.deepEqual(mapProviderId(\"github-copilot\"), [\"github\", \"gh\"]);\n assert.deepEqual(mapProviderId(\"kilo\"), [\"kilocode\", \"kc\", \"kilo-gateway\"]);\n assert.deepEqual(mapProviderId(\"kimi-for-coding\"), [\n \"kimi-coding\",\n \"kmc\",\n \"kimi-coding-apikey\",\n \"kmca\",\n ]);\n assert.deepEqual(mapProviderId(\"fireworks-ai\"), [\"fireworks\"]);\n assert.deepEqual(mapProviderId(\"togetherai\"), [\"together\", \"openrouter\"]);\n });\n});\n\ndescribe(\"modelsDevSync — fetchModelsDev (live API)\", () => {\n it(\"fetches data from models.dev API\", async () => {\n const data = await fetchModelsDev();\n assert.ok(typeof data === \"object\", \"data should be an object\");\n\n const providerCount = Object.keys(data).length;\n assert.ok(providerCount >= 100, `should have 100+ providers, got ${providerCount}`);\n\n let modelCount = 0;\n for (const provider of Object.values(data)) {\n const p = provider;\n if (p.models) {\n modelCount += Object.keys(p.models).length;\n }\n }\n assert.ok(modelCount >= 4000, `should have 4000+ models, got ${modelCount}`);\n });\n\n it(\"returns cached data on second call\", async () => {\n const data1 = await fetchModelsDev();\n const data2 = await fetchModelsDev();\n assert.strictEqual(data1, data2, \"should return same cached reference\");\n });\n\n it(\"has openai provider with gpt-4o model\", async () => {\n const data = await fetchModelsDev();\n assert.ok(data.openai, \"openai provider should exist\");\n assert.ok(data.openai.models[\"gpt-4o\"], \"gpt-4o model should exist\");\n });\n\n it(\"has anthropic provider with claude models\", async () => {\n const data = await fetchModelsDev();\n assert.ok(data.anthropic, \"anthropic provider should exist\");\n const claudeModels = Object.keys(data.anthropic.models).filter((m) => m.includes(\"claude\"));\n assert.ok(claudeModels.length > 0, \"should have claude models\");\n });\n});\n"}}, "omniroute/docs/i18n/zh-TW/docs/guides/USER_GUIDE.md": {"6eea4894299d5371c00c11f1f6dec2f7c0076253": {"t": 1786068459.1343236, "n": 37569, "h": "1e6b88ff7112cb45", "c": "# User Guide (中文 (簡體))\n\n🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇧🇩 [bn](../../bn/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇮🇷 [fa](../../fa/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇮🇳 [gu](../../gu/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇮🇳 [hi](../../hi/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇮🇳 [mr](../../mr/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇰🇪 [sw](../../sw/docs/USER_GUIDE.md) · 🇮🇳 [ta](../../ta/docs/USER_GUIDE.md) · 🇮🇳 [te](../../te/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇹🇷 [tr](../../tr/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇵🇰 [ur](../../ur/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md)\n\n---\n\nComplete guide for configuring providers, creating combos, integrating CLI tools, and deploying OmniRoute.\n\n---\n\n## Table of Contents\n\n- [Pricing at a Glance](#-pricing-at-a-glance)\n- [Use Cases](#-use-cases)\n- [Provider Setup](#-provider-setup)\n- [CLI Integration](#-cli-integration)\n- [Deployment](#-deployment)\n- [Available Models](#-available-models)\n- [Advanced Features](#-advanced-features)\n\n---\n\n## 💰 Pricing at a Glance\n\n| Tier | Provider | Cost | Quota Reset | Best For |\n| ------------------- | ----------------- | ----------- | ---------------- | -------------------- |\n| **💳 SUBSCRIPTION** | Claude Code (Pro) | $20/mo | 5h + weekly | Already subscribed |\n| | Codex (Plus/Pro) | $20-200/mo | 5h + weekly | OpenAI users |\n| | GitHub Copilot | $10-19/mo | Monthly | GitHub users |\n| **🔑 API KEY** | DeepSeek | Pay per use | None | Cheap reasoning |\n| | Groq | Pay per use | None | Ultra-fast inference |\n| | xAI (Grok) | Pay per use | None | Grok 4 reasoning |\n| | Mistral | Pay per use | None | EU-hosted models |\n| | Perplexity | Pay per use | None | Search-augmented |\n| | Together AI | Pay per use | None | Open-source models |\n| | Fireworks AI | Pay per use | None | Fast FLUX images |\n| | Cerebras | Pay per use | None | Wafer-scale speed |\n| | Cohere | Pay per use | None | Command R+ RAG |\n| | NVIDIA NIM | Pay per use | None | Enterprise models |\n| **💰 CHEAP** | GLM-4.7 | $0.6/1M | Daily 10AM | Budget backup |\n| | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option |\n| | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost |\n| **🆓 FREE** | Qoder | $0 | Unlimited | 8 models free |\n| | Qwen | $0 | Unlimited | 3 models free |\n| | Kiro | $0 | Unlimited | Claude free |\n\n\n---\n\n## 🎯 Use Cases\n\n### Case 1: \"I have Claude Pro subscription\"\n\n**Problem:** Quota expires unused, rate limits during heavy coding\n\n```\nCombo: \"maximize-claude\"\n 1. cc/claude-opus-4-7 (use subscription fully)\n 2. glm/glm-4.7 (cheap backup when quota out)\n 3. if/kimi-k2-thinking (free emergency fallback)\n\nMonthly cost: $20 (subscription) + ~$5 (backup) = $25 total\nvs. $20 + hitting limits = frustration\n```\n\n### Case 2: \"I want zero cost\"\n\n**Problem:** Can't afford subscriptions, need reliable AI coding\n\n```\nCombo: \"free-forever\"\n 1. if/kimi-k2-thinking (unlimited free)\n 2. qw/qwen3-coder-plus (unlimited free)\n\nMonthly cost: $0\nQuality: Production-ready models\n```\n\n### Case 3: \"I need 24/7 coding, no interruptions\"\n\n**Problem:** Deadlines, can't afford downtime\n\n```\nCombo: \"always-on\"\n 1. cc/claude-opus-4-7 (best quality)\n 2. cx/gpt-5.2-codex (second subscription)\n 3. glm/glm-4.7 (cheap, resets daily)\n 4. minimax/MiniMax-M2.1 (cheapest, 5h reset)\n 5. if/kimi-k2-thinking (free unlimited)\n\nResult: 5 layers of fallback = zero downtime\nMonthly cost: $20-200 (subscriptions) + $10-20 (backup)\n```\n\n### Case 4: \"I want FREE AI in OpenClaw\"\n\n**Problem:** Need AI assistant in messaging apps, completely free\n\n```\nCombo: \"openclaw-free\"\n 1. if/glm-4.7 (unlimited free)\n 2. if/minimax-m2.1 (unlimited free)\n 3. if/kimi-k2-thinking (unlimited free)\n\nMonthly cost: $0\nAccess via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...\n```\n\n---\n\n## 📖 Provider Setup\n\n### 🔐 Subscription Providers\n\n#### Claude Code (Pro/Max)\n\n```bash\nDashboard → Providers → Connect Claude Code\n→ OAuth login → Auto token refresh\n→ 5-hour + weekly quota tracking\n\nModels:\n cc/claude-opus-4-7\n cc/claude-sonnet-4-5-20250929\n cc/claude-haiku-4-5-20251001\n```\n\n**Pro Tip:** Use Opus for complex tasks, Sonnet for speed. OmniRoute tracks quota per model!\n\n#### OpenAI Codex (Plus/Pro)\n\n```bash\nDashboard → Providers → Connect Codex\n→ OAuth login (port 1455)\n→ 5-hour + weekly reset\n\nModels:\n cx/gpt-5.2-codex\n cx/gpt-5.1-codex-max\n```\n\n\n\n#### GitHub Copilot\n\n```bash\nDashboard → Providers → Connect GitHub\n→ OAuth via GitHub\n→ Monthly reset (1st of month)\n\nModels:\n gh/gpt-5\n gh/claude-4.5-sonnet\n gh/gemini-3.1-pro-preview\n```\n\n### 💰 Cheap Providers\n\n#### GLM-4.7 (Daily reset, $0.6/1M)\n\n1. Sign up: [Zhipu AI](https://open.bigmodel.cn/)\n2. Get API key from Coding Plan\n3. Dashboard → Add API Key: Provider: `glm`, API Key: `your-key`\n\n**Use:** `glm/glm-4.7` — **Pro Tip:** Coding Plan offers 3× quota at 1/7 cost! Reset daily 10:00 AM.\n\n#### MiniMax M2.1 (5h reset, $0.20/1M)\n\n1. Sign up: [MiniMax](https://www.minimax.io/)\n2. Get API key → Dashboard → Add API Key\n\n**Use:** `minimax/MiniMax-M2.1` — **Pro Tip:** Cheapest option for long context (1M tokens)!\n\n#### Kimi K2 ($9/month flat)\n\n1. Subscribe: [Moonshot AI](https://platform.moonshot.ai/)\n2. Get API key → Dashboard → Add API Key\n\n**Use:** `kimi/kimi-latest` — **Pro Tip:** Fixed $9/month for 10M tokens = $0.90/1M effective cost!\n\n### 🆓 FREE Providers\n\n#### Qoder (8 FREE models)\n\n```bash\nDashboard → Connect Qoder → OAuth login → Unlimited usage\n\nModels: if/kimi-k2-thinking, if/qwen3-coder-plus, if/glm-4.7, if/minimax-m2, if/deepseek-r1\n```\n\n#### Qwen (3 FREE models)\n\n```bash\nDashboard → Connect Qwen → Device code auth → Unlimited usage\n\nModels: qw/qwen3-coder-plus, qw/qwen3-coder-flash\n```\n\n#### Kiro (Claude FREE)\n\n```bash\nDashboard → Connect Kiro → AWS Builder ID or Google/GitHub → Unlimited\n\nModels: kr/claude-sonnet-4.5, kr/claude-haiku-4.5\n```\n\n---\n\n## 🎨 Combos\n\nYou can reorder combo cards directly in **Dashboard → Combos** by dragging the handle on each card. The order is stored in SQLite and restored on reload.\n\n### Example 1: Maximize Subscription → Cheap Backup\n\n```\nDashboard → Combos → Create New\n\nName: premium-coding\nModels:\n 1. cc/claude-opus-4-7 (Subscription primary)\n 2. glm/glm-4.7 (Cheap backup, $0.6/1M)\n 3. minimax/MiniMax-M2.1 (Cheapest fallback, $0.20/1M)\n\nUse in CLI: premium-coding\n```\n\n### Example 2: Free-Only (Zero Cost)\n\n```\nName: free-combo\nModels:\n 1. if/kimi-k2-thinking (unlimited)\n 2. qw/qwen3-coder-plus (unlimited)\n\nCost: $0 forever!\n```\n\n---\n\n## 🔧 CLI Integration\n\n### Cursor IDE\n\n```\nSettings → Models → Advanced:\n OpenAI API Base URL: http://localhost:20128/v1\n OpenAI API Key: [from omniroute dashboard]\n Model: cc/claude-opus-4-7\n```\n\n### Claude Code\n\nEdit `~/.claude/config.json`:\n\n```json\n{\n \"anthropic_api_base\": \"http://localhost:20128/v1\",\n \"anthropic_api_key\": \"your-omniroute-api-key\"\n}\n```\n\n### Codex CLI\n\n```bash\nexport OPENAI_BASE_URL=\"http://localhost:20128\"\nexport OPENAI_API_KEY=\"your-omniroute-api-key\"\ncodex \"your prompt\"\n```\n\n### OpenClaw\n\nEdit `~/.openclaw/openclaw.json`:\n\n```json\n{\n \"agents\": {\n \"defaults\": {\n \"model\": { \"primary\": \"omniroute/if/glm-4.7\" }\n }\n },\n \"models\": {\n \"providers\": {\n \"omniroute\": {\n \"baseUrl\": \"http://localhost:20128/v1\",\n \"apiKey\": \"your-omniroute-api-key\",\n \"api\": \"openai-completions\",\n \"models\": [{ \"id\": \"if/glm-4.7\", \"name\": \"glm-4.7\" }]\n }\n }\n }\n}\n```\n\n**Or use Dashboard:** CLI Tools → OpenClaw → Auto-config\n\n### Cline / Continue / RooCode\n\n```\nProvider: OpenAI Compatible\nBase URL: http://localhost:20128/v1\nAPI Key: [from dashboard]\nModel: cc/claude-opus-4-7\n```\n\n---\n\n## 部署\n\n### Global npm install (Recommended)\n\n```bash\nnpm install -g omniroute\n\n# Create config directory\nmkdir -p ~/.omniroute\n\n# Create .env file (see .env.example)\ncp .env.example ~/.omniroute/.env\n\n# Start server\nomniroute\n# Or with custom port:\nomniroute --port 3000\n```\n\nThe CLI automatically loads `.env` from `~/.omniroute/.env` or `./.env`.\n\n### Uninstalling\n\nWhen you no longer need OmniRoute, we provide two quick scripts for a clean removal:\n\n| Command | Action |\n| ------------------------ | ----------------------------------------------------------------------------------- |\n| `npm run uninstall` | Removes the system app but **keeps your DB and configurations** in `~/.omniroute`. |\n| `npm run uninstall:full` | Removes the app AND permanently **erases all configurations, keys, and databases**. |\n\n> Note: To run these commands, navigate to the OmniRoute project folder (if you cloned it) and run them. Alternatively, if globally installed, you can simply run `npm uninstall -g omniroute`.\n\n### VPS Deployment\n\n```bash\ngit clone https://github.com/diegosouzapw/OmniRoute.git\ncd OmniRoute && npm install && npm run build\n\nexport JWT_SECRET=\"your-secure-secret-change-this\"\nexport INITIAL_PASSWORD=\"your-password\"\nexport DATA_DIR=\"/var/lib/omniroute\"\nexport PORT=\"20128\"\nexport HOSTNAME=\"0.0.0.0\"\nexport NODE_ENV=\"production\"\nexport NEXT_PUBLIC_BASE_URL=\"http://localhost:20128\"\nexport API_KEY_SECRET=\"endpoint-proxy-api-key-secret\"\n\nnpm run start\n# Or: pm2 start npm --name omniroute -- start\n```\n\n### PM2 Deployment (Low Memory)\n\nFor servers with limited RAM, use the memory limit option:\n\n```bash\n# With 512MB limit (default)\npm2 start npm --name omniroute -- start\n\n# Or with custom memory limit\nOMNIROUTE_MEMORY_MB=512 pm2 start npm --name omniroute -- start\n\n# Or using ecosystem.config.js\npm2 start ecosystem.config.js\n```\n\nCreate `ecosystem.config.js`:\n\n```javascript\nmodule.exports = {\n apps: [\n {\n name: \"omniroute\",\n script: \"npm\",\n args: \"start\",\n env: {\n NODE_ENV: \"production\",\n OMNIROUTE_MEMORY_MB: \"512\",\n JWT_SECRET: \"your-secret\",\n INITIAL_PASSWORD: \"your-password\",\n },\n node_args: \"--max-old-space-size=512\",\n max_memory_restart: \"300M\",\n },\n ],\n};\n```\n\n### Docker\n\n```bash\n# Build image (default = runner-cli with codex/claude/droid preinstalled)\ndocker build -t omniroute:cli .\n\n# Portable mode (recommended)\ndocker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-data:/app/data omniroute:cli\n```\n\nFor host-integrated mode with CLI binaries, see the Docker section in the main docs.\n\n### Void Linux (xbps-src)\n\nVoid Linux users can package and install OmniRoute natively using the `xbps-src` cross-compilation framework. This automates the Node.js standalone build along with the required `better-sqlite3` native bindings.\n\n<details>\n<summary><b>View xbps-src template</b></summary>\n\n```bash\n# Template file for 'omniroute'\npkgname=omniroute\nversion=3.2.4\nrevision=1\nhostmakedepends=\"nodejs python3 make\"\ndepends=\"openssl\"\nshort_desc=\"Universal AI gateway with smart routing for multiple LLM providers\"\nmaintainer=\"zenobit <zenobit@disroot.org>\"\nlicense=\"MIT\"\nhomepage=\"https://github.com/diegosouzapw/OmniRoute\"\ndistfiles=\"https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz\"\nchecksum=009400afee90a9f32599d8fe734145cfd84098140b7287990183dde45ae2245b\nsystem_accounts=\"_omniroute\"\nomniroute_homedir=\"/var/lib/omniroute\"\nexport NODE_ENV=production\nexport npm_config_engine_strict=false\nexport npm_config_loglevel=error\nexport npm_config_fund=false\nexport npm_config_audit=false\n\ndo_build() {\n\t# Determine target CPU arch for node-gyp\n\tlocal _gyp_arch\n\tcase \"$XBPS_TARGET_MACHINE\" in\n\t\taarch64*) _gyp_arch=arm64 ;;\n\t\tarmv7*|armv6*) _gyp_arch=arm ;;\n\t\ti686*) _gyp_arch=ia32 ;;\n\t\t*) _gyp_arch=x64 ;;\n\tesac\n\n\t# 1) Install all deps – skip scripts\n\tNODE_ENV=development npm ci --ignore-scripts\n\n\t# 2) Build the Next.js standalone bundle\n\tnpm run build\n\n\t# 3) Copy static assets into standalone\n\tcp -r .next/static .next/standalone/.next/static\n\t[ -d public ] && cp -r public .next/standalone/public || true\n\n\t# 4) Compile better-sqlite3 native binding\n\tlocal _node_gyp=/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js\n\t(cd node_modules/better-sqlite3 && node \"$_node_gyp\" rebuild --arch=\"$_gyp_arch\")\n\n\t# 5) Place the compiled binding into the standalone bundle\n\tlocal _bs3_release=.next/standalone/node_modules/better-sqlite3/build/Release\n\tmkdir -p \"$_bs3_release\"\n\tcp node_modules/better-sqlite3/build/Release/better_sqlite3.node \"$_bs3_release/\"\n\n\t# 6) Remove arch-specific sharp bundles\n\trm -rf .next/standalone/node_modules/@img\n\n\t# 7) Copy pino runtime deps omitted by Next.js static analysis:\n\tfor _mod in pino-abstract-transport split2 process-warning; do\n\t\tcp -r \"node_modules/$_mod\" .next/standalone/node_modules/\n\tdone\n}\n\ndo_check() {\n\tnpm run test:unit\n}\n\ndo_install() {\n\tvmkdir usr/lib/omniroute/.next\n\tvcopy .next/standalone/. usr/lib/omniroute/.next/standalone\n\n\t# Prevent removal of empty Next.js app router dirs by the post-install hook\n\tfor _d in \\\n\t\t.next/standalone/.next/server/app/dashboard \\\n\t\t.next/standalone/.next/server/app/dashboard/settings \\\n\t\t.next/standalone/.next/server/app/dashboard/providers; do\n\t\ttouch \"${DESTDIR}/usr/lib/omniroute/${_d}/.keep\"\n\tdone\n\n\tcat > \"${WRKDIR}/omniroute\" <<'EOF'\n#!/bin/sh\nexport PORT=\"${PORT:-20128}\"\nexport DATA_DIR=\"${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}\"\nexport APP_LOG_TO_FILE=\"${APP_LOG_TO_FILE:-false}\"\nmkdir -p \"${DATA_DIR}\"\nexec node /usr/lib/omniroute/.next/standalone/server.js \"$@\"\nEOF\n\tvbin \"${WRKDIR}/omniroute\"\n}\n\npost_install() {\n\tvlicense LICENSE\n}\n```\n\n</details>\n\n### Environment Variables\n\n| Variable | Default | Description |\n| --------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------- |\n| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |\n| `INITIAL_PASSWORD` | `123456` | First login password |\n| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |\n| `PORT` | framework default | Service port (`20128` in examples) |\n| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |\n| `NODE_ENV` | runtime default | Set `production` for deploy |\n| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |\n| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |\n| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |\n| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |\n| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |\n| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Server-side refresh cadence for cached Provider Limits data; UI refresh buttons still trigger manual sync |\n| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |\n| `APP_LOG_TO_FILE` | `true` | Enables application and audit log output to disk |\n| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |\n| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |\n| `CLOUDFLARED_PROTOCOL` | `http2` | Transport for managed Quick Tunnels (`http2`, `quic`, or `auto`) |\n| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |\n| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |\n| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |\n\nFor the full environment variable reference, see the [README](../README.md).\n\n---\n\n## 📊 Available Models\n\n<details>\n<summary><b>View all available models</b></summary>\n\n**Claude Code (`cc/`)** — Pro/Max: `cc/claude-opus-4-7`, `cc/claude-sonnet-4-5-20250929`, `cc/claude-haiku-4-5-20251001`\n\n**Codex (`cx/`)** — Plus/Pro: `cx/gpt-5.2-codex`, `cx/gpt-5.1-codex-max`\n\n\n**GitHub Copilot (`gh/`)**: `gh/gpt-5`, `gh/claude-4.5-sonnet`\n\n**GLM (`glm/`)** — $0.6/1M: `glm/glm-4.7`\n\n**MiniMax (`minimax/`)** — $0.2/1M: `minimax/MiniMax-M2.1`\n\n**Qoder (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`\n\n**Qwen (`qw/`)** — FREE: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`\n\n**Kiro (`kr/`)** — FREE: `kr/claude-sonnet-4.5`, `kr/claude-haiku-4.5`\n\n**DeepSeek (`ds/`)**: `ds/deepseek-chat`, `ds/deepseek-reasoner`\n\n**Groq (`groq/`)**: `groq/llama-3.3-70b-versatile`, `groq/llama-4-maverick-17b-128e-instruct`\n\n**xAI (`xai/`)**: `xai/grok-4`, `xai/grok-4-0709-fast-reasoning`, `xai/grok-code-mini`\n\n**Mistral (`mistral/`)**: `mistral/mistral-large-2501`, `mistral/codestral-2501`\n\n**Perplexity (`pplx/`)**: `pplx/sonar-pro`, `pplx/sonar`\n\n**Together AI (`together/`)**: `together/meta-llama/Llama-3.3-70B-Instruct-Turbo`\n\n**Fireworks AI (`fireworks/`)**: `fireworks/accounts/fireworks/models/deepseek-v3p1`\n\n**Cerebras (`cerebras/`)**: `cerebras/llama-3.3-70b`\n\n**Cohere (`cohere/`)**: `cohere/command-r-plus-08-2024`\n\n**NVIDIA NIM (`nvidia/`)**: `nvidia/nvidia/llama-3.3-70b-instruct`\n\n</details>\n\n---\n\n## 🧩 Advanced Features\n\n### Custom Models\n\nAdd any model ID to any provider without waiting for an app update:\n\n```bash\n# Via API\ncurl -X POST http://localhost:20128/api/provider-models \\\n -H \"Content-Type: application/json\" \\\n -d '{\"provider\": \"openai\", \"modelId\": \"gpt-4.5-preview\", \"modelName\": \"GPT-4.5 Preview\"}'\n\n# List: curl http://localhost:20128/api/provider-models?provider=openai\n# Remove: curl -X DELETE \"http://localhost:20128/api/provider-models?provider=openai&model=gpt-4.5-preview\"\n```\n\nOr use Dashboard: **Providers → [Provider] → Custom Models**.\n\nNotes:\n\n- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.\n- The **Custom Models** section is intended for providers that do not expose managed available-model imports.\n\n### Dedicated Provider Routes\n\nRoute requests directly to a specific provider with model validation:\n\n```bash\nPOST http://localhost:20128/v1/providers/openai/chat/completions\nPOST http://localhost:20128/v1/providers/openai/embeddings\nPOST http://localhost:20128/v1/providers/fireworks/images/generations\n```\n\nThe provider prefix is auto-added if missing. Mismatched models return `400`.\n\n### Network Proxy Configuration\n\n```bash\n# Set global proxy\ncurl -X PUT http://localhost:20128/api/settings/proxy \\\n -d '{\"global\": {\"type\":\"http\",\"host\":\"proxy.example.com\",\"port\":\"8080\"}}'\n\n# Per-provider proxy\ncurl -X PUT http://localhost:20128/api/settings/proxy \\\n -d '{\"providers\": {\"openai\": {\"type\":\"socks5\",\"host\":\"proxy.example.com\",\"port\":\"1080\"}}}'\n\n# Test proxy\ncurl -X POST http://localhost:20128/api/settings/proxy/test \\\n -d '{\"proxy\":{\"type\":\"socks5\",\"host\":\"proxy.example.com\",\"port\":\"1080\"}}'\n```\n\n**Precedence:** Key-specific → Combo-specific → Provider-specific → Global → Environment.\n\n### Model Catalog API\n\n```bash\ncurl http://localhost:20128/api/models/catalog\n```\n\nReturns models grouped by provider with types (`chat`, `embedding`, `image`).\n\n### Cloud Sync\n\n- Sync providers, combos, and settings across devices\n- Automatic background sync with timeout + fail-fast\n- Prefer server-side `BASE_URL`/`CLOUD_URL` in production\n\n### Cloudflare Quick Tunnel\n\n- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments\n- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint\n- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary\n- Quick Tunnels are not auto-restored after an OmniRoute or container restart; re-enable them from the dashboard when needed\n- Tunnel URLs are ephemeral and change every time you stop/start the tunnel\n- Managed Quick Tunnels default to HTTP/2 transport to avoid noisy QUIC UDP buffer warnings in constrained containers\n- Set `CLOUDFLARED_PROTOCOL=quic` or `auto` if you want to override the managed transport choice\n- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download\n\n### LLM Gateway Intelligence (Phase 9)\n\n- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)\n- **Request Idempotency** — Deduplicates requests within 5s via `Idempotency-Key` or `X-Request-Id` header\n- **Progress Tracking** — Opt-in SSE `event: progress` events via `X-OmniRoute-Progress: true` header\n\n---\n\n### Translator Playground\n\nAccess via **Dashboard → Translator**. Debug and visualize how OmniRoute translates API requests between providers.\n\n| Mode | Purpose |\n| ---------------- | -------------------------------------------------------------------------------------- |\n| **Playground** | Select source/target formats, paste a request, and see the translated output instantly |\n| **Chat Tester** | Send live chat messages through the proxy and inspect the full request/response cycle |\n| **Test Bench** | Run batch tests across multiple format combinations to verify translation correctness |\n| **Live Monitor** | Watch real-time translations as requests flow through the proxy |\n\n**Use cases:**\n\n- Debug why a specific client/provider combination fails\n- Verify that thinking tags, tool calls, and system prompts translate correctly\n- Compare format differences between OpenAI, Claude, Gemini, and Responses API formats\n\n---\n\n### Routing Strategies\n\nConfigure via **Dashboard → Settings → Routing**.\n\n| Strategy | Description |\n| ------------------------------ | ------------------------------------------------------------------------------------------------ |\n| **Fill First** | Uses accounts in priority order — primary account handles all requests until unavailable |\n| **Round Robin** | Cycles through all accounts with a configurable sticky limit (default: 3 calls per account) |\n| **P2C (Power of Two Choices)** | Picks 2 random accounts and routes to the healthier one — balances load with awareness of health |\n| **Random** | Randomly selects an account for each request using Fisher-Yates shuffle |\n| **Least Used** | Routes to the account with the oldest `lastUsedAt` timestamp, distributing traffic evenly |\n| **Cost Optimized** | Routes to the account with the lowest priority value, optimizing for lowest-cost providers |\n\n#### External Sticky Session Header\n\nFor external session affinity (for example, Claude Code/Codex agents behind reverse proxies), send:\n\n```http\nX-Session-Id: your-session-key\n```\n\nOmniRoute also accepts `x_session_id` and returns the effective session key in `X-OmniRoute-Session-Id`.\n\nIf you use Nginx and send underscore-form headers, enable:\n\n```nginx\nunderscores_in_headers on;\n```\n\n#### Wildcard Model Aliases\n\nCreate wildcard patterns to remap model names:\n\n```\nPattern: claude-sonnet-* → Target: cc/claude-sonnet-4-5-20250929\nPattern: gpt-* → Target: gh/gpt-5.1-codex\n```\n\nWildcards support `*` (any characters) and `?` (single character).\n\n#### Fallback Chains\n\nDefine global fallback chains that apply across all requests:\n\n```\nChain: production-fallback\n 1. cc/claude-opus-4-7\n 2. gh/gpt-5.1-codex\n 3. glm/glm-4.7\n```\n\n---\n\n### Resilience & Circuit Breakers\n\nConfigure via **Dashboard → Settings → Resilience**.\n\nOmniRoute implements provider-level resilience with five components:\n\n1. **Request Queue & Pacing** — System-level request shaping:\n - **Requests Per Minute (RPM)** — Maximum requests per minute per account\n - **Min Time Between Requests** — Minimum gap in milliseconds between requests\n - **Max Concurrent Requests** — Maximum simultaneous requests per account\n\n2. **Connection Cooldown** — Per-auth-type configuration for a single connection after retryable failures:\n - **Base Cooldown** — Default cooldown window for retryable upstream failures\n - **Use Upstream Retry Hints** — Honors authoritative `Retry-After` or reset hints when provided\n - **Max Backoff Steps** — Maximum exponential backoff level for repeated failures\n\n3. **Provider Circuit Breaker** — Tracks end-to-end provider failures and automatically opens the breaker when the configured threshold is reached:\n - **Failure Threshold** — Consecutive provider failures before opening the breaker\n - **Reset Timeout** — Time window before the provider is tested again\n - **CLOSED** (Healthy) — Requests flow normally\n - **OPEN** — Provider is temporarily blocked after repeated failures\n - **HALF_OPEN** — Testing if provider has recovered\n\n Connection-scoped `429` rate limits stay in **Connection Cooldown** and do not count toward the provider breaker.\n\n The provider breaker runtime state is shown on **Dashboard → Health** only.\n\n4. **Wait For Cooldown** — If every candidate connection is already cooling down, OmniRoute can wait for the earliest cooldown and retry the same client request automatically.\n\n5. **Rate Limit Auto-Detection** — When upstream providers return explicit wait windows, those hints override the local connection cooldown when the setting is enabled.\n\n**Pro Tip:** Use the **Health** page to inspect and reset live provider breakers after an outage. The Resilience page only changes configuration.\n\n---\n\n### Database Export / Import\n\nManage database backups in **Dashboard → Settings → System & Storage**.\n\n| Action | Description |\n| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |\n| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |\n| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |\n\n```bash\n# API: Export database\ncurl -o backup.sqlite http://localhost:20128/api/db-backups/export\n\n# API: Export all (full archive)\ncurl -o backup.tar.gz http://localhost:20128/api/db-backups/exportAll\n\n# API: Import database\ncurl -X POST http://localhost:20128/api/db-backups/import \\\n -F \"file=@backup.sqlite\"\n```\n\n**Import Validation:** The imported file is validated for integrity (SQLite pragma check), required tables (`provider_connections`, `provider_nodes`, `combos`, `api_keys`), and size (max 100MB).\n\n**Use Cases:**\n\n- Migrate OmniRoute between machines\n- Create external backups for disaster recovery\n- Share configurations between team members (export all → share archive)\n\n---\n\n### Settings Dashboard\n\nThe settings page is organized into 6 tabs for easy navigation:\n\n| Tab | Contents |\n| -------------- | -------------------------------------------------------------------------------------------- |\n| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |\n| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |\n| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |\n| **Resilience** | Request queue, connection cooldown, provider breaker config, and wait-for-cooldown behavior |\n| **AI** | Thinking budget configuration, global system prompt injection, prompt cache stats |\n| **Advanced** | Global proxy configuration (HTTP/SOCKS5) |\n\n---\n\n### Costs & Budget Management\n\nAccess via **Dashboard → Costs**.\n\n| Tab | Purpose |\n| ----------- | ---------------------------------------------------------------------------------------- |\n| **Budget** | Set spending limits per API key with daily/weekly/monthly budgets and real-time tracking |\n| **Pricing** | View and edit model pricing entries — cost per 1K input/output tokens per provider |\n\n```bash\n# API: Set a budget\ncurl -X POST http://localhost:20128/api/usage/budget \\\n -H \"Content-Type: application/json\" \\\n -d '{\"keyId\": \"key-123\", \"limit\": 50.00, \"period\": \"monthly\"}'\n\n# API: Get current budget status\ncurl http://localhost:20128/api/usage/budget\n```\n\n**Cost Tracking:** Every request logs token usage and calculates cost using the pricing table. View breakdowns in **Dashboard → Usage** by provider, model, and API key.\n\n---\n\n### Audio Transcription\n\nOmniRoute supports audio transcription via the OpenAI-compatible endpoint:\n\n```bash\nPOST /v1/audio/transcriptions\nAuthorization: Bearer your-api-key\nContent-Type: multipart/form-data\n\n# Example with curl\ncurl -X POST http://localhost:20128/v1/audio/transcriptions \\\n -H \"Authorization: Bearer your-api-key\" \\\n -F \"file=@audio.mp3\" \\\n -F \"model=deepgram/nova-3\"\n```\n\nAvailable providers: **Deepgram** (`deepgram/`), **AssemblyAI** (`assemblyai/`).\n\nSupported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.\n\n---\n\n### Combo Balancing Strategies\n\nConfigure per-combo balancing in **Dashboard → Combos → Create/Edit → Strategy**.\n\n| Strategy | Description |\n| ------------------ | ------------------------------------------------------------------------ |\n| **Round-Robin** | Rotates through models sequentially |\n| **Priority** | Always tries the first model; falls back only on error |\n| **Random** | Picks a random model from the combo for each request |\n| **Weighted** | Routes proportionally based on assigned weights per model |\n| **Least-Used** | Routes to the model with the fewest recent requests (uses combo metrics) |\n| **Cost-Optimized** | Routes to the cheapest available model (uses pricing table) |\n\nGlobal combo defaults can be set in **Dashboard → Settings → Routing → Combo Defaults**.\n\n---\n\n### Health Dashboard\n\nAccess via **Dashboard → Health**. Real-time system health overview with 6 cards:\n\n| Card | What It Shows |\n| --------------------- | ----------------------------------------------------------- |\n| **System Status** | Uptime, version, memory usage, data directory |\n| **Provider Health** | Global provider circuit breaker runtime state |\n| **Rate Limits** | Active connection cooldowns per account with remaining time |\n| **Active Lockouts** | Active model-scoped lockouts and temporary exclusions |\n| **Signature Cache** | Deduplication cache stats (active keys, hit rate) |\n| **Latency Telemetry** | p50/p95/p99 latency aggregation per provider |\n\n**Pro Tip:** The Health page auto-refreshes every 10 seconds. Use the circuit breaker card to identify which providers are experiencing issues.\n\n---\n\n## 🖥️ Desktop Application (Electron)\n\nOmniRoute is available as a native desktop application for Windows, macOS, and Linux.\n\n### 安裝\n\n```bash\n# From the electron directory:\ncd electron\nnpm install\n\n# Development mode (connect to running Next.js dev server):\nnpm run dev\n\n# Production mode (uses standalone build):\nnpm start\n```\n\n### Building Installers\n\n```bash\ncd electron\nnpm run build # Current platform\nnpm run build:win # Windows (.exe NSIS)\nnpm run build:mac # macOS (.dmg universal)\nnpm run build:linux # Linux (.AppImage)\n```\n\nOutput → `electron/dist-electron/`\n\n### Key Features\n\n| Feature | Description |\n| --------------------------- | ---------------------------------------------------- |\n| **Server Readiness** | Polls server before showing window (no blank screen) |\n| **System Tray** | Minimize to tray, change port, quit from tray menu |\n| **Port Management** | Change server port from tray (auto-restarts server) |\n| **Content Security Policy** | Restrictive CSP via session headers |\n| **Single Instance** | Only one app instance can run at a time |\n| **Offline Mode** | Bundled Next.js server works without internet |\n\n### Environment Variables\n\n| Variable | Default | Description |\n| --------------------- | ------- | -------------------------------- |\n| `OMNIROUTE_PORT` | `20128` | Server port |\n| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit (64–16384 MB) |\n\n📖 Full documentation: [`electron/README.md`](../electron/README.md)\n"}}}} |