@iislee/opencodex 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +225 -0
- package/assets/architecture.png +0 -0
- package/assets/banner.png +0 -0
- package/assets/claude-code-models.gif +0 -0
- package/assets/codex-app-picker.png +0 -0
- package/bin/ocx.mjs +451 -0
- package/bin/package-main.mjs +9 -0
- package/gui/dist/assets/index-DTpMHS4F.js +67 -0
- package/gui/dist/assets/index-ZNVDE3C7.css +1 -0
- package/gui/dist/favicon.png +0 -0
- package/gui/dist/icons.svg +24 -0
- package/gui/dist/index.html +25 -0
- package/gui/dist/logo.png +0 -0
- package/gui/dist/provider-icons/alibaba-color.svg +1 -0
- package/gui/dist/provider-icons/antigravity-color.svg +1 -0
- package/gui/dist/provider-icons/antigravity.svg +1 -0
- package/gui/dist/provider-icons/claude-color.svg +1 -0
- package/gui/dist/provider-icons/claude.svg +1 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -0
- package/gui/dist/provider-icons/copilot.svg +1 -0
- package/gui/dist/provider-icons/cursor-color.svg +2 -0
- package/gui/dist/provider-icons/cursor.svg +2 -0
- package/gui/dist/provider-icons/deepseek-color.svg +1 -0
- package/gui/dist/provider-icons/discord.svg +1 -0
- package/gui/dist/provider-icons/firepass-color.svg +1 -0
- package/gui/dist/provider-icons/fireworks-color.svg +1 -0
- package/gui/dist/provider-icons/gemini-color.svg +1 -0
- package/gui/dist/provider-icons/gemini.svg +1 -0
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
- package/gui/dist/provider-icons/grok-color.svg +1 -0
- package/gui/dist/provider-icons/grok.svg +1 -0
- package/gui/dist/provider-icons/groq-color.svg +1 -0
- package/gui/dist/provider-icons/huggingface-color.svg +1 -0
- package/gui/dist/provider-icons/kimi-color.svg +1 -0
- package/gui/dist/provider-icons/kiro-color.svg +15 -0
- package/gui/dist/provider-icons/kiro.svg +14 -0
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
- package/gui/dist/provider-icons/mistral-color.svg +1 -0
- package/gui/dist/provider-icons/moonshot-color.svg +1 -0
- package/gui/dist/provider-icons/nvidia-color.svg +1 -0
- package/gui/dist/provider-icons/ollama-color.svg +1 -0
- package/gui/dist/provider-icons/openai.svg +1 -0
- package/gui/dist/provider-icons/opencode.svg +1 -0
- package/gui/dist/provider-icons/openrouter-color.svg +1 -0
- package/gui/dist/provider-icons/pi.svg +21 -0
- package/gui/dist/provider-icons/qianfan-color.svg +1 -0
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
- package/gui/dist/provider-icons/telegram.svg +1 -0
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/vllm-color.svg +1 -0
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
- package/package.json +102 -0
- package/src/AGENTS.md +28 -0
- package/src/adapters/anthropic-image-guard.ts +251 -0
- package/src/adapters/anthropic-image-normalize.ts +518 -0
- package/src/adapters/anthropic.ts +1003 -0
- package/src/adapters/azure.ts +36 -0
- package/src/adapters/base.ts +72 -0
- package/src/adapters/client-fingerprint.ts +59 -0
- package/src/adapters/cursor/arg-codec.ts +38 -0
- package/src/adapters/cursor/arg-normalize.ts +104 -0
- package/src/adapters/cursor/cursor-errors.ts +165 -0
- package/src/adapters/cursor/discovery.ts +276 -0
- package/src/adapters/cursor/effort-map.ts +127 -0
- package/src/adapters/cursor/exec-policy.ts +88 -0
- package/src/adapters/cursor/framing.ts +211 -0
- package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
- package/src/adapters/cursor/kv-store.ts +52 -0
- package/src/adapters/cursor/live-models.ts +153 -0
- package/src/adapters/cursor/live-smoke-gate.ts +41 -0
- package/src/adapters/cursor/live-transport.ts +1214 -0
- package/src/adapters/cursor/mcp-config.ts +42 -0
- package/src/adapters/cursor/mcp-manager.ts +333 -0
- package/src/adapters/cursor/message-mapper.ts +49 -0
- package/src/adapters/cursor/native-exec-common.ts +55 -0
- package/src/adapters/cursor/native-exec-desktop.ts +184 -0
- package/src/adapters/cursor/native-exec-fs.ts +329 -0
- package/src/adapters/cursor/native-exec-mcp.ts +153 -0
- package/src/adapters/cursor/native-exec-network.ts +43 -0
- package/src/adapters/cursor/native-exec-shell.ts +548 -0
- package/src/adapters/cursor/native-exec-tools.ts +118 -0
- package/src/adapters/cursor/native-exec.ts +576 -0
- package/src/adapters/cursor/protobuf-events.ts +563 -0
- package/src/adapters/cursor/protobuf-request.ts +714 -0
- package/src/adapters/cursor/request-builder.ts +255 -0
- package/src/adapters/cursor/thread-continuity.ts +67 -0
- package/src/adapters/cursor/tool-definitions.ts +505 -0
- package/src/adapters/cursor/transport-retry.ts +132 -0
- package/src/adapters/cursor/transport.ts +57 -0
- package/src/adapters/cursor/types.ts +52 -0
- package/src/adapters/cursor.ts +196 -0
- package/src/adapters/google-antigravity-replay.ts +303 -0
- package/src/adapters/google-antigravity-wire.ts +108 -0
- package/src/adapters/google-errors.ts +85 -0
- package/src/adapters/google-http.ts +100 -0
- package/src/adapters/google-tool-schema.ts +173 -0
- package/src/adapters/google-truncation.ts +13 -0
- package/src/adapters/google-wire-compiler.ts +232 -0
- package/src/adapters/google.ts +758 -0
- package/src/adapters/identity.ts +44 -0
- package/src/adapters/image.ts +23 -0
- package/src/adapters/kiro-constants.ts +16 -0
- package/src/adapters/kiro-errors.ts +197 -0
- package/src/adapters/kiro-events.ts +179 -0
- package/src/adapters/kiro-images.ts +129 -0
- package/src/adapters/kiro-retry.ts +312 -0
- package/src/adapters/kiro-thinking.ts +96 -0
- package/src/adapters/kiro-tool-fallback.ts +36 -0
- package/src/adapters/kiro-tools.ts +215 -0
- package/src/adapters/kiro-truncation.ts +33 -0
- package/src/adapters/kiro-wire.ts +129 -0
- package/src/adapters/kiro.ts +1898 -0
- package/src/adapters/mimo-free.ts +263 -0
- package/src/adapters/openai-chat.ts +1005 -0
- package/src/adapters/openai-responses.ts +1137 -0
- package/src/adapters/run-turn-queue.ts +114 -0
- package/src/adapters/tool-catalog-nudge.ts +71 -0
- package/src/adapters/upstream-http-error.ts +48 -0
- package/src/bridge.ts +1619 -0
- package/src/chat/inbound.ts +295 -0
- package/src/chat/outbound.ts +765 -0
- package/src/claude/agents-inject.ts +243 -0
- package/src/claude/alias.ts +149 -0
- package/src/claude/auth-detect.ts +229 -0
- package/src/claude/auth-mode-migration.ts +32 -0
- package/src/claude/auth-mode.ts +62 -0
- package/src/claude/context-windows.ts +189 -0
- package/src/claude/desktop-3p-guard.ts +35 -0
- package/src/claude/desktop-3p-paths.ts +84 -0
- package/src/claude/desktop-3p.ts +381 -0
- package/src/claude/desktop-health.ts +26 -0
- package/src/claude/desktop-profile.ts +263 -0
- package/src/claude/gateway-cache.ts +70 -0
- package/src/claude/inbound-debug.ts +163 -0
- package/src/claude/inbound.ts +509 -0
- package/src/claude/model-info.ts +151 -0
- package/src/claude/outbound.ts +872 -0
- package/src/cli/access.ts +108 -0
- package/src/cli/account-api.ts +268 -0
- package/src/cli/account-auth.ts +223 -0
- package/src/cli/account-extended.ts +350 -0
- package/src/cli/account.ts +275 -0
- package/src/cli/agent-driven.ts +70 -0
- package/src/cli/agent.ts +184 -0
- package/src/cli/catalog-prewarm.ts +27 -0
- package/src/cli/claude-desktop.ts +188 -0
- package/src/cli/claude.ts +286 -0
- package/src/cli/codex-shim-autorestore.ts +45 -0
- package/src/cli/combo.ts +119 -0
- package/src/cli/config-command.ts +145 -0
- package/src/cli/debug.ts +228 -0
- package/src/cli/doctor.ts +930 -0
- package/src/cli/export-command.ts +187 -0
- package/src/cli/help.ts +354 -0
- package/src/cli/index.ts +1113 -0
- package/src/cli/init.ts +224 -0
- package/src/cli/integrations.ts +142 -0
- package/src/cli/interactive-confirm.ts +133 -0
- package/src/cli/internal-dispatch.ts +20 -0
- package/src/cli/models-runtime.ts +212 -0
- package/src/cli/models.ts +336 -0
- package/src/cli/observe.ts +117 -0
- package/src/cli/opencode.ts +586 -0
- package/src/cli/pi.ts +188 -0
- package/src/cli/provider-runtime.ts +162 -0
- package/src/cli/provider.ts +463 -0
- package/src/cli/runtime-api.ts +325 -0
- package/src/cli/star-prompt.ts +155 -0
- package/src/cli/status-oauth.ts +78 -0
- package/src/cli/status.ts +321 -0
- package/src/cli/sync-cloud.ts +283 -0
- package/src/cli/system-command.ts +112 -0
- package/src/cli/tray-proxy.ts +52 -0
- package/src/cli/v2.ts +173 -0
- package/src/cli.ts +10 -0
- package/src/clients/config-export.ts +377 -0
- package/src/clients/effective-status.ts +385 -0
- package/src/clients/probes/agy.ts +55 -0
- package/src/clients/probes/cc-switch.ts +110 -0
- package/src/clients/probes/claude.ts +90 -0
- package/src/clients/probes/codex.ts +125 -0
- package/src/clients/probes/grok.ts +29 -0
- package/src/clients/probes/opencode.ts +109 -0
- package/src/clients/probes/paseo.ts +55 -0
- package/src/clients/probes/pi.ts +55 -0
- package/src/cloud/onedrive-auth.ts +666 -0
- package/src/cloud/onedrive-graph.ts +108 -0
- package/src/cloud/settings.ts +75 -0
- package/src/cloud/sync.ts +212 -0
- package/src/cloud/types.ts +56 -0
- package/src/cloud/vault.ts +89 -0
- package/src/codex/account-id.ts +34 -0
- package/src/codex/account-label.ts +34 -0
- package/src/codex/account-lifecycle.ts +55 -0
- package/src/codex/account-namespace-match.ts +63 -0
- package/src/codex/account-namespaces.ts +149 -0
- package/src/codex/account-pause.ts +20 -0
- package/src/codex/account-runtime-state.ts +31 -0
- package/src/codex/account-store.ts +517 -0
- package/src/codex/account-usability.ts +20 -0
- package/src/codex/app-server-processes.ts +756 -0
- package/src/codex/auth-api.ts +1540 -0
- package/src/codex/auth-collision.ts +107 -0
- package/src/codex/auth-context.ts +352 -0
- package/src/codex/autostart-health.ts +149 -0
- package/src/codex/catalog/aggregation.ts +378 -0
- package/src/codex/catalog/bundled.ts +251 -0
- package/src/codex/catalog/effort.ts +355 -0
- package/src/codex/catalog/metadata.ts +180 -0
- package/src/codex/catalog/parsing.ts +456 -0
- package/src/codex/catalog/provider-fetch.ts +902 -0
- package/src/codex/catalog/sync.ts +620 -0
- package/src/codex/catalog.ts +12 -0
- package/src/codex/data/upstream-models.json +830 -0
- package/src/codex/exec-invocation.ts +22 -0
- package/src/codex/features.ts +969 -0
- package/src/codex/history-migration-guardian.ts +102 -0
- package/src/codex/history-provider.ts +776 -0
- package/src/codex/home.ts +206 -0
- package/src/codex/inject.ts +799 -0
- package/src/codex/injected-marker.ts +72 -0
- package/src/codex/journal.ts +163 -0
- package/src/codex/main-account-cache.ts +32 -0
- package/src/codex/main-account.ts +40 -0
- package/src/codex/model-cache.ts +227 -0
- package/src/codex/paths.ts +65 -0
- package/src/codex/plugins-doctor.ts +242 -0
- package/src/codex/pool-rotation.ts +225 -0
- package/src/codex/project-config-warnings.ts +411 -0
- package/src/codex/quota.ts +411 -0
- package/src/codex/refresh.ts +53 -0
- package/src/codex/routing.ts +1477 -0
- package/src/codex/runtime.ts +538 -0
- package/src/codex/shim.ts +1189 -0
- package/src/codex/subagent-defaults.ts +550 -0
- package/src/codex/subagent-model-fallback.ts +469 -0
- package/src/codex/sync.ts +130 -0
- package/src/codex/warmup.ts +192 -0
- package/src/codex/websocket-registry.ts +100 -0
- package/src/combos/failover.ts +140 -0
- package/src/combos/index.ts +41 -0
- package/src/combos/request.ts +62 -0
- package/src/combos/resolve.ts +232 -0
- package/src/combos/types.ts +326 -0
- package/src/config.ts +2356 -0
- package/src/generated/jawcode-model-metadata.ts +104 -0
- package/src/github/star-state.ts +203 -0
- package/src/grok/inject.ts +545 -0
- package/src/grok/status.ts +121 -0
- package/src/grok/sync.ts +103 -0
- package/src/grok/usage-hook/report.mjs +348 -0
- package/src/grok/usage-hook.ts +278 -0
- package/src/images/artifacts.ts +516 -0
- package/src/images/fulfill-video.ts +163 -0
- package/src/images/fulfill.ts +149 -0
- package/src/images/index.ts +4 -0
- package/src/images/loop.ts +829 -0
- package/src/images/plan.ts +133 -0
- package/src/images/synthetic-tool.ts +133 -0
- package/src/images/types.ts +41 -0
- package/src/images/xai-client.ts +141 -0
- package/src/images/xai-video-client.ts +163 -0
- package/src/index.ts +22 -0
- package/src/lib/abort.ts +146 -0
- package/src/lib/admin-secrets.ts +25 -0
- package/src/lib/admission.ts +83 -0
- package/src/lib/app-owned-memory-stores.ts +173 -0
- package/src/lib/app-owned-memory.ts +265 -0
- package/src/lib/bounded-body.ts +202 -0
- package/src/lib/bun-binary-validator.d.mts +3 -0
- package/src/lib/bun-binary-validator.mjs +18 -0
- package/src/lib/bun-runtime.ts +71 -0
- package/src/lib/bun-stream-caps.ts +126 -0
- package/src/lib/config-ownership.ts +360 -0
- package/src/lib/crash-guard.ts +344 -0
- package/src/lib/debug-log-buffer.ts +83 -0
- package/src/lib/debug-settings.ts +108 -0
- package/src/lib/debug.ts +31 -0
- package/src/lib/destination-policy.ts +316 -0
- package/src/lib/errors.ts +364 -0
- package/src/lib/eventstream-decoder.ts +253 -0
- package/src/lib/gcp-adc.ts +341 -0
- package/src/lib/injection-debug-log.ts +58 -0
- package/src/lib/open-url.ts +25 -0
- package/src/lib/pinned-http.ts +151 -0
- package/src/lib/privacy.ts +20 -0
- package/src/lib/process-control.ts +165 -0
- package/src/lib/provider-outbound.ts +170 -0
- package/src/lib/provider-url.ts +14 -0
- package/src/lib/proxy-env.ts +18 -0
- package/src/lib/redact.ts +105 -0
- package/src/lib/retry-after.ts +55 -0
- package/src/lib/service-secrets.ts +25 -0
- package/src/lib/shadow-call.ts +30 -0
- package/src/lib/sidecar-tracker.ts +52 -0
- package/src/lib/sse-decoder.ts +323 -0
- package/src/lib/state-store-registrations.ts +109 -0
- package/src/lib/state-store-sweeper.ts +184 -0
- package/src/lib/test-home-guard.ts +90 -0
- package/src/lib/token-estimate.ts +69 -0
- package/src/lib/translator-budget.ts +356 -0
- package/src/lib/upstream-retry.ts +239 -0
- package/src/lib/win-exec.ts +115 -0
- package/src/lib/win-paths.ts +68 -0
- package/src/lib/windows-elevation.ts +705 -0
- package/src/lib/windows-secret-acl.ts +514 -0
- package/src/lib/winsw.ts +375 -0
- package/src/oauth/anthropic-routing.ts +594 -0
- package/src/oauth/anthropic.ts +177 -0
- package/src/oauth/callback-server.ts +294 -0
- package/src/oauth/chatgpt.ts +150 -0
- package/src/oauth/cursor.ts +211 -0
- package/src/oauth/github-copilot.ts +428 -0
- package/src/oauth/google-antigravity.ts +230 -0
- package/src/oauth/health.ts +399 -0
- package/src/oauth/index.ts +1174 -0
- package/src/oauth/key-providers.ts +108 -0
- package/src/oauth/kimi.ts +213 -0
- package/src/oauth/kiro-credentials.ts +726 -0
- package/src/oauth/kiro.ts +577 -0
- package/src/oauth/local-token-detect.ts +121 -0
- package/src/oauth/log.ts +48 -0
- package/src/oauth/login-cli.ts +163 -0
- package/src/oauth/pkce.ts +15 -0
- package/src/oauth/store.ts +630 -0
- package/src/oauth/token-guardian.ts +303 -0
- package/src/oauth/types.ts +62 -0
- package/src/oauth/xai.ts +241 -0
- package/src/pi/extensions.ts +72 -0
- package/src/pi/home.ts +42 -0
- package/src/pi/index.ts +40 -0
- package/src/pi/models.ts +278 -0
- package/src/pi/packages.ts +219 -0
- package/src/pi/settings.ts +365 -0
- package/src/pi/status.ts +68 -0
- package/src/pi/sync.ts +75 -0
- package/src/providers/alibaba-region-backup.ts +75 -0
- package/src/providers/alibaba-region-migration.ts +156 -0
- package/src/providers/alibaba-region-startup.ts +36 -0
- package/src/providers/antigravity-models.ts +205 -0
- package/src/providers/api-keys.ts +140 -0
- package/src/providers/base-url-choices.ts +64 -0
- package/src/providers/context-cap.ts +65 -0
- package/src/providers/derive.ts +339 -0
- package/src/providers/free-directory.ts +184 -0
- package/src/providers/github-copilot-transport.ts +56 -0
- package/src/providers/key-failover.ts +203 -0
- package/src/providers/kiro-models.ts +67 -0
- package/src/providers/label.ts +19 -0
- package/src/providers/model-discovery.ts +356 -0
- package/src/providers/openai-sidecar.ts +175 -0
- package/src/providers/openai-tier-startup.ts +27 -0
- package/src/providers/openai-tiers.ts +301 -0
- package/src/providers/openai-virtual-models.ts +82 -0
- package/src/providers/openrouter-routing.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +150 -0
- package/src/providers/quota.ts +1260 -0
- package/src/providers/registry.ts +1600 -0
- package/src/providers/slug-codec.ts +67 -0
- package/src/providers/xai-transport.ts +141 -0
- package/src/reasoning-effort.ts +135 -0
- package/src/responses/compaction.ts +117 -0
- package/src/responses/parser.ts +656 -0
- package/src/responses/reasoning-envelope.ts +52 -0
- package/src/responses/schema.ts +159 -0
- package/src/responses/spill-store.ts +394 -0
- package/src/responses/state.ts +895 -0
- package/src/responses/tool-groups.ts +19 -0
- package/src/router.ts +425 -0
- package/src/server/adapter-resolve.ts +80 -0
- package/src/server/auth-cors.ts +530 -0
- package/src/server/chat-completions.ts +368 -0
- package/src/server/claude-messages.ts +914 -0
- package/src/server/effort-policy.ts +172 -0
- package/src/server/gui-static.ts +123 -0
- package/src/server/image-retry.ts +42 -0
- package/src/server/images.ts +476 -0
- package/src/server/index.ts +1126 -0
- package/src/server/lifecycle.ts +227 -0
- package/src/server/live.ts +598 -0
- package/src/server/management/agent-settings-routes.ts +1169 -0
- package/src/server/management/api-access.ts +141 -0
- package/src/server/management/api-key-usage.ts +167 -0
- package/src/server/management/body.ts +35 -0
- package/src/server/management/clients-routes.ts +63 -0
- package/src/server/management/cloud-sync-routes.ts +266 -0
- package/src/server/management/combo-routes.ts +220 -0
- package/src/server/management/config-routes.ts +422 -0
- package/src/server/management/context.ts +31 -0
- package/src/server/management/logs-usage-routes.ts +707 -0
- package/src/server/management/model-routes.ts +525 -0
- package/src/server/management/oauth-account-routes.ts +563 -0
- package/src/server/management/provider-routes.ts +556 -0
- package/src/server/management/shared.ts +277 -0
- package/src/server/management/sidebar-routes.ts +90 -0
- package/src/server/management/system-restart.ts +179 -0
- package/src/server/management/system-routes.ts +117 -0
- package/src/server/management/usage-summary-cache.ts +86 -0
- package/src/server/management-api.ts +215 -0
- package/src/server/management-auth.ts +267 -0
- package/src/server/memory-watchdog.ts +156 -0
- package/src/server/port-reclaim.ts +307 -0
- package/src/server/ports.ts +116 -0
- package/src/server/proxy-liveness.ts +201 -0
- package/src/server/relay-eager.ts +313 -0
- package/src/server/relay.ts +1049 -0
- package/src/server/request-decompress.ts +132 -0
- package/src/server/request-log-conversation.ts +168 -0
- package/src/server/request-log.ts +1046 -0
- package/src/server/responses/collaboration.ts +354 -0
- package/src/server/responses/compact.ts +384 -0
- package/src/server/responses/core.ts +2758 -0
- package/src/server/responses/encrypted-payload.ts +308 -0
- package/src/server/responses/fetch-helpers.ts +157 -0
- package/src/server/responses/passthrough-error.ts +78 -0
- package/src/server/responses/terminal-guard.ts +230 -0
- package/src/server/responses/upstream-error.ts +48 -0
- package/src/server/responses-image-gen-repair.ts +132 -0
- package/src/server/responses-item-id-repair.ts +224 -0
- package/src/server/responses.ts +9 -0
- package/src/server/search.ts +136 -0
- package/src/server/sse-payload-rewrite.ts +175 -0
- package/src/server/startup-action-control.ts +308 -0
- package/src/server/startup-health-cache.ts +113 -0
- package/src/server/system-env.ts +413 -0
- package/src/server/windows-tcp-drop.ts +184 -0
- package/src/server/windows-tray-control.ts +41 -0
- package/src/server/ws-bridge.ts +471 -0
- package/src/service.ts +2554 -0
- package/src/stall-timeout.ts +20 -0
- package/src/storage/cleanup-job.ts +57 -0
- package/src/storage/cleanup.ts +3085 -0
- package/src/storage/policy-job.ts +457 -0
- package/src/storage/policy-scheduler.ts +40 -0
- package/src/storage/policy-worker.ts +59 -0
- package/src/storage/policy.ts +527 -0
- package/src/storage/restore-job.ts +299 -0
- package/src/storage/restore-worker.ts +58 -0
- package/src/storage/scanner.ts +238 -0
- package/src/storage/storage-mutation-coordinator.ts +139 -0
- package/src/storage/worker-lifecycle.ts +215 -0
- package/src/tray/assets/opencodex-tray-offline.ico +0 -0
- package/src/tray/assets/opencodex-tray-online.ico +0 -0
- package/src/tray/assets/opencodex-tray-warning.ico +0 -0
- package/src/tray/assets/opencodex-tray.png +0 -0
- package/src/tray/windows-tray.ps1 +290 -0
- package/src/tray/windows.ts +730 -0
- package/src/types.ts +1237 -0
- package/src/update/badge.ts +72 -0
- package/src/update/index.ts +407 -0
- package/src/update/job.ts +1520 -0
- package/src/update/notify.ts +257 -0
- package/src/update/npm-invocation.d.mts +23 -0
- package/src/update/npm-invocation.mjs +94 -0
- package/src/update/tray-update-plan.d.mts +18 -0
- package/src/update/tray-update-plan.mjs +38 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/debug.ts +97 -0
- package/src/usage/expected-prices.ts +164 -0
- package/src/usage/log.ts +658 -0
- package/src/usage/summary.ts +585 -0
- package/src/usage/totals.ts +14 -0
- package/src/vision/anthropic-describe.ts +185 -0
- package/src/vision/describe.ts +125 -0
- package/src/vision/index.ts +467 -0
- package/src/web-search/anthropic-executor.ts +189 -0
- package/src/web-search/executor.ts +105 -0
- package/src/web-search/format-result.ts +89 -0
- package/src/web-search/index.ts +196 -0
- package/src/web-search/loop.ts +664 -0
- package/src/web-search/parse.ts +220 -0
- package/src/web-search/progress-stream.ts +342 -0
- package/src/web-search/synthetic-tool.ts +47 -0
|
@@ -0,0 +1,1600 @@
|
|
|
1
|
+
import type { CodexAccountMode, OcxProviderConfig } from "../types";
|
|
2
|
+
import { KIRO_MODELS, KIRO_MODEL_CONTEXT_WINDOWS, KIRO_MODEL_REASONING_EFFORTS } from "./kiro-models";
|
|
3
|
+
import { ANTIGRAVITY_MODELS, ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, ANTIGRAVITY_MODEL_EFFORTS } from "./antigravity-models";
|
|
4
|
+
import type { ProviderBaseUrlChoice } from "./base-url-choices";
|
|
5
|
+
import {
|
|
6
|
+
QWEN_CLOUD_BASE_URL_CHOICES, QWEN_CLOUD_TOKEN_PLAN_BASE_URL,
|
|
7
|
+
ALIBABA_INTL_BASE_URL_CHOICES, ALIBABA_INTL_TOKEN_PLAN_BASE_URL,
|
|
8
|
+
ALIBABA_CODING_BASE_URL_CHOICES, ALIBABA_CODING_INTL_BASE_URL,
|
|
9
|
+
} from "./base-url-choices";
|
|
10
|
+
import {
|
|
11
|
+
CURSOR_STATIC_MODELS,
|
|
12
|
+
cursorModelContextWindows,
|
|
13
|
+
cursorModelIds,
|
|
14
|
+
cursorModelInputModalities,
|
|
15
|
+
cursorModelReasoningEfforts,
|
|
16
|
+
} from "../adapters/cursor/discovery";
|
|
17
|
+
|
|
18
|
+
export type ProviderAuthKind = "forward" | "oauth" | "key" | "local";
|
|
19
|
+
export type MetadataModelIdNormalize = "case-insensitive";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Wire protocol a client spoke when it reached the proxy. Chat and Anthropic surfaces
|
|
23
|
+
* translate into a Responses-shaped body and replay through `handleResponses`, so the
|
|
24
|
+
* original inbound has to travel with the request or the replay looks native.
|
|
25
|
+
*/
|
|
26
|
+
export type InboundWire = "responses" | "chat" | "anthropic";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A per-model wire default: a bare string applies to every inbound, while the object
|
|
30
|
+
* form applies only to the listed inbound protocols.
|
|
31
|
+
*/
|
|
32
|
+
export type ModelWireDefault = string | { wire: string; inbound: readonly InboundWire[] };
|
|
33
|
+
|
|
34
|
+
export type ProviderModelDiscoveryScalar = string | number | boolean;
|
|
35
|
+
|
|
36
|
+
export type ProviderModelDiscoveryPredicate =
|
|
37
|
+
| {
|
|
38
|
+
path: readonly string[];
|
|
39
|
+
equalsAny: readonly ProviderModelDiscoveryScalar[];
|
|
40
|
+
caseInsensitive?: boolean;
|
|
41
|
+
}
|
|
42
|
+
| {
|
|
43
|
+
path: readonly string[];
|
|
44
|
+
/**
|
|
45
|
+
* A string-valued upstream target uses substring matching; an array-valued target uses
|
|
46
|
+
* exact element matching. Use `equalsAny` when the string must match in full.
|
|
47
|
+
*/
|
|
48
|
+
containsAny: readonly ProviderModelDiscoveryScalar[];
|
|
49
|
+
caseInsensitive?: boolean;
|
|
50
|
+
}
|
|
51
|
+
| {
|
|
52
|
+
path: readonly string[];
|
|
53
|
+
/** Uses the same string-substring and array-element semantics as `containsAny`. */
|
|
54
|
+
containsAll: readonly ProviderModelDiscoveryScalar[];
|
|
55
|
+
caseInsensitive?: boolean;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export interface ProviderModelDiscoveryFilter {
|
|
59
|
+
/** Every predicate must match. */
|
|
60
|
+
allOf?: readonly ProviderModelDiscoveryPredicate[];
|
|
61
|
+
/** At least one predicate must match. */
|
|
62
|
+
anyOf?: readonly ProviderModelDiscoveryPredicate[];
|
|
63
|
+
/** No predicate may match. */
|
|
64
|
+
noneOf?: readonly ProviderModelDiscoveryPredicate[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface ProviderModelDiscoverySharedSpec {
|
|
68
|
+
/** Query parameters applied to the resolved discovery URL. */
|
|
69
|
+
query?: Readonly<Record<string, string>>;
|
|
70
|
+
/** Declarative eligibility rules evaluated against each untrusted model row. */
|
|
71
|
+
filter?: ProviderModelDiscoveryFilter;
|
|
72
|
+
/** Optional lower byte ceiling; the process-wide hard ceiling still wins. */
|
|
73
|
+
maxResponseBytes?: number;
|
|
74
|
+
/** Optional lower raw-row ceiling; the process-wide hard ceiling still wins. */
|
|
75
|
+
maxModels?: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
type ProviderModelDiscoveryLocation =
|
|
79
|
+
| {
|
|
80
|
+
/** Registry-owned absolute endpoint. Mutually exclusive with `path`. */
|
|
81
|
+
url: string;
|
|
82
|
+
path?: never;
|
|
83
|
+
}
|
|
84
|
+
| {
|
|
85
|
+
/** Resource path relative to baseUrl; query strings and fragments are disallowed. */
|
|
86
|
+
path: string;
|
|
87
|
+
url?: never;
|
|
88
|
+
}
|
|
89
|
+
| {
|
|
90
|
+
/** Keep the adapter-derived default discovery endpoint. */
|
|
91
|
+
url?: never;
|
|
92
|
+
path?: never;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Trusted live-model discovery policy. This metadata is registry-only: it must never be copied
|
|
97
|
+
* into config.json, where a same-named custom provider could otherwise redirect a stored key.
|
|
98
|
+
*/
|
|
99
|
+
export type ProviderModelDiscoverySpec = ProviderModelDiscoverySharedSpec & ProviderModelDiscoveryLocation;
|
|
100
|
+
|
|
101
|
+
export interface ProviderRegistryEntry {
|
|
102
|
+
id: string;
|
|
103
|
+
label: string;
|
|
104
|
+
adapter: string;
|
|
105
|
+
baseUrl: string;
|
|
106
|
+
apiKeyTransport?: OcxProviderConfig["apiKeyTransport"];
|
|
107
|
+
authKind: ProviderAuthKind;
|
|
108
|
+
codexAccountMode?: CodexAccountMode;
|
|
109
|
+
/** OAuth preset may explicitly honor a persisted API-key billing mode. */
|
|
110
|
+
allowKeyAuthOverride?: boolean;
|
|
111
|
+
allowPrivateNetworkByDefault?: boolean;
|
|
112
|
+
keyOptional?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Free-tier pricing (no paid subscription required). Distinct from `keyOptional`:
|
|
115
|
+
* free tiers may still require an API key (e.g. NVIDIA NIM free credits).
|
|
116
|
+
*/
|
|
117
|
+
freeTier?: boolean;
|
|
118
|
+
allowBaseUrlOverride?: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Do not claim an existing same-named key provider whose fixed destination differs from this
|
|
121
|
+
* preset. Enable for newly promoted ids so an older custom key cannot be silently retargeted.
|
|
122
|
+
*/
|
|
123
|
+
preserveCustomDestination?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Optional endpoint picker for providers with multiple official hosts
|
|
126
|
+
* (e.g. Qwen Cloud token plan vs pay-as-you-go). Requires `allowBaseUrlOverride`
|
|
127
|
+
* so the selected URL is honored at route time. A choice without `baseUrl` is "Custom".
|
|
128
|
+
*/
|
|
129
|
+
baseUrlChoices?: readonly ProviderBaseUrlChoice[];
|
|
130
|
+
/** Static headers merged into every upstream request for this provider. */
|
|
131
|
+
staticHeaders?: Record<string, string>;
|
|
132
|
+
modelSuffixBracketStrip?: boolean;
|
|
133
|
+
featured?: boolean;
|
|
134
|
+
dashboardPreset?: boolean;
|
|
135
|
+
note?: string;
|
|
136
|
+
dashboardUrl?: string;
|
|
137
|
+
defaultModel?: string;
|
|
138
|
+
models?: string[];
|
|
139
|
+
liveModels?: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Registry-only per-model wire defaults for mixed OpenAI-compatible gateways.
|
|
142
|
+
* These are intentionally not seeded into saved config: an explicit `modelAdapters`
|
|
143
|
+
* entry must remain distinguishable and must always win over a default.
|
|
144
|
+
*
|
|
145
|
+
* A bare string applies to every inbound protocol. The object form scopes the
|
|
146
|
+
* default to the inbound surfaces named in `inbound`, which is how a model that is
|
|
147
|
+
* native on two wires can serve each client on the wire it already speaks instead
|
|
148
|
+
* of paying a translation hop.
|
|
149
|
+
*/
|
|
150
|
+
modelWireDefaults?: Record<string, ModelWireDefault>;
|
|
151
|
+
/**
|
|
152
|
+
* Responses-API resource path for providers whose route is not `/v1/responses`.
|
|
153
|
+
* Unlike `modelWireDefaults` above, this IS seeded into saved config: it describes
|
|
154
|
+
* the provider's fixed endpoint rather than a default a user might want to override
|
|
155
|
+
* per model. DeepSeek documents `POST /responses` with no `/v1` segment.
|
|
156
|
+
*/
|
|
157
|
+
responsesPath?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Responses upstream that stores nothing server-side. Stateful request parameters
|
|
160
|
+
* are dropped and `store` is pinned false, and orphaned tool results left by a
|
|
161
|
+
* replay miss are repaired rather than forwarded.
|
|
162
|
+
*/
|
|
163
|
+
statelessResponses?: boolean;
|
|
164
|
+
modelDiscovery?: ProviderModelDiscoverySpec;
|
|
165
|
+
contextWindow?: number;
|
|
166
|
+
modelContextWindows?: Record<string, number>;
|
|
167
|
+
modelInputModalities?: Record<string, string[]>;
|
|
168
|
+
defaultMaxOutputTokens?: number;
|
|
169
|
+
modelMaxOutputTokens?: Record<string, number>;
|
|
170
|
+
reasoningEfforts?: string[];
|
|
171
|
+
modelReasoningEfforts?: Record<string, string[]>;
|
|
172
|
+
modelDefaultReasoningEfforts?: Record<string, string>;
|
|
173
|
+
reasoningEffortMap?: Record<string, string>;
|
|
174
|
+
modelReasoningEffortMap?: Record<string, Record<string, string>>;
|
|
175
|
+
noVisionModels?: string[];
|
|
176
|
+
noReasoningModels?: string[];
|
|
177
|
+
noTemperatureModels?: string[];
|
|
178
|
+
noTopPModels?: string[];
|
|
179
|
+
noPenaltyModels?: string[];
|
|
180
|
+
/** Opt this provider into parallel tool calls (see OcxProviderConfig.parallelToolCalls). */
|
|
181
|
+
parallelToolCalls?: boolean;
|
|
182
|
+
/** Opt this provider into forwarding prompt_cache_key (OpenAI-specific; strict backends reject it). */
|
|
183
|
+
promptCacheKey?: boolean;
|
|
184
|
+
autoToolChoiceOnlyModels?: string[];
|
|
185
|
+
preserveReasoningContentModels?: string[];
|
|
186
|
+
reasoningSplitModels?: string[];
|
|
187
|
+
thinkingToggleModels?: string[];
|
|
188
|
+
thinkingBudgetModels?: string[];
|
|
189
|
+
escapeBuiltinToolNames?: boolean;
|
|
190
|
+
oauthId?: string;
|
|
191
|
+
virtualModels?: Record<string, { wireModelId: string; reasoningMode: "pro" }>;
|
|
192
|
+
modelMaxInputTokens?: Record<string, number>;
|
|
193
|
+
jawcodeBundle?: string;
|
|
194
|
+
extraMetadataAliases?: string[];
|
|
195
|
+
metadataModelIdNormalize?: MetadataModelIdNormalize;
|
|
196
|
+
googleMode?: "ai-studio" | "vertex" | "cloud-code-assist";
|
|
197
|
+
project?: string;
|
|
198
|
+
location?: string;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export type ProviderConfigSeed = Pick<
|
|
202
|
+
OcxProviderConfig,
|
|
203
|
+
"adapter" | "baseUrl" | "apiKeyTransport" | "responsesPath" | "authMode" | "keyOptional" | "freeTier" | "modelSuffixBracketStrip" | "defaultModel" | "models"
|
|
204
|
+
| "liveModels" | "contextWindow" | "modelContextWindows" | "modelInputModalities"
|
|
205
|
+
| "modelMaxInputTokens" | "defaultMaxOutputTokens" | "modelMaxOutputTokens"
|
|
206
|
+
| "reasoningEfforts" | "modelReasoningEfforts" | "modelDefaultReasoningEfforts" | "reasoningEffortMap" | "modelReasoningEffortMap"
|
|
207
|
+
| "noVisionModels" | "noReasoningModels" | "noTemperatureModels" | "noTopPModels" | "noPenaltyModels"
|
|
208
|
+
| "autoToolChoiceOnlyModels" | "preserveReasoningContentModels" | "reasoningSplitModels" | "thinkingToggleModels" | "thinkingBudgetModels" | "escapeBuiltinToolNames"
|
|
209
|
+
| "googleMode" | "project" | "location" | "headers"
|
|
210
|
+
>;
|
|
211
|
+
|
|
212
|
+
// Shared between the OAuth (Claude account) and API-key Anthropic entries so both expose the
|
|
213
|
+
// same static model seed.
|
|
214
|
+
// 260710 context refresh: Tier-2 evidence in
|
|
215
|
+
// devlog/_plan/260710_provider_hardening/001_research_frontier.md.
|
|
216
|
+
const ANTHROPIC_MODELS = ["claude-fable-5", "claude-sonnet-5", "claude-opus-5", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-4-6", "claude-sonnet-4-6", "claude-haiku-4-5"];
|
|
217
|
+
const ANTHROPIC_MODEL_CONTEXT_WINDOWS: Record<string, number> = { "claude-sonnet-5": 1_000_000, "claude-fable-5": 1_000_000, "claude-opus-5": 1_000_000, "claude-opus-4-8": 1_000_000, "claude-haiku-4-5": 200_000 };
|
|
218
|
+
|
|
219
|
+
const ZAI_GLM_52_MODELS = ["glm-5.2", "glm-5.2[1m]"];
|
|
220
|
+
const ZAI_GLM_52_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
221
|
+
// 260710 MiniMax models and context windows: Tier-2 evidence in
|
|
222
|
+
// devlog/_plan/260710_provider_hardening/002_research_cn.md.
|
|
223
|
+
const MINIMAX_MODELS = [
|
|
224
|
+
"MiniMax-M3",
|
|
225
|
+
"MiniMax-M2.7", "MiniMax-M2.7-highspeed",
|
|
226
|
+
"MiniMax-M2.5", "MiniMax-M2.5-highspeed",
|
|
227
|
+
"MiniMax-M2.1", "MiniMax-M2.1-highspeed",
|
|
228
|
+
"MiniMax-M2",
|
|
229
|
+
];
|
|
230
|
+
const MINIMAX_MODEL_CONTEXT_WINDOWS: Record<string, number> = Object.fromEntries(
|
|
231
|
+
MINIMAX_MODELS.map(id => [id, id === "MiniMax-M3" ? 1_000_000 : 204_800]),
|
|
232
|
+
);
|
|
233
|
+
const MINIMAX_M3_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
234
|
+
const MINIMAX_M3_REASONING_EFFORT_MAP: Record<string, string> = {
|
|
235
|
+
none: "disabled",
|
|
236
|
+
minimal: "disabled",
|
|
237
|
+
low: "disabled",
|
|
238
|
+
medium: "adaptive",
|
|
239
|
+
high: "adaptive",
|
|
240
|
+
xhigh: "adaptive",
|
|
241
|
+
max: "adaptive",
|
|
242
|
+
};
|
|
243
|
+
const OPENAI_GPT56_MODELS = ["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"];
|
|
244
|
+
const OPENAI_GPT56_PRO_MODELS = ["gpt-5.6-sol-pro", "gpt-5.6-terra-pro", "gpt-5.6-luna-pro"];
|
|
245
|
+
const OPENAI_API_GPT56_CONTEXT_WINDOW = 1_050_000;
|
|
246
|
+
const OPENAI_CODEX_GPT56_CONTEXT_WINDOW = 372_000;
|
|
247
|
+
const OPENAI_GPT56_CONTEXT_WINDOWS = {
|
|
248
|
+
"gpt-5.6-sol": OPENAI_CODEX_GPT56_CONTEXT_WINDOW,
|
|
249
|
+
"gpt-5.6-terra": OPENAI_CODEX_GPT56_CONTEXT_WINDOW,
|
|
250
|
+
"gpt-5.6-luna": OPENAI_CODEX_GPT56_CONTEXT_WINDOW,
|
|
251
|
+
};
|
|
252
|
+
const OPENAI_API_GPT56_CONTEXT_WINDOWS: Record<string, number> = {
|
|
253
|
+
...Object.fromEntries([...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS].map(id => [id, OPENAI_API_GPT56_CONTEXT_WINDOW])),
|
|
254
|
+
"gpt-5.5": OPENAI_API_GPT56_CONTEXT_WINDOW,
|
|
255
|
+
};
|
|
256
|
+
const OPENAI_API_GPT56_MAX_INPUT_TOKENS: Record<string, number> = {
|
|
257
|
+
...Object.fromEntries([...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS].map(id => [id, 922_000])),
|
|
258
|
+
"gpt-5.5": 922_000,
|
|
259
|
+
};
|
|
260
|
+
const OPENAI_API_GPT56_VIRTUAL_MODELS: Record<string, { wireModelId: string; reasoningMode: "pro" }> = {
|
|
261
|
+
"gpt-5.6-sol-pro": { wireModelId: "gpt-5.6-sol", reasoningMode: "pro" },
|
|
262
|
+
"gpt-5.6-terra-pro": { wireModelId: "gpt-5.6-terra", reasoningMode: "pro" },
|
|
263
|
+
"gpt-5.6-luna-pro": { wireModelId: "gpt-5.6-luna", reasoningMode: "pro" },
|
|
264
|
+
};
|
|
265
|
+
const OPENAI_API_GPT56_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
266
|
+
const OPENROUTER_GPT56_MODELS = OPENAI_GPT56_MODELS.map(id => `openai/${id}`);
|
|
267
|
+
// OpenRouter's live /endpoints routes report 1,050,000; keep this separate from the
|
|
268
|
+
// unverified OpenAI API-key seed. Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
|
|
269
|
+
const OPENROUTER_GPT56_CONTEXT_WINDOW = 1_050_000;
|
|
270
|
+
const OPENROUTER_GPT56_CONTEXT_WINDOWS = {
|
|
271
|
+
"openai/gpt-5.6-sol": OPENROUTER_GPT56_CONTEXT_WINDOW,
|
|
272
|
+
"openai/gpt-5.6-terra": OPENROUTER_GPT56_CONTEXT_WINDOW,
|
|
273
|
+
"openai/gpt-5.6-luna": OPENROUTER_GPT56_CONTEXT_WINDOW,
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Vendor thinking-toggle models (MiMo v2.x, GLM 5/5.1 on Zen Go): the wire knob is
|
|
278
|
+
* `thinking: {type: enabled|disabled}` — a binary. Advertise the full Codex picker ladder
|
|
279
|
+
* and map efforts onto the toggle. Zen Go
|
|
280
|
+
* pass-through probed live 2026-07-07 (glm-5.2 toggle verified; mimo/minimax accept shape).
|
|
281
|
+
*/
|
|
282
|
+
const THINKING_TOGGLE_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
283
|
+
const THINKING_TOGGLE_MAP: Record<string, string> = {
|
|
284
|
+
none: "disabled",
|
|
285
|
+
minimal: "disabled",
|
|
286
|
+
low: "disabled",
|
|
287
|
+
medium: "enabled",
|
|
288
|
+
high: "enabled",
|
|
289
|
+
xhigh: "enabled",
|
|
290
|
+
max: "enabled",
|
|
291
|
+
};
|
|
292
|
+
const OPENCODE_GO_THINKING_TOGGLE_MODELS = [
|
|
293
|
+
"mimo-v2.5", "mimo-v2.5-pro", "mimo-v2-omni", "mimo-v2-pro", "glm-5", "glm-5.1",
|
|
294
|
+
];
|
|
295
|
+
/**
|
|
296
|
+
* Zhipu's domestic BigModel platform. Text families first, then the vision member: modalities are
|
|
297
|
+
* declared per model because `noVisionModels` means the opposite of "text only" here — it routes
|
|
298
|
+
* images through the proxy's vision sidecar (src/codex/catalog/provider-fetch.ts), a claim nobody
|
|
299
|
+
* has verified for BigModel-hosted GLM.
|
|
300
|
+
*/
|
|
301
|
+
const ZHIPU_BIGMODEL_TEXT_MODELS = ["glm-4.6", "glm-4.7", "glm-4.7-flash", "glm-5", "glm-5.1"];
|
|
302
|
+
const ZHIPU_BIGMODEL_MODELS = [...ZHIPU_BIGMODEL_TEXT_MODELS, "glm-4.6v"];
|
|
303
|
+
const ZHIPU_BIGMODEL_INPUT_MODALITIES: Record<string, string[]> = {
|
|
304
|
+
...Object.fromEntries(ZHIPU_BIGMODEL_TEXT_MODELS.map(id => [id, ["text"]])),
|
|
305
|
+
"glm-4.6v": ["text", "image"],
|
|
306
|
+
};
|
|
307
|
+
const ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS = ["glm-4.6", "glm-4.7", "glm-5", "glm-5.1"];
|
|
308
|
+
const THINKING_BUDGET_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
309
|
+
const THINKING_BUDGET_MODELS = [
|
|
310
|
+
"qwen3.5-397b", "qwen3.6-35b",
|
|
311
|
+
"qwen3.5-plus", "qwen3.6-plus", "qwen3.7-max", "qwen3.7-plus",
|
|
312
|
+
];
|
|
313
|
+
const OPENCODE_GO_THINKING_BUDGET_MODELS = ["qwen3.5-plus", "qwen3.6-plus", "qwen3.7-max", "qwen3.7-plus"];
|
|
314
|
+
const DEEPSEEK_THINKING_MODELS = ["deepseek-v4-pro", "deepseek-v4-flash"];
|
|
315
|
+
const OPENCODE_FREE_DEEPSEEK_MODELS = ["deepseek-v4-flash-free"];
|
|
316
|
+
// "max" is advertised too: the wire map routes xhigh->max and max->max, so the picker
|
|
317
|
+
// should surface the max tier instead of hiding it behind xhigh.
|
|
318
|
+
const DEEPSEEK_THINKING_EFFORTS = ["high", "xhigh", "max"];
|
|
319
|
+
const DEEPSEEK_THINKING_REASONING_MAP: Record<string, string> = {
|
|
320
|
+
low: "high",
|
|
321
|
+
medium: "high",
|
|
322
|
+
high: "high",
|
|
323
|
+
xhigh: "max",
|
|
324
|
+
max: "max",
|
|
325
|
+
};
|
|
326
|
+
// 260719 Alibaba Token Plan Personal Edition (China/Beijing). Keep it distinct from
|
|
327
|
+
// Coding Plan: the products use different exact allowlists and different base URLs.
|
|
328
|
+
// Evidence: https://help.aliyun.com/en/model-studio/token-plan-personal-overview
|
|
329
|
+
// https://help.aliyun.com/en/model-studio/token-plan-quickstart
|
|
330
|
+
const ALIBABA_TOKEN_PLAN_MODELS = [
|
|
331
|
+
"qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-flash",
|
|
332
|
+
"glm-5.2", "deepseek-v4-pro",
|
|
333
|
+
];
|
|
334
|
+
const ALIBABA_TOKEN_PLAN_QWEN_MODELS = [
|
|
335
|
+
"qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-flash",
|
|
336
|
+
];
|
|
337
|
+
const ALIBABA_TOKEN_PLAN_INPUT_MODALITIES: Record<string, string[]> = {
|
|
338
|
+
"qwen3.8-max-preview": ["text", "image"],
|
|
339
|
+
"qwen3.7-max": ["text", "image"],
|
|
340
|
+
"qwen3.7-plus": ["text", "image"],
|
|
341
|
+
"qwen3.6-flash": ["text", "image"],
|
|
342
|
+
"glm-5.2": ["text"],
|
|
343
|
+
"deepseek-v4-pro": ["text"],
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
// 260721 Alibaba Token Plan International (ap-southeast-1 / Singapore, hardened 260721).
|
|
347
|
+
// Multi-vendor lineup distinct from Beijing — includes DeepSeek V4 flash, Kimi K2.7, MiniMax.
|
|
348
|
+
// Evidence: https://www.alibabacloud.com/help/en/model-studio/token-plan-overview
|
|
349
|
+
// https://qwencloud.com/pricing/token-plan (qwen3.8 metadata)
|
|
350
|
+
const ALIBABA_INTL_TOKEN_PLAN_MODELS = [
|
|
351
|
+
"qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", "qwen3.6-flash",
|
|
352
|
+
"deepseek-v4-pro", "deepseek-v4-flash", "deepseek-v3.2",
|
|
353
|
+
"kimi-k2.7-code", "kimi-k2.6", "kimi-k2.5",
|
|
354
|
+
"glm-5.2", "glm-5.1", "glm-5",
|
|
355
|
+
"MiniMax-M2.5",
|
|
356
|
+
];
|
|
357
|
+
const ALIBABA_INTL_TOKEN_PLAN_QWEN_MODELS = [
|
|
358
|
+
"qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", "qwen3.6-flash",
|
|
359
|
+
];
|
|
360
|
+
|
|
361
|
+
// 260722 Tencent Cloud Coding Plan. The plan's model set is explicitly dynamic; these are the
|
|
362
|
+
// current documented ids and live discovery remains enabled so successful /models responses win.
|
|
363
|
+
// Tencent marks every Coding Plan model as text-only input and restricts plan keys to interactive
|
|
364
|
+
// coding tools (not custom application backends or non-interactive batch automation).
|
|
365
|
+
// Evidence: https://cloud.tencent.cn/document/product/1823/130092
|
|
366
|
+
const TENCENT_CODING_PLAN_MODELS = ["tc-code-latest", "glm-5", "kimi-k2.5", "minimax-m2.5"];
|
|
367
|
+
// Volcengine's authenticated /api/v3/models catalog mixes chat models with embedding,
|
|
368
|
+
// image, video, and 3D generation resources. Keep the Codex-facing presets scoped to
|
|
369
|
+
// models documented for text/agent or Coding Plan use.
|
|
370
|
+
//
|
|
371
|
+
// Maintenance owner: @lidge-jun. Verified 2026-08-01 against the vendor's own docs —
|
|
372
|
+
// endpoints https://docs.volcengine.com/docs/82379/1528783 (Coding Plan) and
|
|
373
|
+
// https://docs.volcengine.com/docs/82379/2165245 (Agent Plan); Codex CLI integration
|
|
374
|
+
// https://www.volcengine.com/docs/82379/2556056; supported clients
|
|
375
|
+
// https://www.volcengine.com/docs/82379/2188957; terms https://www.volcengine.com/docs/6256/64903
|
|
376
|
+
// (北京火山引擎科技有限公司). Plan quota is restricted to supported AI coding tools and misuse
|
|
377
|
+
// is documented as grounds for suspension — see the `note` on both Plan entries.
|
|
378
|
+
// Report a break by opening an issue tagging the owner; the three things that rot first are the
|
|
379
|
+
// static catalogs (liveModels:false cannot self-heal), the base URLs, and those Plan terms.
|
|
380
|
+
// Full evidence ledger: devlog/_plan/260801_pr611_volcengine_evidence/000_evidence_ledger.md
|
|
381
|
+
const VOLCENGINE_ARK_MODELS = [
|
|
382
|
+
"doubao-seed-2-1-pro-260628",
|
|
383
|
+
"doubao-seed-2-1-turbo-260628",
|
|
384
|
+
"doubao-seed-evolving",
|
|
385
|
+
"deepseek-v4-pro-260425",
|
|
386
|
+
"deepseek-v4-flash-260425",
|
|
387
|
+
"deepseek-v3-2-251201",
|
|
388
|
+
"glm-5-2-260617",
|
|
389
|
+
"glm-4-7-251222",
|
|
390
|
+
];
|
|
391
|
+
const VOLCENGINE_DOUBAO_THINKING_MODELS = [
|
|
392
|
+
"doubao-seed-2-1-pro-260628",
|
|
393
|
+
"doubao-seed-2-1-turbo-260628",
|
|
394
|
+
"doubao-seed-evolving",
|
|
395
|
+
];
|
|
396
|
+
const VOLCENGINE_CODING_PLAN_MODELS = [
|
|
397
|
+
"ark-code-latest",
|
|
398
|
+
"doubao-seed-2.0-code",
|
|
399
|
+
"deepseek-v4-pro",
|
|
400
|
+
"deepseek-v4-flash",
|
|
401
|
+
"glm-5.2",
|
|
402
|
+
"kimi-k2.6",
|
|
403
|
+
"minimax-m3",
|
|
404
|
+
];
|
|
405
|
+
const VOLCENGINE_AGENT_PLAN_MODELS = [
|
|
406
|
+
"deepseek-v4-pro",
|
|
407
|
+
"deepseek-v4-flash",
|
|
408
|
+
"glm-5.2",
|
|
409
|
+
"kimi-k2.6",
|
|
410
|
+
"minimax-m3",
|
|
411
|
+
"doubao-seed-2.0-pro",
|
|
412
|
+
];
|
|
413
|
+
const VOLCENGINE_PLAN_INPUT_MODALITIES: Record<string, string[]> = {
|
|
414
|
+
"kimi-k2.6": ["text", "image"],
|
|
415
|
+
"minimax-m3": ["text", "image"],
|
|
416
|
+
};
|
|
417
|
+
// Every other Plan model is text-only. Declaring this explicitly keeps the vision
|
|
418
|
+
// sidecar from advertising image input for models that cannot accept it — the same
|
|
419
|
+
// treatment tencent-coding-plan gives its (entirely text-only) plan catalog.
|
|
420
|
+
const VOLCENGINE_PLAN_TEXT_ONLY_MODELS = [
|
|
421
|
+
"ark-code-latest",
|
|
422
|
+
"doubao-seed-2.0-code",
|
|
423
|
+
"deepseek-v4-pro",
|
|
424
|
+
"deepseek-v4-flash",
|
|
425
|
+
"glm-5.2",
|
|
426
|
+
"doubao-seed-2.0-pro",
|
|
427
|
+
];
|
|
428
|
+
const ALIBABA_INTL_TOKEN_PLAN_INPUT_MODALITIES: Record<string, string[]> = {
|
|
429
|
+
"qwen3.8-max-preview": ["text", "image"],
|
|
430
|
+
"qwen3.7-max": ["text", "image"],
|
|
431
|
+
"qwen3.7-plus": ["text", "image"],
|
|
432
|
+
"qwen3.6-plus": ["text", "image"],
|
|
433
|
+
"qwen3.6-flash": ["text", "image"],
|
|
434
|
+
"deepseek-v4-pro": ["text"],
|
|
435
|
+
"deepseek-v4-flash": ["text"],
|
|
436
|
+
"deepseek-v3.2": ["text"],
|
|
437
|
+
"kimi-k2.7-code": ["text", "image"],
|
|
438
|
+
"kimi-k2.6": ["text", "image"],
|
|
439
|
+
"kimi-k2.5": ["text", "image"],
|
|
440
|
+
"glm-5.2": ["text"],
|
|
441
|
+
"glm-5.1": ["text"],
|
|
442
|
+
"glm-5": ["text"],
|
|
443
|
+
"MiniMax-M2.5": ["text"],
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
// 260717 Kimi K3: the subscription endpoint uses one upstream id (`k3`) for both
|
|
447
|
+
// entitlement tiers. Bare `k3` advertises the Moderato 256K ceiling; the local `[1m]`
|
|
448
|
+
// alias advertises Allegretto's 1M ceiling and is stripped before the upstream request.
|
|
449
|
+
// The separately billed Moonshot API uses `kimi-k3`.
|
|
450
|
+
// Evidence: https://www.kimi.com/code/docs/en/kimi-code/models.html
|
|
451
|
+
// https://www.kimi.com/code/docs/en/kimi-code/error-reference.html
|
|
452
|
+
const KIMI_K3_STANDARD_CONTEXT_WINDOW = 262_144;
|
|
453
|
+
const KIMI_K3_1M_CONTEXT_WINDOW = 1_048_576;
|
|
454
|
+
const KIMI_CODING_K3_MODELS = ["k3", "k3[1m]"];
|
|
455
|
+
const KIMI_LEGACY_API_MODELS = ["kimi-k2.7-code", "kimi-k2.7-code-highspeed", "kimi-k2.6", "kimi-k2.5"];
|
|
456
|
+
const KIMI_API_MODELS = ["kimi-k3", ...KIMI_LEGACY_API_MODELS];
|
|
457
|
+
const KIMI_CODING_MODELS = [...KIMI_CODING_K3_MODELS, ...KIMI_LEGACY_API_MODELS, "kimi-for-coding"];
|
|
458
|
+
const KIMI_THINKING_MODELS = KIMI_CODING_MODELS;
|
|
459
|
+
const KIMI_CODING_NO_REASONING_MODELS = KIMI_CODING_MODELS.filter(id => !KIMI_CODING_K3_MODELS.includes(id));
|
|
460
|
+
const KIMI_API_NO_REASONING_MODELS = KIMI_API_MODELS.filter(id => id !== "kimi-k3");
|
|
461
|
+
const KIMI_CODING_K3_REASONING_EFFORTS = ["low", "high", "max"];
|
|
462
|
+
const KIMI_CODING_K3_REASONING_EFFORT_MAP: Record<string, string> = {
|
|
463
|
+
none: "none",
|
|
464
|
+
low: "low",
|
|
465
|
+
medium: "high",
|
|
466
|
+
high: "high",
|
|
467
|
+
xhigh: "max",
|
|
468
|
+
max: "max",
|
|
469
|
+
};
|
|
470
|
+
const KIMI_CODING_REASONING_EFFORTS = Object.fromEntries(
|
|
471
|
+
KIMI_CODING_MODELS.map(id => [id, KIMI_CODING_K3_MODELS.includes(id) ? KIMI_CODING_K3_REASONING_EFFORTS : []]),
|
|
472
|
+
);
|
|
473
|
+
const KIMI_CODING_DEFAULT_REASONING_EFFORTS = Object.fromEntries(
|
|
474
|
+
KIMI_CODING_K3_MODELS.map(id => [id, "max"]),
|
|
475
|
+
);
|
|
476
|
+
const KIMI_CODING_REASONING_EFFORT_MAPS = Object.fromEntries(
|
|
477
|
+
KIMI_CODING_K3_MODELS.map(id => [id, KIMI_CODING_K3_REASONING_EFFORT_MAP]),
|
|
478
|
+
);
|
|
479
|
+
const KIMI_API_REASONING_EFFORTS = Object.fromEntries(
|
|
480
|
+
KIMI_API_MODELS.map(id => [id, id === "kimi-k3" ? ["max"] : []]),
|
|
481
|
+
);
|
|
482
|
+
const KIMI_LOCKED_PARAMETER_MODELS = KIMI_CODING_MODELS;
|
|
483
|
+
const KIMI_AUTO_TOOL_CHOICE_ONLY_MODELS = ["kimi-k2.7-code", "kimi-k2.7-code-highspeed", "kimi-for-coding"];
|
|
484
|
+
const KIMI_API_MODEL_CONTEXT_WINDOWS: Record<string, number> = Object.fromEntries(
|
|
485
|
+
KIMI_API_MODELS.map(id => [id, id === "kimi-k3" ? KIMI_K3_1M_CONTEXT_WINDOW : 262_144]),
|
|
486
|
+
);
|
|
487
|
+
const KIMI_API_MODEL_INPUT_MODALITIES = { "kimi-k3": ["text", "image"] };
|
|
488
|
+
|
|
489
|
+
// 260715 NVIDIA NIM kimi family (issue #126): documented served ids on integrate
|
|
490
|
+
// chat/completions per docs.api.nvidia.com/nim/reference/llm-apis; live /v1/models
|
|
491
|
+
// currently lists only kimi-k2.6 but the list is dynamic, so carry the documented family.
|
|
492
|
+
const NVIDIA_NIM_KIMI_THINKING_MODELS = [
|
|
493
|
+
"moonshotai/kimi-k2.6", "moonshotai/kimi-k2.5", "moonshotai/kimi-k2-thinking",
|
|
494
|
+
];
|
|
495
|
+
const NVIDIA_NIM_KIMI_MODELS = [
|
|
496
|
+
...NVIDIA_NIM_KIMI_THINKING_MODELS,
|
|
497
|
+
"moonshotai/kimi-k2-instruct", "moonshotai/kimi-k2-instruct-0905",
|
|
498
|
+
];
|
|
499
|
+
const KIMI_CODING_MODEL_CONTEXT_WINDOWS: Record<string, number> = Object.fromEntries(
|
|
500
|
+
KIMI_CODING_MODELS.map(id => [id, id === "k3[1m]" ? KIMI_K3_1M_CONTEXT_WINDOW : KIMI_K3_STANDARD_CONTEXT_WINDOW]),
|
|
501
|
+
);
|
|
502
|
+
const KIMI_CODING_MODEL_INPUT_MODALITIES = Object.fromEntries(
|
|
503
|
+
KIMI_CODING_K3_MODELS.map(id => [id, ["text", "image"]]),
|
|
504
|
+
);
|
|
505
|
+
const NEURALWATT_REASONING_HISTORY_MODELS = [
|
|
506
|
+
"glm-5.2", "glm-5.2-short",
|
|
507
|
+
"kimi-k2.6", "kimi-k2.7-code",
|
|
508
|
+
"qwen3.5-397b", "qwen3.6-35b",
|
|
509
|
+
];
|
|
510
|
+
|
|
511
|
+
// 260728 Baseten Model APIs: `/v1/models` owns the live lineup, while these hints
|
|
512
|
+
// describe only capabilities that Baseten documents per slug. Unlisted live models
|
|
513
|
+
// intentionally inherit the empty provider ladder instead of being advertised with
|
|
514
|
+
// opencodex's generic reasoning defaults. Audio is omitted because the current proxy
|
|
515
|
+
// request model does not carry OpenAI `audio_url` parts.
|
|
516
|
+
// Evidence: https://docs.baseten.co/inference/model-apis/reasoning
|
|
517
|
+
// https://docs.baseten.co/inference/model-apis/vision
|
|
518
|
+
const BASETEN_FULL_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
519
|
+
const BASETEN_MODEL_REASONING_EFFORTS: Record<string, string[]> = {
|
|
520
|
+
"deepseek-ai/DeepSeek-V4-Pro": BASETEN_FULL_REASONING_EFFORTS,
|
|
521
|
+
"thinkingmachines/inkling": BASETEN_FULL_REASONING_EFFORTS,
|
|
522
|
+
"openai/gpt-oss-120b": BASETEN_FULL_REASONING_EFFORTS,
|
|
523
|
+
"moonshotai/Kimi-K3": ["low", "high", "max"],
|
|
524
|
+
"zai-org/GLM-5.2": ["high", "max"],
|
|
525
|
+
"zai-org/GLM-5.2-Fast": ["high", "max"],
|
|
526
|
+
};
|
|
527
|
+
const BASETEN_MODEL_REASONING_EFFORT_MAP: Record<string, Record<string, string>> = {
|
|
528
|
+
"deepseek-ai/DeepSeek-V4-Pro": { none: "none", minimal: "minimal" },
|
|
529
|
+
"thinkingmachines/inkling": { none: "none", minimal: "minimal" },
|
|
530
|
+
"openai/gpt-oss-120b": { none: "none", minimal: "minimal" },
|
|
531
|
+
"moonshotai/Kimi-K3": { none: "none" },
|
|
532
|
+
"zai-org/GLM-5.2": { none: "none" },
|
|
533
|
+
"zai-org/GLM-5.2-Fast": { none: "none" },
|
|
534
|
+
};
|
|
535
|
+
const BASETEN_MODEL_DEFAULT_REASONING_EFFORTS: Record<string, string> = {
|
|
536
|
+
"deepseek-ai/DeepSeek-V4-Pro": "medium",
|
|
537
|
+
"thinkingmachines/inkling": "high",
|
|
538
|
+
"openai/gpt-oss-120b": "medium",
|
|
539
|
+
"moonshotai/Kimi-K3": "max",
|
|
540
|
+
};
|
|
541
|
+
const BASETEN_MODEL_INPUT_MODALITIES: Record<string, string[]> = {
|
|
542
|
+
"thinkingmachines/inkling": ["text", "image"],
|
|
543
|
+
"moonshotai/Kimi-K2.6": ["text", "image"],
|
|
544
|
+
"moonshotai/Kimi-K2.7-Code": ["text", "image"],
|
|
545
|
+
"moonshotai/Kimi-K3": ["text", "image"],
|
|
546
|
+
};
|
|
547
|
+
const UMANS_MODELS = [
|
|
548
|
+
"umans-coder",
|
|
549
|
+
"umans-kimi-k2.7",
|
|
550
|
+
"umans-flash",
|
|
551
|
+
"umans-glm-5.2",
|
|
552
|
+
"umans-glm-5.1",
|
|
553
|
+
"umans-qwen3.6-35b-a3b",
|
|
554
|
+
];
|
|
555
|
+
const UMANS_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
556
|
+
const UMANS_GLM_REASONING_EFFORTS = ["high", "xhigh", "max"];
|
|
557
|
+
const UMANS_TEXT_ONLY_MODELS = ["umans-glm-5.2", "umans-glm-5.1"];
|
|
558
|
+
const UMANS_MODEL_CONTEXT_WINDOWS: Record<string, number> = {
|
|
559
|
+
"umans-coder": 262_144,
|
|
560
|
+
"umans-kimi-k2.7": 262_144,
|
|
561
|
+
"umans-flash": 262_144,
|
|
562
|
+
"umans-glm-5.2": 405_504,
|
|
563
|
+
"umans-glm-5.1": 202_752,
|
|
564
|
+
"umans-qwen3.6-35b-a3b": 262_144,
|
|
565
|
+
};
|
|
566
|
+
const UMANS_MODEL_INPUT_MODALITIES: Record<string, string[]> = Object.fromEntries(
|
|
567
|
+
UMANS_MODELS.map(id => [id, UMANS_TEXT_ONLY_MODELS.includes(id) ? ["text"] : ["text", "image"]]),
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
571
|
+
{
|
|
572
|
+
id: "openai",
|
|
573
|
+
label: "OpenAI (Codex login)",
|
|
574
|
+
adapter: "openai-responses",
|
|
575
|
+
baseUrl: "https://chatgpt.com/backend-api/codex",
|
|
576
|
+
authKind: "forward",
|
|
577
|
+
codexAccountMode: "pool",
|
|
578
|
+
featured: true,
|
|
579
|
+
note: "Codex login account pool (default) or Direct main-account mode via codexAccountMode",
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
id: "cursor",
|
|
583
|
+
label: "Cursor (experimental)",
|
|
584
|
+
adapter: "cursor",
|
|
585
|
+
baseUrl: "https://api2.cursor.sh",
|
|
586
|
+
authKind: "oauth",
|
|
587
|
+
featured: false,
|
|
588
|
+
dashboardPreset: true,
|
|
589
|
+
note: "Experimental Cursor bridge. Live transport and live model discovery are enabled after a standalone PKCE browser login via 'ocx login cursor'; native read/write/delete/shell/fetch execution is disabled by default and request text such as Codex sandbox markers never authorizes it. Set \"nativeLocalExec\": \"on\" on providers.cursor in ~/.opencodex/config.json (dashboard: Providers → Cursor → Edit JSON) only for a trusted local experiment where every data-plane caller is trusted. \"off\" denies all, \"codex-sandbox\" is accepted for backwards compatibility but fails closed, and legacy \"unsafeAllowNativeLocalExec\": true still means explicit operator opt-in.",
|
|
590
|
+
models: cursorModelIds(CURSOR_STATIC_MODELS),
|
|
591
|
+
liveModels: true,
|
|
592
|
+
defaultModel: "auto",
|
|
593
|
+
modelContextWindows: cursorModelContextWindows(CURSOR_STATIC_MODELS),
|
|
594
|
+
modelInputModalities: cursorModelInputModalities(CURSOR_STATIC_MODELS),
|
|
595
|
+
modelReasoningEfforts: cursorModelReasoningEfforts(CURSOR_STATIC_MODELS),
|
|
596
|
+
// Kimi K3 documents `max` as its API default, and its Cursor ladder has no `medium`
|
|
597
|
+
// rung — so applyReasoningLevels' medium->high->first fallback would settle the catalog
|
|
598
|
+
// default on `high`, the picker would send `high` explicitly, and the request builder's
|
|
599
|
+
// no-effort fallback to `kimi-k3-max` would never be reached. Mirrors the other K3
|
|
600
|
+
// routes (kimi, kimi-code, opencode-go).
|
|
601
|
+
modelDefaultReasoningEfforts: { "kimi-k3": "max" },
|
|
602
|
+
// Cursor's wire protocol never forwards image parts (request-builder emits an unsupported-
|
|
603
|
+
// content marker), so the vision sidecar covers ALL cursor models regardless of what the
|
|
604
|
+
// upstream model could natively do. Live-discovered models outside the static list fall back
|
|
605
|
+
// to the same marker until they appear here.
|
|
606
|
+
noVisionModels: cursorModelIds(CURSOR_STATIC_MODELS),
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
id: "xai",
|
|
610
|
+
label: "xAI Grok",
|
|
611
|
+
adapter: "openai-chat",
|
|
612
|
+
baseUrl: "https://api.x.ai/v1",
|
|
613
|
+
authKind: "oauth",
|
|
614
|
+
allowKeyAuthOverride: true,
|
|
615
|
+
featured: true,
|
|
616
|
+
oauthId: "xai",
|
|
617
|
+
jawcodeBundle: "xai",
|
|
618
|
+
note: "Log in with your Grok account",
|
|
619
|
+
// Parallel tool calls: officially supported and default-on per docs.x.ai function-calling
|
|
620
|
+
// (verified 260709, devlog/_plan/260709_parallel_tool_calls). Streamed calls arrive whole
|
|
621
|
+
// per chunk, so the buffered parser assembles them losslessly.
|
|
622
|
+
parallelToolCalls: true,
|
|
623
|
+
// Live /v1/models discovery is the authoritative lineup (verified 260709: returns grok-4.5);
|
|
624
|
+
// the static list below is the logged-out fallback seed.
|
|
625
|
+
liveModels: true,
|
|
626
|
+
// 260709 refresh: lineup + metadata from official docs.x.ai (grok-4.5 announced 07-08);
|
|
627
|
+
// grok-composer-2.5-fast kept as account-verified (absent from public docs). Evidence:
|
|
628
|
+
// devlog/model_update/260709_model_refresh/001_xai_lineup.md.
|
|
629
|
+
// grok-4.20-multi-agent-0309 is intentionally absent: the OAuth chat-completions
|
|
630
|
+
// transport returns 400 ("Multi Agent requests are not allowed on chat completions").
|
|
631
|
+
models: ["grok-4.5", "grok-4.3", "grok-4.20-0309-reasoning", "grok-4.20-0309-non-reasoning", "grok-build-0.1", "grok-composer-2.5-fast"],
|
|
632
|
+
defaultModel: "grok-4.5",
|
|
633
|
+
// Vision lineup per docs.x.ai model-capabilities/images/understanding: the grok-4.x chat
|
|
634
|
+
// models accept image input (JPEG/PNG, URL or base64). Without this the catalog leaves
|
|
635
|
+
// inputModalities undefined, and deriveComboCatalogModel defaults an undefined member to
|
|
636
|
+
// ["text"] — so any combo containing an xAI target is advertised to Codex as text-only and
|
|
637
|
+
// the app blocks attachments client-side. grok-build-0.1 / grok-composer-2.5-fast stay out
|
|
638
|
+
// (they are already listed in noVisionModels below).
|
|
639
|
+
modelInputModalities: {
|
|
640
|
+
"grok-4.5": ["text", "image"],
|
|
641
|
+
"grok-4.3": ["text", "image"],
|
|
642
|
+
"grok-4.20-0309-reasoning": ["text", "image"],
|
|
643
|
+
"grok-4.20-0309-non-reasoning": ["text", "image"],
|
|
644
|
+
},
|
|
645
|
+
noReasoningModels: ["grok-4.20-0309-non-reasoning", "grok-build-0.1", "grok-composer-2.5-fast"],
|
|
646
|
+
// Replay assistant reasoning_content for grok reasoning models: xAI documents dropped
|
|
647
|
+
// reasoning_content as the top cause of prompt-cache misses on multi-turn conversations
|
|
648
|
+
// (docs.x.ai prompt-caching/multi-turn, verified 2026-07-13 — devlog/_plan/260713_grok_caching).
|
|
649
|
+
// Models that never emit reasoning simply have no thinking parts to replay (no-op).
|
|
650
|
+
preserveReasoningContentModels: ["grok-4.5", "grok-4.3", "grok-4.20-0309-reasoning"],
|
|
651
|
+
// grok-4.5 reasoning is always-on with low/medium/high control (no off tier upstream).
|
|
652
|
+
modelReasoningEfforts: { "grok-4.5": ["low", "medium", "high"] },
|
|
653
|
+
modelContextWindows: {
|
|
654
|
+
"grok-4.5": 500_000,
|
|
655
|
+
"grok-4.3": 1_000_000,
|
|
656
|
+
"grok-4.20-0309-reasoning": 1_000_000,
|
|
657
|
+
"grok-4.20-0309-non-reasoning": 1_000_000,
|
|
658
|
+
"grok-build-0.1": 256_000,
|
|
659
|
+
},
|
|
660
|
+
noVisionModels: ["grok-build-0.1", "grok-composer-2.5-fast"],
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
id: "anthropic",
|
|
664
|
+
label: "Anthropic Claude",
|
|
665
|
+
adapter: "anthropic",
|
|
666
|
+
baseUrl: "https://api.anthropic.com",
|
|
667
|
+
authKind: "oauth",
|
|
668
|
+
featured: true,
|
|
669
|
+
oauthId: "anthropic",
|
|
670
|
+
jawcodeBundle: "anthropic",
|
|
671
|
+
note: "Log in with your Claude account",
|
|
672
|
+
models: [...ANTHROPIC_MODELS],
|
|
673
|
+
modelContextWindows: { ...ANTHROPIC_MODEL_CONTEXT_WINDOWS },
|
|
674
|
+
defaultModel: "claude-sonnet-5",
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
id: "anthropic-apikey",
|
|
678
|
+
label: "Anthropic (API key)",
|
|
679
|
+
adapter: "anthropic",
|
|
680
|
+
baseUrl: "https://api.anthropic.com",
|
|
681
|
+
authKind: "key",
|
|
682
|
+
featured: true,
|
|
683
|
+
dashboardUrl: "https://console.anthropic.com/settings/keys",
|
|
684
|
+
jawcodeBundle: "anthropic",
|
|
685
|
+
extraMetadataAliases: ["anthropic-key"],
|
|
686
|
+
note: "Direct Anthropic API billing — no Claude subscription",
|
|
687
|
+
models: [...ANTHROPIC_MODELS],
|
|
688
|
+
liveModels: true,
|
|
689
|
+
modelContextWindows: { ...ANTHROPIC_MODEL_CONTEXT_WINDOWS },
|
|
690
|
+
defaultModel: "claude-sonnet-5",
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
id: "kimi",
|
|
694
|
+
label: "Kimi",
|
|
695
|
+
adapter: "openai-chat",
|
|
696
|
+
baseUrl: "https://api.kimi.com/coding/v1",
|
|
697
|
+
authKind: "oauth",
|
|
698
|
+
modelSuffixBracketStrip: true,
|
|
699
|
+
// Kimi Code Plan documents a stable session/task prompt_cache_key as required to improve
|
|
700
|
+
// cache hit rates.
|
|
701
|
+
// The chat adapter only forwards a key already on the internal request (Codex's session key,
|
|
702
|
+
// or the one the Claude /v1/messages inbound derives); the adapter itself never invents one.
|
|
703
|
+
// Evidence: https://platform.kimi.com/docs/api/chat
|
|
704
|
+
promptCacheKey: true,
|
|
705
|
+
featured: true,
|
|
706
|
+
oauthId: "kimi",
|
|
707
|
+
jawcodeBundle: "moonshot",
|
|
708
|
+
note: "Log in with your Kimi account",
|
|
709
|
+
models: KIMI_CODING_MODELS,
|
|
710
|
+
defaultModel: "kimi-k2.7-code",
|
|
711
|
+
modelContextWindows: KIMI_CODING_MODEL_CONTEXT_WINDOWS,
|
|
712
|
+
modelInputModalities: KIMI_CODING_MODEL_INPUT_MODALITIES,
|
|
713
|
+
// K3 accepts low/high/max; Codex aliases are normalized by the model-scoped wire map.
|
|
714
|
+
noReasoningModels: KIMI_CODING_NO_REASONING_MODELS,
|
|
715
|
+
modelReasoningEfforts: KIMI_CODING_REASONING_EFFORTS,
|
|
716
|
+
modelDefaultReasoningEfforts: KIMI_CODING_DEFAULT_REASONING_EFFORTS,
|
|
717
|
+
modelReasoningEffortMap: KIMI_CODING_REASONING_EFFORT_MAPS,
|
|
718
|
+
noTemperatureModels: KIMI_LOCKED_PARAMETER_MODELS,
|
|
719
|
+
noTopPModels: KIMI_LOCKED_PARAMETER_MODELS,
|
|
720
|
+
noPenaltyModels: KIMI_LOCKED_PARAMETER_MODELS,
|
|
721
|
+
autoToolChoiceOnlyModels: KIMI_AUTO_TOOL_CHOICE_ONLY_MODELS,
|
|
722
|
+
preserveReasoningContentModels: KIMI_THINKING_MODELS,
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
id: "kiro",
|
|
726
|
+
label: "Kiro (AWS CodeWhisperer)",
|
|
727
|
+
adapter: "kiro",
|
|
728
|
+
baseUrl: "https://runtime.us-east-1.kiro.dev",
|
|
729
|
+
authKind: "oauth",
|
|
730
|
+
oauthId: "kiro",
|
|
731
|
+
note: "Import-first: reuses your installed and signed-in Kiro CLI session (requires `kiro-cli login`). Add account logs `kiro-cli` out, switches it through a fresh browser login, stores the account by profile ARN, and restores the previous CLI session on cancellation or failure. Experimental third-party harness — see Kiro ToS.",
|
|
732
|
+
models: KIRO_MODELS,
|
|
733
|
+
defaultModel: "kiro-auto",
|
|
734
|
+
// Kiro speaks CodeWhisperer wire, not OpenAI-style GET /models. Keep the static
|
|
735
|
+
// catalog authoritative so a spurious 2xx from runtime.../models cannot drop seeded ids
|
|
736
|
+
// (e.g. newly listed GPT-5.6 tiers) via live-discovery reconciliation.
|
|
737
|
+
liveModels: false,
|
|
738
|
+
// Per-model context metadata is maintained next to the Kiro model list.
|
|
739
|
+
modelContextWindows: KIRO_MODEL_CONTEXT_WINDOWS,
|
|
740
|
+
modelReasoningEfforts: KIRO_MODEL_REASONING_EFFORTS,
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
id: "openai-apikey",
|
|
744
|
+
label: "OpenAI API",
|
|
745
|
+
adapter: "openai-responses",
|
|
746
|
+
baseUrl: "https://api.openai.com/v1",
|
|
747
|
+
authKind: "key",
|
|
748
|
+
featured: true,
|
|
749
|
+
dashboardUrl: "https://platform.openai.com/api-keys",
|
|
750
|
+
defaultModel: "gpt-5.5",
|
|
751
|
+
models: ["gpt-5.5", ...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS],
|
|
752
|
+
liveModels: true,
|
|
753
|
+
modelContextWindows: OPENAI_API_GPT56_CONTEXT_WINDOWS,
|
|
754
|
+
modelMaxInputTokens: OPENAI_API_GPT56_MAX_INPUT_TOKENS,
|
|
755
|
+
modelInputModalities: Object.fromEntries(
|
|
756
|
+
["gpt-5.5", ...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS].map(id => [id, ["text", "image"]]),
|
|
757
|
+
),
|
|
758
|
+
modelReasoningEfforts: Object.fromEntries(
|
|
759
|
+
[...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS].map(id => [id, OPENAI_API_GPT56_REASONING_EFFORTS]),
|
|
760
|
+
),
|
|
761
|
+
virtualModels: OPENAI_API_GPT56_VIRTUAL_MODELS,
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
id: "umans",
|
|
765
|
+
label: "Umans AI Coding Plan",
|
|
766
|
+
adapter: "anthropic",
|
|
767
|
+
baseUrl: "https://api.code.umans.ai",
|
|
768
|
+
authKind: "key",
|
|
769
|
+
featured: true,
|
|
770
|
+
dashboardUrl: "https://app.umans.ai/billing",
|
|
771
|
+
defaultModel: "umans-coder",
|
|
772
|
+
models: UMANS_MODELS,
|
|
773
|
+
modelContextWindows: UMANS_MODEL_CONTEXT_WINDOWS,
|
|
774
|
+
modelInputModalities: UMANS_MODEL_INPUT_MODALITIES,
|
|
775
|
+
note: "Coding plan via Anthropic Messages",
|
|
776
|
+
modelReasoningEfforts: {
|
|
777
|
+
"umans-coder": UMANS_REASONING_EFFORTS,
|
|
778
|
+
"umans-kimi-k2.7": UMANS_REASONING_EFFORTS,
|
|
779
|
+
"umans-flash": UMANS_REASONING_EFFORTS,
|
|
780
|
+
"umans-glm-5.2": UMANS_GLM_REASONING_EFFORTS,
|
|
781
|
+
"umans-glm-5.1": UMANS_GLM_REASONING_EFFORTS,
|
|
782
|
+
"umans-qwen3.6-35b-a3b": UMANS_REASONING_EFFORTS,
|
|
783
|
+
},
|
|
784
|
+
noVisionModels: UMANS_TEXT_ONLY_MODELS,
|
|
785
|
+
escapeBuiltinToolNames: true,
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
id: "opencode-go", label: "opencode go", adapter: "openai-chat", baseUrl: "https://opencode.ai/zen/go/v1",
|
|
789
|
+
authKind: "key", featured: true, dashboardUrl: "https://opencode.ai/auth", defaultModel: "kimi-k2.7-code",
|
|
790
|
+
jawcodeBundle: "opencode-go", note: "GLM, DeepSeek, Kimi, Qwen, MiMo…",
|
|
791
|
+
modelContextWindows: { "kimi-k3": KIMI_K3_STANDARD_CONTEXT_WINDOW },
|
|
792
|
+
modelInputModalities: { "kimi-k3": ["text", "image"] },
|
|
793
|
+
modelReasoningEfforts: {
|
|
794
|
+
"glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
|
|
795
|
+
"kimi-k3": KIMI_CODING_K3_REASONING_EFFORTS,
|
|
796
|
+
"kimi-k2.7-code": [],
|
|
797
|
+
"kimi-k2.7-code-highspeed": [],
|
|
798
|
+
...Object.fromEntries(OPENCODE_GO_THINKING_TOGGLE_MODELS.map(id => [id, THINKING_TOGGLE_EFFORTS])),
|
|
799
|
+
...Object.fromEntries(OPENCODE_GO_THINKING_BUDGET_MODELS.map(id => [id, THINKING_BUDGET_EFFORTS])),
|
|
800
|
+
...Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id, DEEPSEEK_THINKING_EFFORTS])),
|
|
801
|
+
},
|
|
802
|
+
modelDefaultReasoningEfforts: { "kimi-k3": "max" },
|
|
803
|
+
// glm-5.2 uses identity labels now that `max` is a native Codex level (no alias map);
|
|
804
|
+
// the thinking-toggle map is a REAL wire alias (effort -> enabled/disabled) and stays.
|
|
805
|
+
modelReasoningEffortMap: {
|
|
806
|
+
"kimi-k3": KIMI_CODING_K3_REASONING_EFFORT_MAP,
|
|
807
|
+
...Object.fromEntries(OPENCODE_GO_THINKING_TOGGLE_MODELS.map(id => [id, THINKING_TOGGLE_MAP])),
|
|
808
|
+
...Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id, DEEPSEEK_THINKING_REASONING_MAP])),
|
|
809
|
+
},
|
|
810
|
+
thinkingToggleModels: OPENCODE_GO_THINKING_TOGGLE_MODELS,
|
|
811
|
+
thinkingBudgetModels: THINKING_BUDGET_MODELS,
|
|
812
|
+
noReasoningModels: ["kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
|
|
813
|
+
// Text-only Zen Go models (jawcode metadata) — the vision sidecar describes images for
|
|
814
|
+
// every model listed here (and the catalog advertises image input on their behalf).
|
|
815
|
+
// Kimi K2.7 Code accepts text+image+video: do NOT list it here.
|
|
816
|
+
noVisionModels: [
|
|
817
|
+
"glm-5.2", "glm-5", "glm-5.1",
|
|
818
|
+
"deepseek-v4-flash", "deepseek-v4-pro",
|
|
819
|
+
"mimo-v2-pro", "mimo-v2.5-pro",
|
|
820
|
+
"minimax-m2.5", "minimax-m2.7",
|
|
821
|
+
"qwen3.7-max",
|
|
822
|
+
],
|
|
823
|
+
noTemperatureModels: ["kimi-k3", "kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
|
|
824
|
+
noTopPModels: ["kimi-k3", "kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
|
|
825
|
+
noPenaltyModels: ["kimi-k3", "kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
|
|
826
|
+
autoToolChoiceOnlyModels: ["kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
|
|
827
|
+
// Issue #78: DeepSeek V4 thinking mode requires reasoning_content replay on tool-call turns.
|
|
828
|
+
preserveReasoningContentModels: ["glm-5.2", "kimi-k3", "kimi-k2.7-code", "kimi-k2.7-code-highspeed", ...DEEPSEEK_THINKING_MODELS],
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
id: "neuralwatt",
|
|
832
|
+
label: "Neuralwatt Cloud",
|
|
833
|
+
adapter: "openai-chat",
|
|
834
|
+
baseUrl: "https://api.neuralwatt.com/v1",
|
|
835
|
+
authKind: "key",
|
|
836
|
+
dashboardUrl: "https://portal.neuralwatt.com",
|
|
837
|
+
defaultModel: "glm-5.2",
|
|
838
|
+
// 2026-07-10 live /v1/models: K2.5 rows were removed and GLM-5.2 short variants added.
|
|
839
|
+
// Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md and https://api.neuralwatt.com/v1/models.
|
|
840
|
+
models: [
|
|
841
|
+
"glm-5.2", "glm-5.2-fast", "glm-5.2-short", "glm-5.2-short-fast",
|
|
842
|
+
"kimi-k2.6", "kimi-k2.6-fast",
|
|
843
|
+
"kimi-k2.7-code",
|
|
844
|
+
"qwen3.5-397b", "qwen3.5-397b-fast", "qwen3.6-35b", "qwen3.6-35b-fast",
|
|
845
|
+
],
|
|
846
|
+
// Neuralwatt's /v1/models metadata is authoritative; these static hints are the offline fallback.
|
|
847
|
+
modelReasoningEfforts: {
|
|
848
|
+
"glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
|
|
849
|
+
"glm-5.2-fast": [],
|
|
850
|
+
"glm-5.2-short": ZAI_GLM_52_REASONING_EFFORTS,
|
|
851
|
+
"glm-5.2-short-fast": [],
|
|
852
|
+
"kimi-k2.6": [],
|
|
853
|
+
"kimi-k2.6-fast": [],
|
|
854
|
+
"kimi-k2.7-code": [],
|
|
855
|
+
// Qwen3.x uses thinking_budget, NOT graded reasoning_effort; the adapter maps the five
|
|
856
|
+
// Codex picker levels onto budget fractions.
|
|
857
|
+
"qwen3.5-397b": THINKING_BUDGET_EFFORTS,
|
|
858
|
+
"qwen3.5-397b-fast": [],
|
|
859
|
+
"qwen3.6-35b": THINKING_BUDGET_EFFORTS,
|
|
860
|
+
"qwen3.6-35b-fast": [],
|
|
861
|
+
},
|
|
862
|
+
thinkingBudgetModels: THINKING_BUDGET_MODELS,
|
|
863
|
+
noReasoningModels: ["glm-5.2-fast", "glm-5.2-short-fast", "kimi-k2.6-fast", "qwen3.5-397b-fast", "qwen3.6-35b-fast"],
|
|
864
|
+
noVisionModels: ["glm-5.2", "glm-5.2-fast", "glm-5.2-short", "glm-5.2-short-fast", "qwen3.5-397b", "qwen3.5-397b-fast"],
|
|
865
|
+
noTemperatureModels: ["kimi-k2.7-code"],
|
|
866
|
+
noTopPModels: ["kimi-k2.7-code"],
|
|
867
|
+
noPenaltyModels: ["kimi-k2.7-code"],
|
|
868
|
+
autoToolChoiceOnlyModels: ["kimi-k2.7-code"],
|
|
869
|
+
preserveReasoningContentModels: NEURALWATT_REASONING_HISTORY_MODELS,
|
|
870
|
+
},
|
|
871
|
+
{ id: "openrouter", label: "OpenRouter", adapter: "openai-chat", baseUrl: "https://openrouter.ai/api/v1", authKind: "key", featured: true, dashboardUrl: "https://openrouter.ai/keys", jawcodeBundle: "openrouter", models: ["anthropic/claude-sonnet-5", ...OPENROUTER_GPT56_MODELS], modelContextWindows: { "anthropic/claude-sonnet-5": 1_000_000, ...OPENROUTER_GPT56_CONTEXT_WINDOWS } },
|
|
872
|
+
{
|
|
873
|
+
// OrcaRouter: OpenAI-compatible adaptive router (api.orcarouter.ai). Model ids are
|
|
874
|
+
// vendor-namespaced (`<vendor>/<model>`) and pass through to the upstream as-is.
|
|
875
|
+
// The default pins a tool-capable model; the adaptive `orcarouter/auto` router is also
|
|
876
|
+
// selectable. Live-verified 2026-07-20: /v1/chat/completions accepts the `tools` field
|
|
877
|
+
// and routes to a function-calling-capable upstream.
|
|
878
|
+
id: "orcarouter", label: "OrcaRouter", adapter: "openai-chat", baseUrl: "https://api.orcarouter.ai/v1",
|
|
879
|
+
authKind: "key", dashboardUrl: "https://www.orcarouter.ai/console",
|
|
880
|
+
defaultModel: "openai/gpt-5.5",
|
|
881
|
+
models: [
|
|
882
|
+
"openai/gpt-5.5",
|
|
883
|
+
"anthropic/claude-opus-4.8",
|
|
884
|
+
"google/gemini-3.5-flash",
|
|
885
|
+
"deepseek/deepseek-v4-pro",
|
|
886
|
+
"orcarouter/auto",
|
|
887
|
+
],
|
|
888
|
+
// Text-only models → the vision sidecar describes images instead.
|
|
889
|
+
noVisionModels: ["deepseek/deepseek-v4-pro"],
|
|
890
|
+
// Reasoning/temperature behavior verified live 2026-07-20 against api.orcarouter.ai:
|
|
891
|
+
// - openai/gpt-5.5 accepts reasoning_effort none|low|medium|high|xhigh but rejects `max` (400),
|
|
892
|
+
// so advertise up to xhigh and let mapReasoningEffort clamp a `max`/`ultra` request to xhigh.
|
|
893
|
+
// - deepseek/deepseek-v4-pro mirrors the direct-DeepSeek wiring (thinking-effort map +
|
|
894
|
+
// reasoning_content history replay) so the namespaced selection behaves identically.
|
|
895
|
+
// - temperature is accepted by every seeded model (gpt-5.5, claude-opus-4.8, deepseek-v4-pro all
|
|
896
|
+
// returned 200), so no noTemperatureModels entry is warranted here.
|
|
897
|
+
modelReasoningEfforts: {
|
|
898
|
+
"openai/gpt-5.5": ["low", "medium", "high", "xhigh"],
|
|
899
|
+
"deepseek/deepseek-v4-pro": DEEPSEEK_THINKING_EFFORTS,
|
|
900
|
+
},
|
|
901
|
+
modelReasoningEffortMap: { "deepseek/deepseek-v4-pro": DEEPSEEK_THINKING_REASONING_MAP },
|
|
902
|
+
preserveReasoningContentModels: ["deepseek/deepseek-v4-pro"],
|
|
903
|
+
note: "OpenAI-compatible adaptive router. Default is a tool-capable model; orcarouter/auto (adaptive routing) is also selectable. Full catalog: https://www.orcarouter.ai/models",
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
// BizRouter: Korean enterprise LLM gateway (api.bizrouter.ai). Model ids are
|
|
907
|
+
// vendor-namespaced (`<vendor>/<model>`) and pass through to the upstream as-is.
|
|
908
|
+
// Live-verified 2026-07-24: /v1/chat/completions accepts the `tools` field and
|
|
909
|
+
// streams, and GET /v1/models returns the per-API-key allowed catalog in the
|
|
910
|
+
// OpenAI list shape, so live model discovery narrows to what the key can use.
|
|
911
|
+
id: "bizrouter", label: "BizRouter", adapter: "openai-chat", baseUrl: "https://api.bizrouter.ai/v1",
|
|
912
|
+
authKind: "key", dashboardUrl: "https://bizrouter.ai/settings/keys",
|
|
913
|
+
defaultModel: "openai/gpt-5.6-sol",
|
|
914
|
+
models: ["openai/gpt-5.6-sol", "anthropic/claude-sonnet-5", "google/gemini-3.5-flash"],
|
|
915
|
+
note: "Korean enterprise LLM gateway. Per-key allowed models are discovered live from /v1/models. Full catalog: https://bizrouter.ai/models",
|
|
916
|
+
},
|
|
917
|
+
{ id: "groq", label: "Groq", adapter: "openai-chat", baseUrl: "https://api.groq.com/openai/v1", authKind: "key", featured: true, dashboardUrl: "https://console.groq.com/keys" },
|
|
918
|
+
// 2026-07-10 Gemini API refresh: Tier-2 ai.google.dev evidence recorded in
|
|
919
|
+
// devlog/_plan/260710_provider_hardening/001_research_frontier.md.
|
|
920
|
+
{
|
|
921
|
+
id: "google", label: "Google Gemini", adapter: "google", baseUrl: "https://generativelanguage.googleapis.com", authKind: "key", featured: true,
|
|
922
|
+
dashboardUrl: "https://aistudio.google.com/apikey", defaultModel: "gemini-3.5-flash", models: ["gemini-3.6-flash", "gemini-3.5-flash", "gemini-3.5-flash-lite", "gemini-3.1-pro-preview"],
|
|
923
|
+
modelContextWindows: { "gemini-3.6-flash": 1_048_576, "gemini-3.5-flash": 1_000_000, "gemini-3.5-flash-lite": 1_048_576 },
|
|
924
|
+
modelInputModalities: { "gemini-3.6-flash": ["text", "image"], "gemini-3.5-flash-lite": ["text", "image"] },
|
|
925
|
+
modelReasoningEfforts: {
|
|
926
|
+
"gemini-3.6-flash": ["minimal", "low", "medium", "high"],
|
|
927
|
+
"gemini-3.5-flash": ["minimal", "low", "medium", "high"],
|
|
928
|
+
"gemini-3.1-pro-preview": ["low", "medium", "high"],
|
|
929
|
+
},
|
|
930
|
+
jawcodeBundle: "google", extraMetadataAliases: ["gemini"],
|
|
931
|
+
},
|
|
932
|
+
// 2026-07-10: defaultModel is frozen pending Vertex-specific Tier-2 evidence; Gemini API
|
|
933
|
+
// evidence from ai.google.dev does not establish Vertex publisher availability.
|
|
934
|
+
{ id: "google-vertex", label: "Google Vertex AI", adapter: "google", baseUrl: "https://aiplatform.googleapis.com", authKind: "key", dashboardUrl: "https://console.cloud.google.com/vertex-ai", defaultModel: "gemini-3-pro", googleMode: "vertex", jawcodeBundle: "google", extraMetadataAliases: ["gemini-vertex"] },
|
|
935
|
+
{ id: "google-antigravity", label: "Google Antigravity", adapter: "google", baseUrl: "https://daily-cloudcode-pa.googleapis.com", authKind: "oauth", dashboardUrl: "https://antigravity.google", models: ANTIGRAVITY_MODELS, liveModels: false, defaultModel: "gemini-3.6-flash", modelContextWindows: ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, modelReasoningEfforts: ANTIGRAVITY_MODEL_EFFORTS, googleMode: "cloud-code-assist", jawcodeBundle: "google", extraMetadataAliases: ["antigravity", "gemini-antigravity"] },
|
|
936
|
+
{ id: "azure-openai", label: "Azure OpenAI", adapter: "azure-openai", baseUrl: "https://{resource}.openai.azure.com/openai", authKind: "key", featured: true, dashboardUrl: "https://portal.azure.com" },
|
|
937
|
+
{ id: "ollama", label: "Ollama (local)", adapter: "openai-chat", baseUrl: "http://localhost:11434/v1", authKind: "local", allowPrivateNetworkByDefault: true, allowBaseUrlOverride: true, featured: true, note: "Local — key usually blank" },
|
|
938
|
+
{ id: "vllm", label: "vLLM (local)", adapter: "openai-chat", baseUrl: "http://localhost:8000/v1", authKind: "local", allowPrivateNetworkByDefault: true, allowBaseUrlOverride: true, featured: true, note: "Local — key usually blank" },
|
|
939
|
+
{ id: "lm-studio", label: "LM Studio (local)", adapter: "openai-chat", baseUrl: "http://localhost:1234/v1", authKind: "local", allowPrivateNetworkByDefault: true, allowBaseUrlOverride: true, featured: true, note: "Local — no key needed" },
|
|
940
|
+
{
|
|
941
|
+
id: "deepseek",
|
|
942
|
+
label: "DeepSeek",
|
|
943
|
+
baseUrl: "https://api.deepseek.com",
|
|
944
|
+
adapter: "openai-chat",
|
|
945
|
+
authKind: "key",
|
|
946
|
+
dashboardUrl: "https://platform.deepseek.com/api_keys",
|
|
947
|
+
// deepseek-chat/deepseek-reasoner are upstream-deprecated at 2026-07-24 15:59 UTC;
|
|
948
|
+
// kept until then. Evidence: devlog/_plan/260710_provider_hardening/002_research_cn.md.
|
|
949
|
+
models: ["deepseek-chat", "deepseek-reasoner", ...DEEPSEEK_THINKING_MODELS],
|
|
950
|
+
defaultModel: "deepseek-v4-flash",
|
|
951
|
+
modelContextWindows: { "deepseek-v4-flash": 1_000_000, "deepseek-v4-pro": 1_000_000 },
|
|
952
|
+
// DeepSeek documents V4-Flash as a native Responses API model adapted for Codex. The
|
|
953
|
+
// API id is `deepseek-v4-flash`; `DeepSeek-V4-Flash-0731` is a release/version label.
|
|
954
|
+
modelWireDefaults: {
|
|
955
|
+
// Codex speaks Responses natively and DeepSeek ships a Codex-compatible
|
|
956
|
+
// apply_patch tool on that wire, so a Responses inbound goes straight out with
|
|
957
|
+
// no translation. Claude Code and OpenAI-compatible clients keep the
|
|
958
|
+
// provider-wide Chat wire: DeepSeek serves Chat Completions natively too, so
|
|
959
|
+
// translating them into Responses would add a hop onto our newest upstream path
|
|
960
|
+
// for no gain.
|
|
961
|
+
"deepseek-v4-flash": { wire: "openai-responses", inbound: ["responses"] },
|
|
962
|
+
},
|
|
963
|
+
// DeepSeek's Responses route is `POST /responses` with no `/v1` segment. Without
|
|
964
|
+
// this the passthrough adapter falls back to its legacy `/v1/responses`
|
|
965
|
+
// construction and the wire above can never route.
|
|
966
|
+
// Evidence: https://api-docs.deepseek.com/api/create-response/
|
|
967
|
+
responsesPath: "/responses",
|
|
968
|
+
// "The API is stateless: responses and conversations are not stored on the
|
|
969
|
+
// server." https://api-docs.deepseek.com/api/create-response/
|
|
970
|
+
statelessResponses: true,
|
|
971
|
+
/* [Decision Log]
|
|
972
|
+
- 목적: DeepSeek V4 thinking mode multi-turn/tool-call requests must replay prior assistant reasoning_content.
|
|
973
|
+
- 대안 분석: Globally preserve reasoning_content for all OpenAI-compatible models; preserve it for legacy deepseek-reasoner too; mark only V4 thinking models in registry metadata.
|
|
974
|
+
- 선택 근거: DeepSeek V4 thinking mode requires history replay, while older DeepSeek reasoner has different compatibility rules. A model-scoped registry flag fixes built-in and stale saved configs without broad provider regressions.
|
|
975
|
+
*/
|
|
976
|
+
modelReasoningEfforts: Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id, DEEPSEEK_THINKING_EFFORTS])),
|
|
977
|
+
modelReasoningEffortMap: Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id, DEEPSEEK_THINKING_REASONING_MAP])),
|
|
978
|
+
preserveReasoningContentModels: DEEPSEEK_THINKING_MODELS,
|
|
979
|
+
// Issue #88: every DeepSeek API model is text-only input (no image support upstream) — the
|
|
980
|
+
// vision sidecar describes attached images for them, and the catalog advertises image input
|
|
981
|
+
// on their behalf (same treatment as opencode-go's DeepSeek V4 entries above).
|
|
982
|
+
noVisionModels: ["deepseek-chat", "deepseek-reasoner", ...DEEPSEEK_THINKING_MODELS],
|
|
983
|
+
},
|
|
984
|
+
// llama-3.3-70b was deprecated by Cerebras on 2026-02-16. Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
|
|
985
|
+
{ id: "cerebras", label: "Cerebras", baseUrl: "https://api.cerebras.ai/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://cloud.cerebras.ai/platform/apikeys", defaultModel: "gpt-oss-120b" },
|
|
986
|
+
{
|
|
987
|
+
id: "deepinfra",
|
|
988
|
+
label: "DeepInfra",
|
|
989
|
+
baseUrl: "https://api.deepinfra.com/v1/openai",
|
|
990
|
+
adapter: "openai-chat",
|
|
991
|
+
authKind: "key",
|
|
992
|
+
dashboardUrl: "https://deepinfra.com/dash/api_keys",
|
|
993
|
+
liveModels: true,
|
|
994
|
+
preserveCustomDestination: true,
|
|
995
|
+
modelDiscovery: {
|
|
996
|
+
// DeepInfra documents the OpenAI model catalog outside the chat-compatible `/v1/openai`
|
|
997
|
+
// namespace, so keep this destination registry-owned instead of deriving it from baseUrl.
|
|
998
|
+
url: "https://api.deepinfra.com/v1/models",
|
|
999
|
+
maxResponseBytes: 512 * 1024,
|
|
1000
|
+
maxModels: 512,
|
|
1001
|
+
filter: {
|
|
1002
|
+
allOf: [{ path: ["metadata", "tags"], containsAny: ["chat"] }],
|
|
1003
|
+
},
|
|
1004
|
+
},
|
|
1005
|
+
note: "OpenAI-compatible chat models only; live discovery excludes non-chat rows from DeepInfra's mixed model catalog.",
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
id: "hyperbolic",
|
|
1009
|
+
label: "Hyperbolic",
|
|
1010
|
+
baseUrl: "https://api.hyperbolic.xyz/v1",
|
|
1011
|
+
adapter: "openai-chat",
|
|
1012
|
+
authKind: "key",
|
|
1013
|
+
dashboardUrl: "https://app.hyperbolic.ai",
|
|
1014
|
+
liveModels: true,
|
|
1015
|
+
preserveCustomDestination: true,
|
|
1016
|
+
modelDiscovery: {
|
|
1017
|
+
path: "models",
|
|
1018
|
+
maxResponseBytes: 256 * 1024,
|
|
1019
|
+
maxModels: 256,
|
|
1020
|
+
},
|
|
1021
|
+
note: "Serverless text and vision-language chat models only; Hyperbolic's separate image, audio, and GPU endpoints are out of scope.",
|
|
1022
|
+
},
|
|
1023
|
+
{
|
|
1024
|
+
id: "baseten",
|
|
1025
|
+
label: "Baseten Model APIs",
|
|
1026
|
+
baseUrl: "https://inference.baseten.co/v1",
|
|
1027
|
+
adapter: "openai-chat",
|
|
1028
|
+
authKind: "key",
|
|
1029
|
+
dashboardUrl: "https://app.baseten.co/settings/api_keys",
|
|
1030
|
+
liveModels: true,
|
|
1031
|
+
preserveCustomDestination: true,
|
|
1032
|
+
// Baseten's Chat Completions contract documents parallel_tool_calls as default-on.
|
|
1033
|
+
parallelToolCalls: true,
|
|
1034
|
+
// Baseten says models outside its reasoning table do not support reasoning. Keep
|
|
1035
|
+
// unknown/new live slugs conservative until an official-docs registry refresh proves it.
|
|
1036
|
+
reasoningEfforts: [],
|
|
1037
|
+
modelReasoningEfforts: BASETEN_MODEL_REASONING_EFFORTS,
|
|
1038
|
+
modelReasoningEffortMap: BASETEN_MODEL_REASONING_EFFORT_MAP,
|
|
1039
|
+
modelDefaultReasoningEfforts: BASETEN_MODEL_DEFAULT_REASONING_EFFORTS,
|
|
1040
|
+
modelInputModalities: BASETEN_MODEL_INPUT_MODALITIES,
|
|
1041
|
+
modelDiscovery: {
|
|
1042
|
+
path: "models",
|
|
1043
|
+
maxResponseBytes: 1_048_576,
|
|
1044
|
+
maxModels: 256,
|
|
1045
|
+
},
|
|
1046
|
+
note: "Shared Model APIs only (personal API key, or team key with Call Model APIs access); dedicated Truss predict endpoints are outside this preset.",
|
|
1047
|
+
},
|
|
1048
|
+
// FREEZE 2026-07-10: exact serverless ids remain auth-gated/unverified. Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
|
|
1049
|
+
{ id: "together", label: "Together", baseUrl: "https://api.together.xyz/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://api.together.xyz/settings/api-keys" },
|
|
1050
|
+
{ id: "fireworks", label: "Fireworks", baseUrl: "https://api.fireworks.ai/inference/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://fireworks.ai/account/api-keys" },
|
|
1051
|
+
{
|
|
1052
|
+
id: "firepass", label: "Fire Pass (Fireworks Kimi)", baseUrl: "https://api.fireworks.ai/inference/v1", adapter: "openai-chat", authKind: "key",
|
|
1053
|
+
dashboardUrl: "https://fireworks.ai/account/api-keys",
|
|
1054
|
+
note: "Model data frozen pending Tier-2 entitlement proof",
|
|
1055
|
+
},
|
|
1056
|
+
{
|
|
1057
|
+
id: "moonshot", label: "Moonshot (Kimi API)", baseUrl: "https://api.moonshot.ai/v1", adapter: "openai-chat", authKind: "key",
|
|
1058
|
+
dashboardUrl: "https://platform.moonshot.ai/console/api-keys", defaultModel: "kimi-k2.7-code", jawcodeBundle: "moonshot",
|
|
1059
|
+
models: KIMI_API_MODELS,
|
|
1060
|
+
modelContextWindows: KIMI_API_MODEL_CONTEXT_WINDOWS,
|
|
1061
|
+
modelInputModalities: KIMI_API_MODEL_INPUT_MODALITIES,
|
|
1062
|
+
noReasoningModels: KIMI_API_NO_REASONING_MODELS,
|
|
1063
|
+
modelReasoningEfforts: KIMI_API_REASONING_EFFORTS,
|
|
1064
|
+
noTemperatureModels: KIMI_API_MODELS,
|
|
1065
|
+
noTopPModels: KIMI_API_MODELS,
|
|
1066
|
+
noPenaltyModels: KIMI_API_MODELS,
|
|
1067
|
+
autoToolChoiceOnlyModels: ["kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
|
|
1068
|
+
preserveReasoningContentModels: KIMI_API_MODELS,
|
|
1069
|
+
},
|
|
1070
|
+
{ id: "huggingface", label: "Hugging Face", baseUrl: "https://router.huggingface.co/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://huggingface.co/settings/tokens" },
|
|
1071
|
+
// 260715 NIM hardening (issue #126, devlog/_plan/260715_issue126_nim_kimi):
|
|
1072
|
+
// - NIM kimi rejects `parallel_tool_calls: true` with 400 "This model only supports single
|
|
1073
|
+
// tool-calls at once!" (openclaw#37048). NVIDIA's own function-calling docs default the
|
|
1074
|
+
// Boolean to false, so provider-wide `false` is the documented-safe wire value.
|
|
1075
|
+
// - `reasoning_effort` is not portable on NIM (models use chat_template_kwargs); the kimi
|
|
1076
|
+
// family is live-discovered with no capability metadata, so Codex would otherwise send
|
|
1077
|
+
// reasoning_effort=medium. Exact-id lists per modelInList semantics; gpt-oss on NIM keeps
|
|
1078
|
+
// its working reasoning_effort. Future kimi ids must be appended individually.
|
|
1079
|
+
{
|
|
1080
|
+
id: "nvidia", label: "NVIDIA NIM", baseUrl: "https://integrate.api.nvidia.com/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://build.nvidia.com",
|
|
1081
|
+
// Free pricing, but an API key is still required (free key from build.nvidia.com).
|
|
1082
|
+
freeTier: true,
|
|
1083
|
+
parallelToolCalls: false,
|
|
1084
|
+
noReasoningModels: NVIDIA_NIM_KIMI_MODELS,
|
|
1085
|
+
modelReasoningEfforts: Object.fromEntries(NVIDIA_NIM_KIMI_MODELS.map(id => [id, []])),
|
|
1086
|
+
preserveReasoningContentModels: NVIDIA_NIM_KIMI_THINKING_MODELS,
|
|
1087
|
+
note: "Free tier on NVIDIA NIM — API key still required (get a free key at build.nvidia.com).",
|
|
1088
|
+
},
|
|
1089
|
+
{ id: "venice", label: "Venice", baseUrl: "https://api.venice.ai/api/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://venice.ai/settings/api" },
|
|
1090
|
+
// 260710 GLM-5.2 context and path-specific ids: Tier-2 evidence in
|
|
1091
|
+
// devlog/_plan/260710_provider_hardening/002_research_cn.md.
|
|
1092
|
+
{
|
|
1093
|
+
id: "zai", label: "Z.AI — GLM Coding Plan", baseUrl: "https://api.z.ai/api/coding/paas/v4", adapter: "openai-chat", authKind: "key",
|
|
1094
|
+
dashboardUrl: "https://z.ai/manage-apikey/apikey-list", defaultModel: "glm-5.2",
|
|
1095
|
+
note: "GLM-5.2 coding subscription",
|
|
1096
|
+
models: ["glm-5.2", "glm-5.2[1m]", "glm-5.1", "glm-5", "glm-4.6"],
|
|
1097
|
+
modelContextWindows: { "glm-5.2": 1_000_000, "glm-5.2[1m]": 1_000_000 },
|
|
1098
|
+
// Z.AI's OpenAI path returns 400 code 1211 for bracketed model ids.
|
|
1099
|
+
modelSuffixBracketStrip: true,
|
|
1100
|
+
noVisionModels: ZAI_GLM_52_MODELS,
|
|
1101
|
+
modelReasoningEfforts: Object.fromEntries(ZAI_GLM_52_MODELS.map(id => [id, ZAI_GLM_52_REASONING_EFFORTS])),
|
|
1102
|
+
preserveReasoningContentModels: ZAI_GLM_52_MODELS,
|
|
1103
|
+
},
|
|
1104
|
+
// Zhipu's domestic BigModel platform: OpenAI-compatible pay-as-you-go on open.bigmodel.cn — a
|
|
1105
|
+
// different host and billing product from the `zai` coding-plan subscription above.
|
|
1106
|
+
// The id is deliberately NOT `glm` or `glm-cn`: both are already bound in FREE_PROVIDER_DIRECTORY
|
|
1107
|
+
// (to api.z.ai and to the BigModel *coding* path), and routedProviderConfig() canonicalizes a
|
|
1108
|
+
// saved provider onto the registry baseUrl — reusing either id would silently retarget an
|
|
1109
|
+
// existing config's endpoint and send its API key to another host.
|
|
1110
|
+
// Evidence: docs.bigmodel.cn/api-reference (OpenAI-compatible chat completions),
|
|
1111
|
+
// docs.bigmodel.cn/cn/guide/models/text/glm-4.6 (thinking: {type: enabled|disabled}).
|
|
1112
|
+
// Originally proposed in #536 by @Lucinegogo.
|
|
1113
|
+
{
|
|
1114
|
+
id: "zhipu-bigmodel",
|
|
1115
|
+
label: "Zhipu AI — BigModel",
|
|
1116
|
+
baseUrl: "https://open.bigmodel.cn/api/paas/v4",
|
|
1117
|
+
adapter: "openai-chat",
|
|
1118
|
+
authKind: "key",
|
|
1119
|
+
dashboardUrl: "https://bigmodel.cn/console/usercenter/apikeys",
|
|
1120
|
+
defaultModel: "glm-4.6",
|
|
1121
|
+
models: ZHIPU_BIGMODEL_MODELS,
|
|
1122
|
+
// The GLM families here are the same ones the `zai` metadata bundle already describes, so the
|
|
1123
|
+
// bundle owns context windows and modalities for the whole list instead of a hand-copied table.
|
|
1124
|
+
jawcodeBundle: "zai",
|
|
1125
|
+
// Declared explicitly for the default model so its window survives a bundle-lookup miss:
|
|
1126
|
+
// without it, catalog normalization falls back to a generic 128k and compacts ~76,800 early.
|
|
1127
|
+
modelContextWindows: { "glm-4.6": 204_800 },
|
|
1128
|
+
modelInputModalities: ZHIPU_BIGMODEL_INPUT_MODALITIES,
|
|
1129
|
+
// GLM exposes a binary thinking knob, not an effort ladder: the adapter emits
|
|
1130
|
+
// `thinking: {type}` for these ids and would otherwise send a rejected reasoning_effort.
|
|
1131
|
+
thinkingToggleModels: ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS,
|
|
1132
|
+
modelReasoningEfforts: Object.fromEntries(
|
|
1133
|
+
ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS.map(id => [id, THINKING_TOGGLE_EFFORTS]),
|
|
1134
|
+
),
|
|
1135
|
+
modelReasoningEffortMap: Object.fromEntries(
|
|
1136
|
+
ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS.map(id => [id, THINKING_TOGGLE_MAP]),
|
|
1137
|
+
),
|
|
1138
|
+
preserveReasoningContentModels: ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS,
|
|
1139
|
+
// No liveModels: GET /api/paas/v4/models has not been observed to answer on this host, and a
|
|
1140
|
+
// false live claim yields an empty picker at runtime. Flip it on once someone verifies it.
|
|
1141
|
+
note: "Domestic BigModel pay-as-you-go endpoint (open.bigmodel.cn)",
|
|
1142
|
+
},
|
|
1143
|
+
{ id: "nanogpt", label: "NanoGPT", baseUrl: "https://nano-gpt.com/api/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://nano-gpt.com/api" },
|
|
1144
|
+
{ id: "synthetic", label: "Synthetic", baseUrl: "https://api.synthetic.new/openai/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://synthetic.new" },
|
|
1145
|
+
// SiliconFlow publishes an OpenAI-compatible chat endpoint and a dynamic model catalog. Do not
|
|
1146
|
+
// freeze reasoning controls here: enable_thinking/thinking_budget support and limits vary by
|
|
1147
|
+
// model, so live metadata or an explicit user override must own those capabilities.
|
|
1148
|
+
// Evidence: https://docs.siliconflow.cn/en/api-reference/chat-completions/chat-completions
|
|
1149
|
+
{
|
|
1150
|
+
id: "siliconflow",
|
|
1151
|
+
label: "SiliconFlow",
|
|
1152
|
+
baseUrl: "https://api.siliconflow.cn/v1",
|
|
1153
|
+
adapter: "openai-chat",
|
|
1154
|
+
authKind: "key",
|
|
1155
|
+
dashboardUrl: "https://cloud.siliconflow.cn/account/ak",
|
|
1156
|
+
liveModels: true,
|
|
1157
|
+
note: "OpenAI-compatible live model catalog; reasoning controls vary by model.",
|
|
1158
|
+
},
|
|
1159
|
+
// Qwen Cloud: token plan is the preset default; GUI offers pay-as-you-go + custom via baseUrlChoices.
|
|
1160
|
+
// Formerly `qwen-portal` / portal.qwen.ai — that host is outdated.
|
|
1161
|
+
{
|
|
1162
|
+
id: "qwen-cloud",
|
|
1163
|
+
label: "Qwen Cloud",
|
|
1164
|
+
baseUrl: QWEN_CLOUD_TOKEN_PLAN_BASE_URL,
|
|
1165
|
+
adapter: "openai-chat",
|
|
1166
|
+
authKind: "key",
|
|
1167
|
+
allowBaseUrlOverride: true,
|
|
1168
|
+
baseUrlChoices: QWEN_CLOUD_BASE_URL_CHOICES,
|
|
1169
|
+
dashboardUrl: "https://docs.qwencloud.com",
|
|
1170
|
+
note: "Pick token plan, pay as you go, or a custom compatible-mode base URL",
|
|
1171
|
+
},
|
|
1172
|
+
{
|
|
1173
|
+
id: "tencent-coding-plan",
|
|
1174
|
+
label: "Tencent Cloud Coding Plan",
|
|
1175
|
+
baseUrl: "https://api.lkeap.cloud.tencent.com/coding/v3",
|
|
1176
|
+
adapter: "openai-chat",
|
|
1177
|
+
authKind: "key",
|
|
1178
|
+
dashboardUrl: "https://console.cloud.tencent.com/tokenhub/codingplan",
|
|
1179
|
+
defaultModel: "tc-code-latest",
|
|
1180
|
+
models: TENCENT_CODING_PLAN_MODELS,
|
|
1181
|
+
liveModels: true,
|
|
1182
|
+
modelInputModalities: Object.fromEntries(TENCENT_CODING_PLAN_MODELS.map(id => [id, ["text"]])),
|
|
1183
|
+
noVisionModels: TENCENT_CODING_PLAN_MODELS,
|
|
1184
|
+
note: "Coding tools only. Tencent forbids general API automation, custom backends, and non-interactive batch use.",
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
id: "volcengine",
|
|
1188
|
+
label: "Volcengine Ark",
|
|
1189
|
+
baseUrl: "https://ark.cn-beijing.volces.com/api/v3",
|
|
1190
|
+
adapter: "openai-chat",
|
|
1191
|
+
authKind: "key",
|
|
1192
|
+
preserveCustomDestination: true,
|
|
1193
|
+
dashboardUrl: "https://console.volcengine.com/ark/region:ark+cn-beijing/apikey",
|
|
1194
|
+
defaultModel: "doubao-seed-2-1-pro-260628",
|
|
1195
|
+
models: VOLCENGINE_ARK_MODELS,
|
|
1196
|
+
liveModels: false,
|
|
1197
|
+
modelReasoningEfforts: Object.fromEntries(
|
|
1198
|
+
VOLCENGINE_DOUBAO_THINKING_MODELS.map(id => [id, THINKING_TOGGLE_EFFORTS]),
|
|
1199
|
+
),
|
|
1200
|
+
modelReasoningEffortMap: Object.fromEntries(
|
|
1201
|
+
VOLCENGINE_DOUBAO_THINKING_MODELS.map(id => [id, THINKING_TOGGLE_MAP]),
|
|
1202
|
+
),
|
|
1203
|
+
thinkingToggleModels: VOLCENGINE_DOUBAO_THINKING_MODELS,
|
|
1204
|
+
preserveReasoningContentModels: [
|
|
1205
|
+
"deepseek-v4-pro-260425",
|
|
1206
|
+
"deepseek-v4-flash-260425",
|
|
1207
|
+
"glm-5-2-260617",
|
|
1208
|
+
"glm-4-7-251222",
|
|
1209
|
+
],
|
|
1210
|
+
noVisionModels: [
|
|
1211
|
+
"deepseek-v4-pro-260425",
|
|
1212
|
+
"deepseek-v4-flash-260425",
|
|
1213
|
+
"deepseek-v3-2-251201",
|
|
1214
|
+
"glm-5-2-260617",
|
|
1215
|
+
"glm-4-7-251222",
|
|
1216
|
+
],
|
|
1217
|
+
note: "Pay-as-you-go Ark API with a curated text/agent catalog. Calls on this endpoint do not consume Coding Plan or Agent Plan quota.",
|
|
1218
|
+
},
|
|
1219
|
+
{
|
|
1220
|
+
id: "volcengine-coding-plan",
|
|
1221
|
+
label: "Volcengine Ark Coding Plan",
|
|
1222
|
+
baseUrl: "https://ark.cn-beijing.volces.com/api/coding/v3",
|
|
1223
|
+
adapter: "openai-chat",
|
|
1224
|
+
authKind: "key",
|
|
1225
|
+
preserveCustomDestination: true,
|
|
1226
|
+
dashboardUrl: "https://console.volcengine.com/ark/region:ark+cn-beijing/overview",
|
|
1227
|
+
defaultModel: "ark-code-latest",
|
|
1228
|
+
models: VOLCENGINE_CODING_PLAN_MODELS,
|
|
1229
|
+
liveModels: false,
|
|
1230
|
+
modelInputModalities: VOLCENGINE_PLAN_INPUT_MODALITIES,
|
|
1231
|
+
noVisionModels: VOLCENGINE_PLAN_TEXT_ONLY_MODELS,
|
|
1232
|
+
modelReasoningEfforts: Object.fromEntries(
|
|
1233
|
+
DEEPSEEK_THINKING_MODELS.map(id => [id, DEEPSEEK_THINKING_EFFORTS]),
|
|
1234
|
+
),
|
|
1235
|
+
modelReasoningEffortMap: Object.fromEntries(
|
|
1236
|
+
DEEPSEEK_THINKING_MODELS.map(id => [id, DEEPSEEK_THINKING_REASONING_MAP]),
|
|
1237
|
+
),
|
|
1238
|
+
preserveReasoningContentModels: DEEPSEEK_THINKING_MODELS,
|
|
1239
|
+
note: "Coding tools only. Volcengine restricts Coding Plan quota to supported AI coding tools and warns that using this key for general API calls may suspend the subscription or ban the account. Use the plan key issued by the Ark console.",
|
|
1240
|
+
},
|
|
1241
|
+
{
|
|
1242
|
+
id: "volcengine-agent-plan",
|
|
1243
|
+
label: "Volcengine Ark Agent Plan",
|
|
1244
|
+
baseUrl: "https://ark.cn-beijing.volces.com/api/plan/v3",
|
|
1245
|
+
responsesPath: "/responses",
|
|
1246
|
+
adapter: "openai-responses",
|
|
1247
|
+
authKind: "key",
|
|
1248
|
+
preserveCustomDestination: true,
|
|
1249
|
+
dashboardUrl: "https://console.volcengine.com/ark/region:ark+cn-beijing/overview",
|
|
1250
|
+
defaultModel: "deepseek-v4-pro",
|
|
1251
|
+
models: VOLCENGINE_AGENT_PLAN_MODELS,
|
|
1252
|
+
liveModels: false,
|
|
1253
|
+
modelInputModalities: VOLCENGINE_PLAN_INPUT_MODALITIES,
|
|
1254
|
+
noVisionModels: VOLCENGINE_PLAN_TEXT_ONLY_MODELS,
|
|
1255
|
+
note: "Coding tools only. Agent Plan is a subscription endpoint over the native Responses API with a static fallback catalog; Ark plan quota is intended for supported AI coding and agent tools, so avoid using this key as a general-purpose API key.",
|
|
1256
|
+
},
|
|
1257
|
+
// 2026-07-10: docs unverified; model data frozen. Evidence: devlog/_plan/260710_provider_hardening/002_research_cn.md.
|
|
1258
|
+
{ id: "qianfan", label: "Qianfan (Baidu)", baseUrl: "https://qianfan.baidubce.com/v2", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://console.bce.baidu.com/iam/#/iam/apikey/list" },
|
|
1259
|
+
// 2026-07-10: docs unverified; model data frozen. Evidence: devlog/_plan/260710_provider_hardening/002_research_cn.md.
|
|
1260
|
+
{ id: "alibaba", label: "Alibaba Coding Plan", baseUrl: ALIBABA_CODING_INTL_BASE_URL, adapter: "openai-chat", authKind: "key", allowBaseUrlOverride: true, baseUrlChoices: ALIBABA_CODING_BASE_URL_CHOICES, dashboardUrl: "https://dashscope.console.aliyun.com/apiKey" },
|
|
1261
|
+
{
|
|
1262
|
+
id: "alibaba-token-plan",
|
|
1263
|
+
label: "Alibaba Token Plan (Beijing)",
|
|
1264
|
+
baseUrl: "https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1",
|
|
1265
|
+
adapter: "openai-chat",
|
|
1266
|
+
authKind: "key",
|
|
1267
|
+
dashboardUrl: "https://bailian.console.aliyun.com/cn-beijing?tab=plan",
|
|
1268
|
+
defaultModel: "qwen3.8-max-preview",
|
|
1269
|
+
models: ALIBABA_TOKEN_PLAN_MODELS,
|
|
1270
|
+
liveModels: false,
|
|
1271
|
+
note: "Token Plan Personal Edition · China (Beijing)",
|
|
1272
|
+
modelInputModalities: ALIBABA_TOKEN_PLAN_INPUT_MODALITIES,
|
|
1273
|
+
modelContextWindows: {
|
|
1274
|
+
"qwen3.8-max-preview": 983_616, "qwen3.7-max": 1_000_000, "qwen3.7-plus": 1_000_000,
|
|
1275
|
+
"qwen3.6-flash": 1_000_000, "glm-5.2": 1_000_000, "deepseek-v4-pro": 1_000_000,
|
|
1276
|
+
},
|
|
1277
|
+
modelReasoningEfforts: {
|
|
1278
|
+
...Object.fromEntries(ALIBABA_TOKEN_PLAN_QWEN_MODELS.map(id => [id, THINKING_BUDGET_EFFORTS])),
|
|
1279
|
+
"glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
|
|
1280
|
+
"deepseek-v4-pro": DEEPSEEK_THINKING_EFFORTS,
|
|
1281
|
+
},
|
|
1282
|
+
modelReasoningEffortMap: { "deepseek-v4-pro": DEEPSEEK_THINKING_REASONING_MAP },
|
|
1283
|
+
thinkingBudgetModels: ALIBABA_TOKEN_PLAN_QWEN_MODELS,
|
|
1284
|
+
preserveReasoningContentModels: ["glm-5.2", "deepseek-v4-pro", "qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-flash"],
|
|
1285
|
+
noVisionModels: ["glm-5.2", "deepseek-v4-pro"],
|
|
1286
|
+
},
|
|
1287
|
+
{
|
|
1288
|
+
id: "alibaba-token-plan-intl",
|
|
1289
|
+
label: "Alibaba Token Plan (International)",
|
|
1290
|
+
baseUrl: ALIBABA_INTL_TOKEN_PLAN_BASE_URL,
|
|
1291
|
+
adapter: "openai-chat",
|
|
1292
|
+
authKind: "key",
|
|
1293
|
+
allowBaseUrlOverride: true,
|
|
1294
|
+
baseUrlChoices: ALIBABA_INTL_BASE_URL_CHOICES,
|
|
1295
|
+
dashboardUrl: "https://modelstudio.console.alibabacloud.com/?tab=api#/api",
|
|
1296
|
+
defaultModel: "qwen3.7-max",
|
|
1297
|
+
models: ALIBABA_INTL_TOKEN_PLAN_MODELS,
|
|
1298
|
+
liveModels: false,
|
|
1299
|
+
note: "Token Plan Team Edition · Singapore (ap-southeast-1)",
|
|
1300
|
+
metadataModelIdNormalize: "case-insensitive",
|
|
1301
|
+
modelInputModalities: ALIBABA_INTL_TOKEN_PLAN_INPUT_MODALITIES,
|
|
1302
|
+
modelContextWindows: {
|
|
1303
|
+
"qwen3.8-max-preview": 983_616,
|
|
1304
|
+
"qwen3.7-max": 1_000_000, "qwen3.7-plus": 1_000_000, "qwen3.6-plus": 1_000_000, "qwen3.6-flash": 1_000_000,
|
|
1305
|
+
"deepseek-v4-pro": 1_000_000, "deepseek-v4-flash": 1_000_000, "deepseek-v3.2": 131_072,
|
|
1306
|
+
"kimi-k2.7-code": 262_144, "kimi-k2.6": 262_144, "kimi-k2.5": 262_144,
|
|
1307
|
+
"glm-5.2": 1_000_000, "glm-5.1": 1_000_000, "glm-5": 1_000_000,
|
|
1308
|
+
"MiniMax-M2.5": 204_800,
|
|
1309
|
+
},
|
|
1310
|
+
modelReasoningEfforts: {
|
|
1311
|
+
...Object.fromEntries(ALIBABA_INTL_TOKEN_PLAN_QWEN_MODELS.map(id => [id, THINKING_BUDGET_EFFORTS])),
|
|
1312
|
+
"qwen3.8-max-preview": ["low", "high", "xhigh"],
|
|
1313
|
+
"glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
|
|
1314
|
+
"deepseek-v4-pro": DEEPSEEK_THINKING_EFFORTS,
|
|
1315
|
+
"deepseek-v4-flash": DEEPSEEK_THINKING_EFFORTS,
|
|
1316
|
+
},
|
|
1317
|
+
modelReasoningEffortMap: {
|
|
1318
|
+
"deepseek-v4-pro": DEEPSEEK_THINKING_REASONING_MAP,
|
|
1319
|
+
"deepseek-v4-flash": DEEPSEEK_THINKING_REASONING_MAP,
|
|
1320
|
+
},
|
|
1321
|
+
thinkingBudgetModels: ALIBABA_INTL_TOKEN_PLAN_QWEN_MODELS,
|
|
1322
|
+
preserveReasoningContentModels: ["glm-5.2", "deepseek-v4-pro", "deepseek-v4-flash", "qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", "qwen3.6-flash"],
|
|
1323
|
+
noVisionModels: ["deepseek-v4-pro", "deepseek-v4-flash", "deepseek-v3.2", "glm-5.2", "glm-5.1", "glm-5", "MiniMax-M2.5"],
|
|
1324
|
+
noReasoningModels: ["kimi-k2.7-code", "kimi-k2.6", "kimi-k2.5", "deepseek-v3.2", "glm-5.1", "glm-5", "MiniMax-M2.5"],
|
|
1325
|
+
modelDefaultReasoningEfforts: { "qwen3.8-max-preview": "xhigh" },
|
|
1326
|
+
},
|
|
1327
|
+
// NEEDS_HUMAN 2026-07-10: kept for config compatibility, but this is a dashboard URL,
|
|
1328
|
+
// no /models endpoint is documented, and tools are silently ignored upstream per docs.parallel.ai.
|
|
1329
|
+
// Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
|
|
1330
|
+
{ id: "parallel", label: "Parallel", baseUrl: "https://platform.parallel.ai", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://platform.parallel.ai" },
|
|
1331
|
+
// ZenMux native ids are vendor-namespaced (`<vendor>/<model>`), verified live against
|
|
1332
|
+
// https://zenmux.ai/api/v1/models on 2026-07-18. The static seed doubles as the
|
|
1333
|
+
// cold-cache decode source for the Codex slug codec (src/providers/slug-codec.ts);
|
|
1334
|
+
// live discovery still owns the full catalog.
|
|
1335
|
+
{
|
|
1336
|
+
id: "zenmux", label: "ZenMux", baseUrl: "https://zenmux.ai/api/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://zenmux.ai",
|
|
1337
|
+
models: ["moonshotai/kimi-k3-free", "moonshotai/kimi-k3"],
|
|
1338
|
+
},
|
|
1339
|
+
{
|
|
1340
|
+
id: "litellm", label: "LiteLLM (self-hosted)", baseUrl: "http://localhost:4000/v1", adapter: "openai-chat", authKind: "key",
|
|
1341
|
+
dashboardUrl: "https://docs.litellm.ai/docs/proxy/quick_start",
|
|
1342
|
+
allowPrivateNetworkByDefault: true,
|
|
1343
|
+
allowBaseUrlOverride: true,
|
|
1344
|
+
// A self-hosted proxy may legitimately run without a master key.
|
|
1345
|
+
keyOptional: true,
|
|
1346
|
+
},
|
|
1347
|
+
{
|
|
1348
|
+
id: "ollama-cloud",
|
|
1349
|
+
label: "Ollama Cloud",
|
|
1350
|
+
baseUrl: "https://ollama.com/v1",
|
|
1351
|
+
adapter: "openai-chat",
|
|
1352
|
+
authKind: "key",
|
|
1353
|
+
dashboardUrl: "https://ollama.com/settings/keys",
|
|
1354
|
+
// Live IDs verified 2026-07-10; qwen3-coder:480b retires 2026-07-15.
|
|
1355
|
+
models: ["glm-5.2", "deepseek-v4-pro", "qwen3-coder:480b", "gpt-oss:120b", "kimi-k2.6", "minimax-m3", "qwen3.5:397b", "gemma4:31b"],
|
|
1356
|
+
defaultModel: "glm-5.2",
|
|
1357
|
+
noVisionModels: [
|
|
1358
|
+
"glm-5.2", "glm-5.1", "glm-5", "glm-4.7",
|
|
1359
|
+
"minimax-m2.7", "minimax-m2.5", "minimax-m2.1",
|
|
1360
|
+
"nemotron-3-ultra", "nemotron-3-super",
|
|
1361
|
+
"deepseek-v4-pro", "deepseek-v4-flash",
|
|
1362
|
+
"gpt-oss", "qwen3-coder:480b",
|
|
1363
|
+
],
|
|
1364
|
+
},
|
|
1365
|
+
// FREEZE 2026-07-10: codestral-latest is unconfirmed behind auth. Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
|
|
1366
|
+
{ id: "mistral", label: "Mistral", baseUrl: "https://api.mistral.ai/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://console.mistral.ai/api-keys", defaultModel: "codestral-latest" },
|
|
1367
|
+
{
|
|
1368
|
+
id: "minimax", label: "MiniMax — Coding Plan", baseUrl: "https://api.minimax.io/v1", adapter: "openai-chat", authKind: "key",
|
|
1369
|
+
dashboardUrl: "https://platform.minimax.io", defaultModel: "MiniMax-M3", models: MINIMAX_MODELS,
|
|
1370
|
+
modelContextWindows: MINIMAX_MODEL_CONTEXT_WINDOWS,
|
|
1371
|
+
modelReasoningEfforts: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORTS },
|
|
1372
|
+
modelDefaultReasoningEfforts: { "MiniMax-M3": "medium" },
|
|
1373
|
+
modelReasoningEffortMap: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORT_MAP },
|
|
1374
|
+
preserveReasoningContentModels: MINIMAX_MODELS,
|
|
1375
|
+
reasoningSplitModels: MINIMAX_MODELS,
|
|
1376
|
+
thinkingToggleModels: ["MiniMax-M3"],
|
|
1377
|
+
jawcodeBundle: "minimax", metadataModelIdNormalize: "case-insensitive", note: "Subscription Key or API Key",
|
|
1378
|
+
},
|
|
1379
|
+
{
|
|
1380
|
+
id: "minimax-cn", label: "MiniMax — Coding Plan (CN)", baseUrl: "https://api.minimaxi.com/v1", adapter: "openai-chat", authKind: "key",
|
|
1381
|
+
dashboardUrl: "https://platform.minimaxi.com", defaultModel: "MiniMax-M3", models: MINIMAX_MODELS,
|
|
1382
|
+
modelContextWindows: MINIMAX_MODEL_CONTEXT_WINDOWS,
|
|
1383
|
+
modelReasoningEfforts: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORTS },
|
|
1384
|
+
modelDefaultReasoningEfforts: { "MiniMax-M3": "medium" },
|
|
1385
|
+
modelReasoningEffortMap: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORT_MAP },
|
|
1386
|
+
preserveReasoningContentModels: MINIMAX_MODELS,
|
|
1387
|
+
reasoningSplitModels: MINIMAX_MODELS,
|
|
1388
|
+
thinkingToggleModels: ["MiniMax-M3"],
|
|
1389
|
+
jawcodeBundle: "minimax", metadataModelIdNormalize: "case-insensitive", note: "中国区 Subscription Key",
|
|
1390
|
+
},
|
|
1391
|
+
{
|
|
1392
|
+
id: "kimi-code", label: "Kimi (coding)", baseUrl: "https://api.kimi.com/coding/v1", adapter: "openai-chat", authKind: "key",
|
|
1393
|
+
dashboardUrl: "https://platform.moonshot.cn/console/api-keys", defaultModel: "kimi-k2.7-code",
|
|
1394
|
+
modelSuffixBracketStrip: true,
|
|
1395
|
+
// API-key form of the same Kimi Code Plan transport; keep cache affinity identical to OAuth.
|
|
1396
|
+
promptCacheKey: true,
|
|
1397
|
+
models: KIMI_CODING_MODELS,
|
|
1398
|
+
modelContextWindows: KIMI_CODING_MODEL_CONTEXT_WINDOWS,
|
|
1399
|
+
modelInputModalities: KIMI_CODING_MODEL_INPUT_MODALITIES,
|
|
1400
|
+
noReasoningModels: KIMI_CODING_NO_REASONING_MODELS,
|
|
1401
|
+
modelReasoningEfforts: KIMI_CODING_REASONING_EFFORTS,
|
|
1402
|
+
modelDefaultReasoningEfforts: KIMI_CODING_DEFAULT_REASONING_EFFORTS,
|
|
1403
|
+
modelReasoningEffortMap: KIMI_CODING_REASONING_EFFORT_MAPS,
|
|
1404
|
+
noTemperatureModels: KIMI_LOCKED_PARAMETER_MODELS,
|
|
1405
|
+
noTopPModels: KIMI_LOCKED_PARAMETER_MODELS,
|
|
1406
|
+
noPenaltyModels: KIMI_LOCKED_PARAMETER_MODELS,
|
|
1407
|
+
autoToolChoiceOnlyModels: KIMI_AUTO_TOOL_CHOICE_ONLY_MODELS,
|
|
1408
|
+
preserveReasoningContentModels: KIMI_THINKING_MODELS,
|
|
1409
|
+
},
|
|
1410
|
+
{ id: "opencode-zen", label: "opencode zen", baseUrl: "https://opencode.ai/zen/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://opencode.ai/auth" },
|
|
1411
|
+
{ id: "vercel-ai-gateway", label: "Vercel AI Gateway", baseUrl: "https://ai-gateway.vercel.sh/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://vercel.com/dashboard" },
|
|
1412
|
+
{
|
|
1413
|
+
id: "opencode-free",
|
|
1414
|
+
label: "OpenCode Free",
|
|
1415
|
+
adapter: "openai-chat",
|
|
1416
|
+
baseUrl: "https://opencode.ai/zen/v1",
|
|
1417
|
+
authKind: "key",
|
|
1418
|
+
keyOptional: true,
|
|
1419
|
+
featured: true,
|
|
1420
|
+
liveModels: true,
|
|
1421
|
+
note: "No key needed — public desktop tier. OpenCode currently advertises about 200 Big Pickle/free-model requests per 5 hours. Free models are discovered live from Zen. Data use: per OpenCode's Zen docs (https://opencode.ai/docs/zen/), prompts sent to free models may be retained and used for training/improvement — do not send confidential material through this provider.",
|
|
1422
|
+
dashboardUrl: "https://opencode.ai",
|
|
1423
|
+
staticHeaders: {
|
|
1424
|
+
"x-opencode-client": "desktop",
|
|
1425
|
+
},
|
|
1426
|
+
modelReasoningEfforts: Object.fromEntries(OPENCODE_FREE_DEEPSEEK_MODELS.map(id => [id, DEEPSEEK_THINKING_EFFORTS])),
|
|
1427
|
+
modelReasoningEffortMap: Object.fromEntries(OPENCODE_FREE_DEEPSEEK_MODELS.map(id => [id, DEEPSEEK_THINKING_REASONING_MAP])),
|
|
1428
|
+
preserveReasoningContentModels: OPENCODE_FREE_DEEPSEEK_MODELS,
|
|
1429
|
+
noVisionModels: OPENCODE_FREE_DEEPSEEK_MODELS,
|
|
1430
|
+
},
|
|
1431
|
+
{ id: "xiaomi", label: "Xiaomi MiMo", baseUrl: "https://api.xiaomimimo.com/anthropic", adapter: "anthropic", authKind: "key", dashboardUrl: "https://xiaomimimo.com", defaultModel: "mimo-v2.5-pro" },
|
|
1432
|
+
{ id: "kilo", label: "Kilo", baseUrl: "https://api.kilo.ai/api/gateway", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://kilo.ai" },
|
|
1433
|
+
{
|
|
1434
|
+
id: "mimo-free",
|
|
1435
|
+
label: "MiMo Free",
|
|
1436
|
+
adapter: "mimo-free",
|
|
1437
|
+
baseUrl: "https://api.xiaomimimo.com/api/free-ai/openai/chat",
|
|
1438
|
+
authKind: "key",
|
|
1439
|
+
keyOptional: true,
|
|
1440
|
+
featured: true,
|
|
1441
|
+
liveModels: true,
|
|
1442
|
+
dashboardUrl: "https://xiaomimimo.com",
|
|
1443
|
+
defaultModel: "mimo-auto",
|
|
1444
|
+
models: ["mimo-auto"],
|
|
1445
|
+
note: "No key needed — uses Xiaomi MiMo's free public tier (limited-time offer). A JWT is bootstrapped automatically with an anonymous random client id stored locally. The endpoint contract mirrors the official MiMoCode client and is not publicly documented — Xiaomi may change or restrict it at any time. Prompts may be processed/retained by Xiaomi; do not send confidential material.",
|
|
1446
|
+
},
|
|
1447
|
+
{ id: "cloudflare-ai-gateway", label: "Cloudflare AI Gateway", baseUrl: "https://gateway.ai.cloudflare.com/v1/{account-id}/{gateway}/anthropic", adapter: "anthropic", authKind: "key", dashboardUrl: "https://dash.cloudflare.com/?to=/:account/ai/ai-gateway" },
|
|
1448
|
+
{
|
|
1449
|
+
// Cloudflare Workers AI: OpenAI-compatible endpoint. The base URL contains {account_id}
|
|
1450
|
+
// which must be resolved by the user at setup time. Model IDs use the @cf/ prefix.
|
|
1451
|
+
// Live-verified 2026-07-21 against https://developers.cloudflare.com/workers-ai/models/
|
|
1452
|
+
id: "cloudflare-workers-ai", label: "Cloudflare Workers AI",
|
|
1453
|
+
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/v1",
|
|
1454
|
+
adapter: "openai-chat", authKind: "key", freeTier: true,
|
|
1455
|
+
dashboardUrl: "https://dash.cloudflare.com/?to=/:account/ai/workers-ai",
|
|
1456
|
+
defaultModel: "@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
1457
|
+
models: [
|
|
1458
|
+
"@cf/meta/llama-3.3-70b-instruct-fp8-fast",
|
|
1459
|
+
"@cf/qwen/qwq-32b",
|
|
1460
|
+
"@cf/deepseek-ai/deepseek-r1-distill-qwen-32b",
|
|
1461
|
+
"@cf/moonshotai/kimi-k2.7-code",
|
|
1462
|
+
"@cf/zai-org/glm-5.2",
|
|
1463
|
+
"@cf/mistralai/mistral-small-3.1-24b-instruct",
|
|
1464
|
+
],
|
|
1465
|
+
note: "Workers AI · Free tier included · Account ID required in base URL",
|
|
1466
|
+
},
|
|
1467
|
+
// FREEZE 2026-07-10: /models was auth-gated under key login. OAuth device-flow + copilot_internal
|
|
1468
|
+
// exchange (issue #151) unlocks live discovery; static seed is a cold-start fallback only.
|
|
1469
|
+
{
|
|
1470
|
+
id: "github-copilot",
|
|
1471
|
+
label: "GitHub Copilot",
|
|
1472
|
+
baseUrl: "https://api.githubcopilot.com",
|
|
1473
|
+
adapter: "openai-chat",
|
|
1474
|
+
authKind: "oauth",
|
|
1475
|
+
allowKeyAuthOverride: true,
|
|
1476
|
+
featured: false,
|
|
1477
|
+
dashboardUrl: "https://github.com/settings/copilot",
|
|
1478
|
+
liveModels: true,
|
|
1479
|
+
models: ["gpt-4o", "gpt-4.1", "gpt-4.1-mini", "claude-sonnet-4", "gemini-2.5-pro"],
|
|
1480
|
+
defaultModel: "gpt-4o",
|
|
1481
|
+
note: "Experimental unofficial Copilot bridge. Logs in via GitHub device flow using the public VS Code OAuth client id, then exchanges for a short-lived Copilot API token (copilot_internal). Requires an active Copilot subscription. GitHub may tighten or revoke this path; do not send confidential material you would not paste into Copilot Chat.",
|
|
1482
|
+
},
|
|
1483
|
+
// FREEZE 2026-07-10: no public OpenAI-compatible endpoint is documented. Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
|
|
1484
|
+
{ id: "gitlab-duo", label: "GitLab Duo", baseUrl: "https://cloud.gitlab.com/ai/v1/proxy/openai/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://gitlab.com/-/user_settings/personal_access_tokens" },
|
|
1485
|
+
];
|
|
1486
|
+
|
|
1487
|
+
export function getProviderRegistryEntry(id: string): ProviderRegistryEntry | undefined {
|
|
1488
|
+
return PROVIDER_REGISTRY.find(entry => entry.id === id);
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1491
|
+
function normalizedProviderEndpoint(value: string): string {
|
|
1492
|
+
const trimmed = value.trim();
|
|
1493
|
+
try {
|
|
1494
|
+
const parsed = new URL(trimmed);
|
|
1495
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/, "") || "/";
|
|
1496
|
+
return parsed.toString().replace(/\/$/, "");
|
|
1497
|
+
} catch {
|
|
1498
|
+
return trimmed.replace(/\/+$/, "");
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
/**
|
|
1503
|
+
* Whether registry transport defaults own this configured row.
|
|
1504
|
+
*
|
|
1505
|
+
* OAuth/forward providers stay pinned because their credentials must never be sent to an
|
|
1506
|
+
* arbitrary same-named host. Existing key presets keep their historical pinning behavior; a new
|
|
1507
|
+
* preset can opt into collision preservation, in which case its fixed endpoint owns only rows
|
|
1508
|
+
* that still match that destination.
|
|
1509
|
+
*/
|
|
1510
|
+
export function providerMatchesRegistryTransport(
|
|
1511
|
+
id: string,
|
|
1512
|
+
provider: Pick<OcxProviderConfig, "baseUrl" | "adapter"> & Partial<Pick<OcxProviderConfig, "authMode">>,
|
|
1513
|
+
): boolean {
|
|
1514
|
+
const entry = getProviderRegistryEntry(id);
|
|
1515
|
+
if (!entry) return false;
|
|
1516
|
+
if (entry.authKind !== "key" || entry.preserveCustomDestination !== true) return true;
|
|
1517
|
+
// The opt-in is intentionally limited to fixed key destinations. Fail closed if a future
|
|
1518
|
+
// registry edit combines it with an override/template despite the registry parity tests.
|
|
1519
|
+
if (entry.allowBaseUrlOverride || /\{[^}]*\}/.test(entry.baseUrl)) return false;
|
|
1520
|
+
if (typeof provider.baseUrl !== "string") return false;
|
|
1521
|
+
if (provider.adapter !== entry.adapter) return false;
|
|
1522
|
+
if (provider.authMode !== undefined && provider.authMode !== "key") return false;
|
|
1523
|
+
return normalizedProviderEndpoint(provider.baseUrl) === normalizedProviderEndpoint(entry.baseUrl);
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
/**
|
|
1527
|
+
* Resolve the registry entry a configured provider actually points at, by TRANSPORT
|
|
1528
|
+
* rather than by name.
|
|
1529
|
+
*
|
|
1530
|
+
* `providerMatchesRegistryTransport` answers "does the row named X still point at X's
|
|
1531
|
+
* documented destination", which is the right question for routing but the wrong one
|
|
1532
|
+
* for user-facing metadata: the GUI lets a preset be saved under any name, and a
|
|
1533
|
+
* renamed row would silently lose a usage restriction it still needs to display.
|
|
1534
|
+
*
|
|
1535
|
+
* Only fixed key destinations are matched. Entries with an overridable or templated
|
|
1536
|
+
* base URL are skipped, because their configured URL cannot identify one vendor route.
|
|
1537
|
+
*/
|
|
1538
|
+
export function registryEntryForProviderDestination(
|
|
1539
|
+
provider: Pick<OcxProviderConfig, "baseUrl" | "adapter"> & Partial<Pick<OcxProviderConfig, "authMode">>,
|
|
1540
|
+
): ProviderRegistryEntry | undefined {
|
|
1541
|
+
if (typeof provider.baseUrl !== "string" || !provider.baseUrl) return undefined;
|
|
1542
|
+
if (provider.authMode !== undefined && provider.authMode !== "key") return undefined;
|
|
1543
|
+
const endpoint = normalizedProviderEndpoint(provider.baseUrl);
|
|
1544
|
+
return PROVIDER_REGISTRY.find(entry =>
|
|
1545
|
+
entry.authKind === "key"
|
|
1546
|
+
&& !entry.allowBaseUrlOverride
|
|
1547
|
+
&& !/\{[^}]*\}/.test(entry.baseUrl)
|
|
1548
|
+
&& entry.adapter === provider.adapter
|
|
1549
|
+
&& normalizedProviderEndpoint(entry.baseUrl) === endpoint);
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
/**
|
|
1553
|
+
* Resolve a registry-only default for a mixed-wire provider. Defaults only move a provider
|
|
1554
|
+
* between the two OpenAI-shaped adapters and never override a provider configured on another
|
|
1555
|
+
* wire. The resolver receives the allow-list so this helper cannot accidentally widen the
|
|
1556
|
+
* adapter-selection boundary when a new registry entry is added.
|
|
1557
|
+
*/
|
|
1558
|
+
export function providerModelWireDefault(
|
|
1559
|
+
id: string,
|
|
1560
|
+
provider: Pick<OcxProviderConfig, "baseUrl" | "adapter"> & Partial<Pick<OcxProviderConfig, "authMode">>,
|
|
1561
|
+
modelId: string,
|
|
1562
|
+
allowedWires: ReadonlySet<string>,
|
|
1563
|
+
inbound: InboundWire,
|
|
1564
|
+
): string | undefined {
|
|
1565
|
+
if (!allowedWires.has(provider.adapter)) return undefined;
|
|
1566
|
+
const entry = getProviderRegistryEntry(id);
|
|
1567
|
+
if (!entry?.modelWireDefaults || !providerMatchesRegistryTransport(id, provider)) return undefined;
|
|
1568
|
+
const declared = entry.modelWireDefaults[modelId.trim().toLowerCase()];
|
|
1569
|
+
if (declared === undefined) return undefined;
|
|
1570
|
+
// A bare string applies to every inbound; the object form only to the listed ones.
|
|
1571
|
+
if (typeof declared !== "string" && !declared.inbound.includes(inbound)) return undefined;
|
|
1572
|
+
const wire = typeof declared === "string" ? declared : declared.wire;
|
|
1573
|
+
return wire !== undefined && allowedWires.has(wire) ? wire : undefined;
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
/**
|
|
1577
|
+
* Effective Codex account mode for a provider. For canonical `openai`, a valid persisted
|
|
1578
|
+
* `codexAccountMode` on the provider config wins and a missing/invalid value defaults to
|
|
1579
|
+
* `"pool"`. Other providers keep registry-only metadata (there is no mode for `openai-apikey`).
|
|
1580
|
+
*/
|
|
1581
|
+
export function providerCodexAccountMode(id: string, provider?: OcxProviderConfig): CodexAccountMode | undefined {
|
|
1582
|
+
const registryMode = getProviderRegistryEntry(id)?.codexAccountMode;
|
|
1583
|
+
if (id !== "openai") return registryMode;
|
|
1584
|
+
const persisted = provider?.codexAccountMode;
|
|
1585
|
+
if (persisted === "pool" || persisted === "direct") return persisted;
|
|
1586
|
+
return registryMode ?? "pool";
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
/**
|
|
1590
|
+
* Effective Google wire mode for a provider: config value, else registry backfill (a saved
|
|
1591
|
+
* key-login config may omit `googleMode` — mirrors the router's backfill), else "ai-studio"
|
|
1592
|
+
* (the Generative Language API default). Null for non-google adapters.
|
|
1593
|
+
*/
|
|
1594
|
+
export function effectiveGoogleMode(
|
|
1595
|
+
providerId: string,
|
|
1596
|
+
prov: { adapter?: string; googleMode?: "ai-studio" | "vertex" | "cloud-code-assist" },
|
|
1597
|
+
): "ai-studio" | "vertex" | "cloud-code-assist" | null {
|
|
1598
|
+
if (prov.adapter !== "google") return null;
|
|
1599
|
+
return prov.googleMode ?? getProviderRegistryEntry(providerId)?.googleMode ?? "ai-studio";
|
|
1600
|
+
}
|