Files
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
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.
2026-08-07 12:53:47 +08:00

1 line
328 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"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"}}}}