@iislee/opencodex 2.11.0 → 2.31.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/AGENTS_INSTALL.md +109 -0
- package/README.md +114 -19
- package/bin/ocx.mjs +164 -36
- package/bin/package-main.mjs +1 -1
- package/gui/dist/assets/index-BF38heuV.js +104 -0
- package/gui/dist/assets/index-DMiI18Kv.css +1 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/alibaba-color.svg +1 -1
- package/gui/dist/provider-icons/antigravity-color.svg +1 -1
- package/gui/dist/provider-icons/claude-color.svg +1 -1
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -1
- package/gui/dist/provider-icons/cursor-color.svg +1 -1
- package/gui/dist/provider-icons/deepseek-color.svg +1 -1
- package/gui/dist/provider-icons/firepass-color.svg +1 -1
- package/gui/dist/provider-icons/fireworks-color.svg +1 -1
- package/gui/dist/provider-icons/gemini-color.svg +1 -1
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
- package/gui/dist/provider-icons/grok.svg +1 -1
- package/gui/dist/provider-icons/groq-color.svg +1 -1
- package/gui/dist/provider-icons/huggingface-color.svg +1 -1
- package/gui/dist/provider-icons/kimi-color.svg +1 -1
- package/gui/dist/provider-icons/kiro-color.svg +2 -2
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
- package/gui/dist/provider-icons/mistral-color.svg +1 -1
- package/gui/dist/provider-icons/moonshot-color.svg +1 -1
- package/gui/dist/provider-icons/nvidia-color.svg +1 -1
- package/gui/dist/provider-icons/ollama-color.svg +1 -1
- package/gui/dist/provider-icons/openai.svg +1 -1
- package/gui/dist/provider-icons/opencode.svg +2 -1
- package/gui/dist/provider-icons/openrouter-color.svg +1 -1
- package/gui/dist/provider-icons/pi.svg +2 -2
- package/gui/dist/provider-icons/qianfan-color.svg +1 -1
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/vllm-color.svg +1 -1
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
- package/package.json +19 -10
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +376 -52
- package/src/adapters/base.ts +54 -7
- package/src/adapters/client-fingerprint.ts +18 -12
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +601 -0
- package/src/adapters/cursor/checkpoint-store.ts +303 -0
- package/src/adapters/cursor/cursor-errors.ts +129 -6
- package/src/adapters/cursor/discovery.ts +61 -4
- package/src/adapters/cursor/effort-map.ts +27 -3
- package/src/adapters/cursor/framing.ts +39 -0
- package/src/adapters/cursor/h2-pool.ts +123 -0
- package/src/adapters/cursor/http1-bidi.ts +361 -0
- package/src/adapters/cursor/images.ts +704 -0
- package/src/adapters/cursor/live-models.ts +174 -58
- package/src/adapters/cursor/live-transport.ts +609 -170
- package/src/adapters/cursor/native-exec-common.ts +23 -2
- package/src/adapters/cursor/native-exec-fs.ts +10 -7
- package/src/adapters/cursor/native-exec-network.ts +1 -1
- package/src/adapters/cursor/native-exec-shell.ts +0 -1
- package/src/adapters/cursor/native-exec.ts +101 -14
- package/src/adapters/cursor/protobuf-events.ts +829 -11
- package/src/adapters/cursor/protobuf-request.ts +383 -65
- package/src/adapters/cursor/request-builder.ts +237 -31
- package/src/adapters/cursor/tool-definitions.ts +242 -12
- package/src/adapters/cursor/tool-result-normalize.ts +92 -0
- package/src/adapters/cursor/transport.ts +22 -0
- package/src/adapters/cursor/types.ts +28 -1
- package/src/adapters/cursor.ts +133 -7
- package/src/adapters/google-antigravity-replay.ts +558 -34
- package/src/adapters/google-antigravity-wire.ts +43 -10
- package/src/adapters/google-http.ts +38 -10
- package/src/adapters/google-tool-schema.ts +80 -15
- package/src/adapters/google-truncation.ts +11 -0
- package/src/adapters/google.ts +618 -74
- package/src/adapters/identity.ts +39 -6
- package/src/adapters/kiro-errors.ts +11 -0
- package/src/adapters/kiro-events.ts +19 -1
- package/src/adapters/kiro-thinking.ts +18 -2
- package/src/adapters/kiro-tools.ts +10 -1
- package/src/adapters/kiro.ts +92 -54
- package/src/adapters/mimo-free.ts +17 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1311 -336
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +830 -56
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +104 -21
- package/src/adapters/xai-web-search.ts +185 -0
- package/src/bridge.ts +428 -61
- package/src/chat/inbound.ts +43 -19
- package/src/chat/outbound.ts +82 -26
- package/src/claude/agents-inject.ts +32 -9
- package/src/claude/context-windows.ts +21 -5
- package/src/claude/desktop-3p.ts +243 -9
- package/src/claude/gateway-cache.ts +41 -4
- package/src/claude/inbound.ts +72 -3
- package/src/claude/model-info.ts +38 -15
- package/src/claude/outbound.ts +70 -16
- package/src/cli/account-api.ts +35 -1
- package/src/cli/account-auth.ts +33 -6
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +389 -2
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +30 -6
- package/src/cli/agent.ts +45 -1
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +29 -4
- package/src/cli/claude.ts +103 -34
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +2 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +8 -0
- package/src/cli/config-command.ts +74 -10
- package/src/cli/dispatch.ts +593 -0
- package/src/cli/doctor.ts +315 -43
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +46 -20
- package/src/cli/help.ts +20 -271
- package/src/cli/index.ts +378 -519
- package/src/cli/init.ts +4 -17
- package/src/cli/integrations.ts +120 -2
- package/src/cli/lab.ts +607 -0
- package/src/cli/launcher-context.ts +77 -0
- package/src/cli/minimax.ts +497 -0
- package/src/cli/models-runtime.ts +35 -2
- package/src/cli/models.ts +100 -14
- package/src/cli/observe.ts +92 -3
- package/src/cli/opencode.ts +4 -2
- package/src/cli/provider-runtime.ts +18 -1
- package/src/cli/provider.ts +24 -3
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +437 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +6 -3
- package/src/cli/star-prompt.ts +71 -15
- package/src/cli/status.ts +10 -3
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +153 -6
- package/src/cli/v2.ts +105 -10
- package/src/cli.ts +1 -1
- package/src/clients/config-export.ts +1358 -21
- package/src/codex/account-label.ts +14 -1
- package/src/codex/account-lifecycle.ts +130 -13
- package/src/codex/account-namespaces.ts +49 -3
- package/src/codex/account-priority.ts +83 -0
- package/src/codex/account-store.ts +29 -2
- package/src/codex/account-usability.ts +25 -2
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/app-server-processes.ts +493 -106
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +849 -242
- package/src/codex/auth-collision.ts +5 -3
- package/src/codex/auth-context.ts +345 -32
- package/src/codex/autostart-health.ts +8 -1
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +68 -10
- package/src/codex/catalog/bundled.ts +331 -33
- package/src/codex/catalog/effort.ts +121 -30
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +529 -45
- package/src/codex/catalog/native-models.ts +72 -0
- package/src/codex/catalog/parsing.ts +224 -30
- package/src/codex/catalog/provider-fetch.ts +1460 -134
- package/src/codex/catalog/sync.ts +1449 -186
- package/src/codex/catalog-admission.ts +199 -0
- package/src/codex/catalog-refresh-status.ts +105 -0
- package/src/codex/catalog-write-serialization.ts +242 -0
- package/src/codex/catalog.ts +6 -3
- package/src/codex/codex-write-lock.ts +384 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +651 -0
- package/src/codex/coordinator-doctor.ts +332 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/features.ts +636 -39
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +407 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-migration-guardian.ts +26 -20
- package/src/codex/history-provider.ts +231 -28
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +220 -0
- package/src/codex/inject-coordination.ts +290 -0
- package/src/codex/inject.ts +1073 -152
- package/src/codex/injected-marker.ts +37 -3
- package/src/codex/integration-record.ts +266 -0
- package/src/codex/internal/catalog-writer.ts +203 -0
- package/src/codex/internal/history-writer.ts +80 -0
- package/src/codex/journal.ts +66 -4
- package/src/codex/log-guard/inspect.ts +506 -0
- package/src/codex/log-guard/lock.ts +150 -0
- package/src/codex/log-guard/maintenance.ts +403 -0
- package/src/codex/log-guard/path-safety.ts +88 -0
- package/src/codex/log-guard/policy.ts +44 -0
- package/src/codex/log-guard/processes.ts +205 -0
- package/src/codex/log-guard/protection.ts +489 -0
- package/src/codex/log-guard/sqlite-errors.ts +9 -0
- package/src/codex/main-account-cache.ts +24 -0
- package/src/codex/main-account.ts +29 -1
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +56 -10
- package/src/codex/model-entitlements.ts +353 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +178 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +492 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +682 -0
- package/src/codex/paths.ts +80 -1
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +1 -1
- package/src/codex/pool-rotation.ts +74 -4
- package/src/codex/project-config-warnings.ts +20 -6
- package/src/codex/prompt-journal.ts +352 -0
- package/src/codex/prompt-layers.ts +967 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +175 -13
- package/src/codex/refresh.ts +11 -2
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +505 -94
- package/src/codex/runtime.ts +159 -38
- package/src/codex/shim.ts +1009 -28
- package/src/codex/subagent-model-fallback.ts +350 -35
- package/src/codex/sync.ts +191 -2
- package/src/codex/transition-state.ts +612 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +557 -0
- package/src/codex/warmup.ts +187 -81
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +20 -0
- package/src/combos/index.ts +4 -0
- package/src/combos/request.ts +32 -0
- package/src/combos/types.ts +81 -9
- package/src/config/provider-name.ts +24 -0
- package/src/config.ts +1762 -140
- package/src/generated/compatibility-version.json +3164 -0
- package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
- package/src/grok/inject.ts +16 -5
- package/src/grok/inspect.ts +45 -0
- package/src/grok/sync.ts +2 -2
- package/src/images/loop.ts +152 -29
- package/src/images/plan.ts +23 -13
- package/src/integrations/config-io.ts +269 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/mutation-flight.ts +71 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/omp-yaml-source.ts +358 -0
- package/src/integrations/owned-refresh.ts +74 -0
- package/src/integrations/ownership.ts +111 -0
- package/src/integrations/registry.ts +159 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +361 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +691 -0
- package/src/lab/artifacts/sanitize.ts +586 -0
- package/src/lab/artifacts/secure-fs.ts +475 -0
- package/src/lab/artifacts/store.ts +310 -0
- package/src/lab/automation/budgets.ts +78 -0
- package/src/lab/automation/config-persistence.ts +256 -0
- package/src/lab/automation/constants.ts +39 -0
- package/src/lab/automation/cooldown.ts +103 -0
- package/src/lab/automation/dispatch.ts +211 -0
- package/src/lab/automation/index.ts +13 -0
- package/src/lab/automation/orchestrator.ts +499 -0
- package/src/lab/automation/persistence.ts +512 -0
- package/src/lab/automation/planner.ts +371 -0
- package/src/lab/automation/policy.ts +136 -0
- package/src/lab/automation/queue.ts +191 -0
- package/src/lab/automation/recovery.ts +24 -0
- package/src/lab/automation/route-context.ts +21 -0
- package/src/lab/automation/run-key.ts +44 -0
- package/src/lab/automation/runs-query.ts +34 -0
- package/src/lab/automation/types.ts +160 -0
- package/src/lab/conformance/assertion.ts +325 -0
- package/src/lab/conformance/digest.ts +22 -0
- package/src/lab/conformance/executor.ts +741 -0
- package/src/lab/conformance/fixture-provider.ts +27 -0
- package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
- package/src/lab/conformance/harness-budget.ts +47 -0
- package/src/lab/conformance/index.ts +5 -0
- package/src/lab/conformance/jcs.ts +64 -0
- package/src/lab/conformance/json-pointer.ts +39 -0
- package/src/lab/conformance/manifest.ts +180 -0
- package/src/lab/conformance/mcp-stub.ts +179 -0
- package/src/lab/conformance/negative-controls.ts +164 -0
- package/src/lab/conformance/observation.ts +355 -0
- package/src/lab/conformance/runner.ts +68 -0
- package/src/lab/conformance/sse-normalize.ts +59 -0
- package/src/lab/conformance/suite-manifest.ts +78 -0
- package/src/lab/conformance/types.ts +214 -0
- package/src/lab/constants.ts +126 -0
- package/src/lab/digest.ts +64 -0
- package/src/lab/events/errors.ts +9 -0
- package/src/lab/events/limits.ts +117 -0
- package/src/lab/events/types.ts +229 -0
- package/src/lab/events/validate.ts +781 -0
- package/src/lab/fabric/constants.ts +40 -0
- package/src/lab/fabric/executor.ts +492 -0
- package/src/lab/fabric/index.ts +80 -0
- package/src/lab/fabric/manifest.ts +222 -0
- package/src/lab/fabric/observe.ts +489 -0
- package/src/lab/fabric/patch.ts +79 -0
- package/src/lab/fabric/producer-child.ts +139 -0
- package/src/lab/fabric/producer-isolate.ts +276 -0
- package/src/lab/fabric/producer-protocol.ts +61 -0
- package/src/lab/fabric/scratch.ts +439 -0
- package/src/lab/fabric/subject.ts +106 -0
- package/src/lab/fabric/types.ts +134 -0
- package/src/lab/fabric/verifier.ts +98 -0
- package/src/lab/index.ts +54 -0
- package/src/lab/ledger/artifact-refs.ts +127 -0
- package/src/lab/ledger/invalidation.ts +136 -0
- package/src/lab/ledger/purge.ts +310 -0
- package/src/lab/ledger/store.ts +532 -0
- package/src/lab/live/credential-lease.ts +53 -0
- package/src/lab/live/destination.ts +155 -0
- package/src/lab/live/executor.ts +336 -0
- package/src/lab/live/inert-tools.ts +56 -0
- package/src/lab/live/manifest.ts +85 -0
- package/src/lab/live/mcp-loopback.ts +57 -0
- package/src/lab/live/runner.ts +19 -0
- package/src/lab/live/sandbox.ts +61 -0
- package/src/lab/live/suite-manifest.ts +41 -0
- package/src/lab/live/transport.ts +118 -0
- package/src/lab/live/types.ts +197 -0
- package/src/lab/observe/from-conformance.ts +301 -0
- package/src/lab/observe/from-live.ts +117 -0
- package/src/lab/paths.ts +153 -0
- package/src/lab/projection/rebuild.ts +495 -0
- package/src/lab/projection/schema.ts +135 -0
- package/src/lab/projection/verdicts.ts +474 -0
- package/src/lab/projection/verification.ts +412 -0
- package/src/lab/public/bundle.ts +217 -0
- package/src/lab/public/community-authority.ts +175 -0
- package/src/lab/public/community-files.ts +29 -0
- package/src/lab/public/community.ts +479 -0
- package/src/lab/public/file-safety.ts +155 -0
- package/src/lab/public/ids.ts +26 -0
- package/src/lab/public/index.ts +16 -0
- package/src/lab/public/mutation-lock.ts +424 -0
- package/src/lab/public/operator.ts +353 -0
- package/src/lab/public/origin-purge.ts +79 -0
- package/src/lab/public/origin.ts +203 -0
- package/src/lab/public/privacy.ts +143 -0
- package/src/lab/public/private-file.ts +261 -0
- package/src/lab/public/project.ts +124 -0
- package/src/lab/public/purge-test-fault.ts +21 -0
- package/src/lab/public/purge.ts +223 -0
- package/src/lab/public/registry.ts +44 -0
- package/src/lab/public/revocation.ts +252 -0
- package/src/lab/public/signature.ts +243 -0
- package/src/lab/public/storage.ts +105 -0
- package/src/lab/public/strict-json.ts +206 -0
- package/src/lab/public/time.ts +26 -0
- package/src/lab/public/types.ts +172 -0
- package/src/lab/public/validate.ts +391 -0
- package/src/lab/query/catalog.ts +101 -0
- package/src/lab/query/connection.ts +107 -0
- package/src/lab/query/constants.ts +4 -0
- package/src/lab/query/cursor.ts +132 -0
- package/src/lab/query/dto-map.ts +277 -0
- package/src/lab/query/errors.ts +22 -0
- package/src/lab/query/freshness.ts +53 -0
- package/src/lab/query/index.ts +45 -0
- package/src/lab/query/latest-observation.ts +59 -0
- package/src/lab/query/passive-production.ts +159 -0
- package/src/lab/query/queries.ts +444 -0
- package/src/lab/query/types.ts +266 -0
- package/src/lab/subject/behavior-fingerprint.ts +77 -0
- package/src/lab/subject/installation-salt.ts +112 -0
- package/src/lab/subject/protocol-subject.ts +80 -0
- package/src/lab/subject/route-subject.ts +74 -0
- package/src/lib/app-owned-memory-stores.ts +22 -0
- package/src/lib/bounded-body.ts +153 -9
- package/src/lib/bun-runtime.ts +125 -12
- package/src/lib/bun-stream-caps.ts +13 -9
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +6 -2
- package/src/lib/destination-policy.ts +65 -1
- package/src/lib/errors.ts +44 -2
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/lab-activation.ts +223 -0
- package/src/lib/lab-live-execution-authority.ts +13 -0
- package/src/lib/lab-live-host.ts +30 -0
- package/src/lib/lab-live-pinned-sender.ts +56 -0
- package/src/lib/lab-live-route-production.ts +130 -0
- package/src/lib/lab-passive-linker-registration.ts +26 -0
- package/src/lib/local-management-attestation.ts +51 -0
- package/src/lib/local-management-capability.ts +100 -0
- package/src/lib/local-provider-reload-contract.ts +100 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/pinned-http.ts +145 -26
- package/src/lib/process-control.ts +4 -1
- package/src/lib/provider-outbound.ts +49 -9
- package/src/lib/redact.ts +419 -3
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/shadow-call.ts +35 -4
- package/src/lib/sse-decoder.ts +41 -0
- package/src/lib/state-store-registrations.ts +10 -2
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/token-estimate.ts +19 -2
- package/src/lib/tool-argument-integers.ts +202 -0
- package/src/lib/translator-budget.ts +44 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +156 -3
- package/src/lib/windows-atomic-replace.ts +155 -0
- package/src/lib/windows-elevation.ts +70 -2
- package/src/lib/windows-secret-acl.ts +409 -69
- package/src/lib/windows-service-wrappers.ts +72 -0
- package/src/lib/windows-text.ts +106 -0
- package/src/lib/windows-user-principal.ts +341 -0
- package/src/lib/winsw.ts +33 -5
- package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
- package/src/oauth/account-import/index.ts +15 -0
- package/src/oauth/account-import/parser.ts +83 -0
- package/src/oauth/account-import/registry.ts +18 -0
- package/src/oauth/account-import/service.ts +75 -0
- package/src/oauth/account-import/types.ts +91 -0
- package/src/oauth/anthropic.ts +12 -1
- package/src/oauth/callback-server.ts +8 -2
- package/src/oauth/chatgpt.ts +12 -1
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +46 -5
- package/src/oauth/google-antigravity.ts +35 -3
- package/src/oauth/health.ts +20 -12
- package/src/oauth/index.ts +398 -66
- package/src/oauth/key-providers.ts +16 -0
- package/src/oauth/kimi.ts +16 -2
- package/src/oauth/kiro.ts +50 -6
- package/src/oauth/local-token-detect.ts +11 -2
- package/src/oauth/log.ts +3 -1
- package/src/oauth/login-cli.ts +88 -28
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/store.ts +119 -21
- package/src/oauth/token-guardian.ts +9 -3
- package/src/pi/models.ts +2 -2
- package/src/providers/alibaba-region-migration.ts +1 -1
- package/src/providers/antigravity-models.ts +521 -31
- package/src/providers/base-url-choices.ts +10 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +144 -0
- package/src/providers/context-cap.ts +22 -5
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/derive.ts +253 -6
- package/src/providers/fastwire.ts +501 -0
- package/src/providers/free-directory.ts +10 -7
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +71 -3
- package/src/providers/label.ts +1 -1
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +115 -22
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/openai-sidecar.ts +72 -4
- package/src/providers/openai-tier-startup.ts +31 -2
- package/src/providers/openai-tiers.ts +119 -4
- package/src/providers/openai-virtual-models.ts +1 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +29 -0
- package/src/providers/quota.ts +1319 -38
- package/src/providers/registry.ts +1429 -111
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +42 -6
- package/src/providers/static-model-discovery.ts +86 -0
- package/src/providers/xai-responses-opt-in.ts +15 -0
- package/src/providers/xai-transport.ts +11 -4
- package/src/reasoning-effort.ts +49 -1
- package/src/responses/compaction.ts +26 -1
- package/src/responses/custom-tool-compat.ts +266 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +355 -0
- package/src/responses/parser.ts +220 -38
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +9 -1
- package/src/responses/reasoning-replay-cache.ts +426 -0
- package/src/responses/schema.ts +7 -1
- package/src/responses/spill-store.ts +75 -10
- package/src/responses/state.ts +565 -27
- package/src/responses/thought-signature-replay.ts +347 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/router.ts +366 -30
- package/src/routing/analytics.ts +378 -0
- package/src/routing/capability.ts +244 -0
- package/src/routing/compatibility/assemble.ts +73 -0
- package/src/routing/compatibility/behavior.ts +278 -0
- package/src/routing/compatibility/catalog.ts +99 -0
- package/src/routing/compatibility/endpoint.ts +52 -0
- package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
- package/src/routing/compatibility/policy.ts +181 -0
- package/src/routing/compatibility/provider-slot.ts +56 -0
- package/src/routing/compatibility/reader.ts +110 -0
- package/src/routing/compatibility/subject.ts +191 -0
- package/src/routing/compatibility/types.ts +64 -0
- package/src/routing/compatibility/version.ts +104 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +495 -0
- package/src/routing/health.ts +412 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +547 -0
- package/src/routing/quota.ts +145 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +776 -0
- package/src/server/adapter-resolve.ts +2 -29
- package/src/server/auth-cors.ts +267 -46
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +130 -56
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +426 -0
- package/src/server/claude-messages.ts +159 -43
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +18 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +39 -10
- package/src/server/images.ts +94 -12
- package/src/server/index.ts +865 -181
- package/src/server/lifecycle.ts +284 -13
- package/src/server/live.ts +136 -17
- package/src/server/local-management-read-client.ts +90 -0
- package/src/server/local-provider-reload-client.ts +137 -0
- package/src/server/management/agent-settings-routes.ts +398 -103
- package/src/server/management/api-key-usage.ts +31 -5
- package/src/server/management/body.ts +6 -0
- package/src/server/management/combo-routes.ts +62 -24
- package/src/server/management/config-routes.ts +464 -51
- package/src/server/management/context.ts +80 -2
- package/src/server/management/integration-routes.ts +498 -0
- package/src/server/management/lab-automation-routes.ts +206 -0
- package/src/server/management/lab-routes.ts +563 -0
- package/src/server/management/logs-usage-routes.ts +101 -32
- package/src/server/management/model-routes.ts +189 -131
- package/src/server/management/model-rows.ts +163 -0
- package/src/server/management/native-integration-routes.ts +769 -0
- package/src/server/management/oauth-account-routes.ts +80 -4
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +764 -157
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +380 -0
- package/src/server/management/shared.ts +27 -11
- package/src/server/management/sidebar-routes.ts +47 -31
- package/src/server/management/storage-log-guard-routes.ts +186 -0
- package/src/server/management/sync-response.ts +69 -0
- package/src/server/management/system-restart.ts +288 -32
- package/src/server/management/system-routes.ts +77 -0
- package/src/server/management/usage-summary-cache.ts +9 -1
- package/src/server/management/vision-sidecar-options.ts +167 -0
- package/src/server/management/web-search-sidecar-options.ts +120 -0
- package/src/server/management-api.ts +115 -14
- package/src/server/management-auth.ts +220 -5
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/ports.ts +41 -1
- package/src/server/proxy-liveness.ts +132 -5
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +82 -42
- package/src/server/relay.ts +236 -76
- package/src/server/request-decompress.ts +113 -6
- package/src/server/request-log.ts +235 -22
- package/src/server/responses/agent-task-recovery-cache.ts +143 -0
- package/src/server/responses/agent-task-recovery.ts +465 -0
- package/src/server/responses/collaboration.ts +204 -35
- package/src/server/responses/compact.ts +442 -55
- package/src/server/responses/core.ts +2872 -331
- package/src/server/responses/empty-completion-guard.ts +276 -0
- package/src/server/responses/encrypted-payload.ts +62 -39
- package/src/server/responses/fetch-helpers.ts +79 -4
- package/src/server/responses/input-admission.ts +185 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +251 -0
- package/src/server/responses/terminal-guard.ts +26 -5
- package/src/server/responses/upstream-error.ts +5 -0
- package/src/server/responses/ws-upstream.ts +308 -0
- package/src/server/responses-custom-tool-repair.ts +282 -0
- package/src/server/responses-item-id-repair.ts +54 -6
- package/src/server/responses-json-events.ts +90 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses-terminal-repair.ts +342 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +153 -0
- package/src/server/responses.ts +18 -2
- package/src/server/search.ts +78 -13
- package/src/server/sse-frame-buffer.ts +292 -0
- package/src/server/sse-payload-rewrite.ts +110 -22
- package/src/server/startup-action-control.ts +8 -1
- package/src/server/startup-health-cache.ts +19 -1
- package/src/server/system-env.ts +80 -9
- package/src/server/ws-bridge.ts +39 -38
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +1111 -90
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/storage/cleanup.ts +2 -2
- package/src/storage/scanner.ts +1 -1
- package/src/storage/worker-lifecycle.ts +14 -14
- package/src/tray/windows-tray.ps1 +83 -9
- package/src/tray/windows.ts +43 -16
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +845 -0
- package/src/types/provider.ts +545 -0
- package/src/types/request.ts +384 -0
- package/src/types/tools.ts +131 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +104 -1236
- package/src/update/index.ts +32 -19
- package/src/update/job.ts +442 -67
- package/src/update/notify.ts +12 -6
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +259 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/expected-prices.ts +268 -16
- package/src/usage/log.ts +606 -41
- package/src/usage/summary.ts +177 -9
- package/src/usage/user-cost-overlay-reconciler.ts +313 -0
- package/src/usage/user-cost-overlays.ts +314 -0
- package/src/vision/anthropic-describe.ts +10 -6
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +9 -3
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +238 -24
- package/src/vision/reasoning.ts +55 -0
- package/src/vision/routed-describe.ts +175 -0
- package/src/vision/timeout-bounds.ts +9 -0
- package/src/web-search/anthropic-executor.ts +13 -7
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +88 -0
- package/src/web-search/executor.ts +11 -3
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +150 -15
- package/src/web-search/loop.ts +279 -50
- package/src/web-search/parse.ts +125 -30
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/xai-executor.ts +219 -0
- package/gui/dist/assets/index-DTpMHS4F.js +0 -67
- package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
- package/gui/dist/provider-icons/antigravity.svg +0 -1
- package/gui/dist/provider-icons/claude.svg +0 -1
- package/gui/dist/provider-icons/copilot.svg +0 -1
- package/gui/dist/provider-icons/cursor.svg +0 -2
- package/gui/dist/provider-icons/gemini.svg +0 -1
- package/gui/dist/provider-icons/grok-color.svg +0 -1
- package/gui/dist/provider-icons/kiro.svg +0 -14
- package/src/cli/internal-dispatch.ts +0 -20
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import type { CodexAccountMode, OcxProviderConfig } from "../types";
|
|
1
|
+
import type { CodexAccountMode, FastWire, OcxProviderConfig } from "../types";
|
|
2
|
+
import { fastWireDeclarationError } from "./fastwire";
|
|
2
3
|
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 { ANTIGRAVITY_MODELS, ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, ANTIGRAVITY_MODEL_EFFORTS, ANTIGRAVITY_MODEL_INPUT_MODALITIES } from "./antigravity-models";
|
|
4
5
|
import type { ProviderBaseUrlChoice } from "./base-url-choices";
|
|
5
6
|
import {
|
|
6
7
|
QWEN_CLOUD_BASE_URL_CHOICES, QWEN_CLOUD_TOKEN_PLAN_BASE_URL,
|
|
7
8
|
ALIBABA_INTL_BASE_URL_CHOICES, ALIBABA_INTL_TOKEN_PLAN_BASE_URL,
|
|
8
9
|
ALIBABA_CODING_BASE_URL_CHOICES, ALIBABA_CODING_INTL_BASE_URL,
|
|
10
|
+
MOONSHOT_BASE_URL_CHOICES, MOONSHOT_INTL_BASE_URL,
|
|
9
11
|
} from "./base-url-choices";
|
|
10
12
|
import {
|
|
13
|
+
CURSOR_NO_VISION_MODELS,
|
|
11
14
|
CURSOR_STATIC_MODELS,
|
|
12
15
|
cursorModelContextWindows,
|
|
13
16
|
cursorModelIds,
|
|
14
17
|
cursorModelInputModalities,
|
|
15
18
|
cursorModelReasoningEfforts,
|
|
16
19
|
} from "../adapters/cursor/discovery";
|
|
20
|
+
import { COMMAND_CODE_MODEL_REASONING_EFFORTS } from "./command-code-efforts";
|
|
21
|
+
import { isCanonicalOpenRouterTarget } from "./openrouter-routing";
|
|
17
22
|
|
|
18
23
|
export type ProviderAuthKind = "forward" | "oauth" | "key" | "local";
|
|
19
24
|
export type MetadataModelIdNormalize = "case-insensitive";
|
|
@@ -27,9 +32,20 @@ export type InboundWire = "responses" | "chat" | "anthropic";
|
|
|
27
32
|
|
|
28
33
|
/**
|
|
29
34
|
* A per-model wire default: a bare string applies to every inbound, while the object
|
|
30
|
-
* form
|
|
35
|
+
* form may scope the default to listed inbound protocols and authentication modes.
|
|
31
36
|
*/
|
|
32
|
-
export type ModelWireDefault = string | {
|
|
37
|
+
export type ModelWireDefault = string | {
|
|
38
|
+
wire: string;
|
|
39
|
+
inbound: readonly InboundWire[];
|
|
40
|
+
authModes?: readonly ProviderAuthKind[];
|
|
41
|
+
/** Whether this registry-selected route may relay a caller-owned service_tier. */
|
|
42
|
+
forwardCallerServiceTier?: boolean;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export interface ResponsesTerminalRepairPolicy {
|
|
46
|
+
/** Quiet time after a structurally complete output graph before synthesizing completion. */
|
|
47
|
+
graceMs: number;
|
|
48
|
+
}
|
|
33
49
|
|
|
34
50
|
export type ProviderModelDiscoveryScalar = string | number | boolean;
|
|
35
51
|
|
|
@@ -73,6 +89,11 @@ interface ProviderModelDiscoverySharedSpec {
|
|
|
73
89
|
maxResponseBytes?: number;
|
|
74
90
|
/** Optional lower raw-row ceiling; the process-wide hard ceiling still wins. */
|
|
75
91
|
maxModels?: number;
|
|
92
|
+
/**
|
|
93
|
+
* If a valid extracted id starts with this prefix, strip it and re-validate the remainder.
|
|
94
|
+
* Empty/invalid remainders skip that row only.
|
|
95
|
+
*/
|
|
96
|
+
stripIdPrefix?: string;
|
|
76
97
|
}
|
|
77
98
|
|
|
78
99
|
type ProviderModelDiscoveryLocation =
|
|
@@ -110,6 +131,11 @@ export interface ProviderRegistryEntry {
|
|
|
110
131
|
allowKeyAuthOverride?: boolean;
|
|
111
132
|
allowPrivateNetworkByDefault?: boolean;
|
|
112
133
|
keyOptional?: boolean;
|
|
134
|
+
/**
|
|
135
|
+
* Registry-only key-login policy for public model catalogs that cannot authenticate a key.
|
|
136
|
+
* The dashboard flow then reports the key as unverifiable instead of a false positive.
|
|
137
|
+
*/
|
|
138
|
+
apiKeyValidation?: "unknown";
|
|
113
139
|
/**
|
|
114
140
|
* Free-tier pricing (no paid subscription required). Distinct from `keyOptional`:
|
|
115
141
|
* free tiers may still require an API key (e.g. NVIDIA NIM free credits).
|
|
@@ -148,6 +174,29 @@ export interface ProviderRegistryEntry {
|
|
|
148
174
|
* of paying a translation hop.
|
|
149
175
|
*/
|
|
150
176
|
modelWireDefaults?: Record<string, ModelWireDefault>;
|
|
177
|
+
/** Explicit Fast wire declaration; absence derives from the final model adapter. */
|
|
178
|
+
fastWire?: FastWire | null;
|
|
179
|
+
/**
|
|
180
|
+
* Registry-only per-model override for the upstream request shape used behind a
|
|
181
|
+
* Codex Responses WebSocket turn. `false` keeps the client-facing WebSocket but
|
|
182
|
+
* asks the upstream Responses endpoint for bounded JSON, which the bridge then
|
|
183
|
+
* reframes as Responses events. Use only for upstreams whose streaming response
|
|
184
|
+
* can omit or indefinitely delay the terminal event.
|
|
185
|
+
*/
|
|
186
|
+
modelResponsesUpstreamStreaming?: Record<string, boolean>;
|
|
187
|
+
/** Registry-only repair for a model whose native Responses stream may omit its terminal. */
|
|
188
|
+
modelResponsesTerminalRepair?: Record<string, ResponsesTerminalRepairPolicy>;
|
|
189
|
+
/**
|
|
190
|
+
* Registry-only client-facing item-id repair policy (#938), filled onto the
|
|
191
|
+
* runtime provider only when the user has no explicit policy (derive.ts);
|
|
192
|
+
* never seeded into saved config.
|
|
193
|
+
*/
|
|
194
|
+
responsesItemIdRepair?: {
|
|
195
|
+
message?: string[];
|
|
196
|
+
reasoning?: string[];
|
|
197
|
+
repairMissingTerminalIds?: boolean;
|
|
198
|
+
repairInvalidIds?: boolean;
|
|
199
|
+
};
|
|
151
200
|
/**
|
|
152
201
|
* Responses-API resource path for providers whose route is not `/v1/responses`.
|
|
153
202
|
* Unlike `modelWireDefaults` above, this IS seeded into saved config: it describes
|
|
@@ -161,6 +210,46 @@ export interface ProviderRegistryEntry {
|
|
|
161
210
|
* replay miss are repaired rather than forwarded.
|
|
162
211
|
*/
|
|
163
212
|
statelessResponses?: boolean;
|
|
213
|
+
/**
|
|
214
|
+
* Responses parser requires an unambiguous call batch and its matched result batch
|
|
215
|
+
* to stay contiguous. This is seeded/backfilled like other fixed wire capabilities.
|
|
216
|
+
*/
|
|
217
|
+
requiresAdjacentResponsesToolResults?: boolean;
|
|
218
|
+
/**
|
|
219
|
+
* Registry default for the provider's `service_tier` support; see
|
|
220
|
+
* `OcxProviderConfig.supportsServiceTier`. Registry-only: backfilled (never
|
|
221
|
+
* overriding) at enrich/route time and deliberately NOT seeded into saved
|
|
222
|
+
* config, so an explicit user value stays distinguishable from the default
|
|
223
|
+
* (and the canonical openai seed comparison keeps its exact key set).
|
|
224
|
+
*/
|
|
225
|
+
supportsServiceTier?: boolean;
|
|
226
|
+
/** Registry default for OpenAI extended hosted web_search field support. */
|
|
227
|
+
supportsOpenAiWebSearchToolFields?: boolean;
|
|
228
|
+
/** Registry default for native Responses custom-tool support. */
|
|
229
|
+
supportsResponsesCustomTools?: boolean;
|
|
230
|
+
/** Registry default for exact model service-tier capability; explicit config keys win. */
|
|
231
|
+
modelSupportsServiceTier?: Record<string, boolean>;
|
|
232
|
+
/**
|
|
233
|
+
* Registry-only service-tier defaults for an OAuth preset's explicit API-key transport.
|
|
234
|
+
* Applied only when `allowKeyAuthOverride` is true and the captured effective auth transport
|
|
235
|
+
* is key-based. Explicit provider config still wins field-by-field, including `false`.
|
|
236
|
+
*/
|
|
237
|
+
keyAuthServiceTier?: {
|
|
238
|
+
supportsServiceTier?: boolean;
|
|
239
|
+
modelSupportsServiceTier?: Record<string, boolean>;
|
|
240
|
+
chatServiceTier?: boolean;
|
|
241
|
+
};
|
|
242
|
+
/** Provider-specific copy for the Codex catalog's Fast tier. */
|
|
243
|
+
fastTierDescription?: string;
|
|
244
|
+
/**
|
|
245
|
+
* Registry-only destination guard for `modelSupportsServiceTier`. This scopes vendor evidence
|
|
246
|
+
* without changing provider ownership, routing, authentication, or config validation.
|
|
247
|
+
*/
|
|
248
|
+
modelServiceTierCapabilityBaseUrlGuard?: (baseUrl: string) => boolean;
|
|
249
|
+
/** Registry default for plaintext reasoning replay; see `OcxProviderConfig.preserveResponsesReasoningContent`. Registry-only like `supportsServiceTier`. */
|
|
250
|
+
preserveResponsesReasoningContent?: boolean;
|
|
251
|
+
/** Registry defaults for per-model Codex reasoning propagation; explicit user keys win during enrichment. */
|
|
252
|
+
modelSupportsReasoningSummaries?: Record<string, boolean>;
|
|
164
253
|
modelDiscovery?: ProviderModelDiscoverySpec;
|
|
165
254
|
contextWindow?: number;
|
|
166
255
|
modelContextWindows?: Record<string, number>;
|
|
@@ -172,6 +261,13 @@ export interface ProviderRegistryEntry {
|
|
|
172
261
|
modelDefaultReasoningEfforts?: Record<string, string>;
|
|
173
262
|
reasoningEffortMap?: Record<string, string>;
|
|
174
263
|
modelReasoningEffortMap?: Record<string, Record<string, string>>;
|
|
264
|
+
/**
|
|
265
|
+
* Registry-authoritative models that send OpenAI's direct `reasoning_effort` field.
|
|
266
|
+
* Runtime enrichment uses this to repair stale preset metadata that still classifies a model
|
|
267
|
+
* as a thinking-budget/toggle model. This is registry-only and is never persisted as user config.
|
|
268
|
+
*/
|
|
269
|
+
directReasoningEffortModels?: string[];
|
|
270
|
+
reasoningWireFormat?: OcxProviderConfig["reasoningWireFormat"];
|
|
175
271
|
noVisionModels?: string[];
|
|
176
272
|
noReasoningModels?: string[];
|
|
177
273
|
noTemperatureModels?: string[];
|
|
@@ -181,8 +277,17 @@ export interface ProviderRegistryEntry {
|
|
|
181
277
|
parallelToolCalls?: boolean;
|
|
182
278
|
/** Opt this provider into forwarding prompt_cache_key (OpenAI-specific; strict backends reject it). */
|
|
183
279
|
promptCacheKey?: boolean;
|
|
280
|
+
/**
|
|
281
|
+
* Opt-in: forward `service_tier` on the `/chat/completions` wire. Same hazard as
|
|
282
|
+
* `promptCacheKey` — an OpenAI-specific extension that strict gateways reject. Distinct from
|
|
283
|
+
* `supportsServiceTier`, which governs the Responses wire.
|
|
284
|
+
*/
|
|
285
|
+
chatServiceTier?: boolean;
|
|
286
|
+
/** OpenAI Chat EOF policy for gateways that omit terminal frames after complete tool calls. */
|
|
287
|
+
openaiChatEofTolerance?: boolean;
|
|
184
288
|
autoToolChoiceOnlyModels?: string[];
|
|
185
289
|
preserveReasoningContentModels?: string[];
|
|
290
|
+
requiresReasoningPlaceholderModels?: string[];
|
|
186
291
|
reasoningSplitModels?: string[];
|
|
187
292
|
thinkingToggleModels?: string[];
|
|
188
293
|
thinkingBudgetModels?: string[];
|
|
@@ -203,9 +308,9 @@ export type ProviderConfigSeed = Pick<
|
|
|
203
308
|
"adapter" | "baseUrl" | "apiKeyTransport" | "responsesPath" | "authMode" | "keyOptional" | "freeTier" | "modelSuffixBracketStrip" | "defaultModel" | "models"
|
|
204
309
|
| "liveModels" | "contextWindow" | "modelContextWindows" | "modelInputModalities"
|
|
205
310
|
| "modelMaxInputTokens" | "defaultMaxOutputTokens" | "modelMaxOutputTokens"
|
|
206
|
-
| "reasoningEfforts" | "modelReasoningEfforts" | "modelDefaultReasoningEfforts" | "reasoningEffortMap" | "modelReasoningEffortMap"
|
|
311
|
+
| "reasoningEfforts" | "modelReasoningEfforts" | "modelDefaultReasoningEfforts" | "reasoningEffortMap" | "modelReasoningEffortMap" | "reasoningWireFormat"
|
|
207
312
|
| "noVisionModels" | "noReasoningModels" | "noTemperatureModels" | "noTopPModels" | "noPenaltyModels"
|
|
208
|
-
| "autoToolChoiceOnlyModels" | "preserveReasoningContentModels" | "reasoningSplitModels" | "thinkingToggleModels" | "thinkingBudgetModels" | "escapeBuiltinToolNames"
|
|
313
|
+
| "autoToolChoiceOnlyModels" | "preserveReasoningContentModels" | "requiresReasoningPlaceholderModels" | "reasoningSplitModels" | "thinkingToggleModels" | "thinkingBudgetModels" | "escapeBuiltinToolNames" | "openaiChatEofTolerance"
|
|
209
314
|
| "googleMode" | "project" | "location" | "headers"
|
|
210
315
|
>;
|
|
211
316
|
|
|
@@ -214,10 +319,32 @@ export type ProviderConfigSeed = Pick<
|
|
|
214
319
|
// 260710 context refresh: Tier-2 evidence in
|
|
215
320
|
// devlog/_plan/260710_provider_hardening/001_research_frontier.md.
|
|
216
321
|
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 };
|
|
322
|
+
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-opus-4-7": 1_000_000, "claude-opus-4-6": 1_000_000, "claude-sonnet-4-6": 1_000_000, "claude-haiku-4-5": 200_000 };
|
|
218
323
|
|
|
324
|
+
// 260814 GLM-5.3 is registered pre-emptively alongside 5.2 everywhere 5.2 appears. Z.AI's
|
|
325
|
+
// devpack "How to Switch Models" page (docs.z.ai/devpack/latest-model) lists glm-5.3 and
|
|
326
|
+
// glm-5.3[1m] as Coding Plan ids on the unchanged endpoints; the capability and pricing
|
|
327
|
+
// tables were not published yet, so every 5.3 row mirrors its 5.2 sibling until they settle.
|
|
328
|
+
// The non-Z.AI providers below are speculative on purpose: they carry 5.2 today and are
|
|
329
|
+
// expected to pick 5.3 up on their usual lag. Providers whose live /v1/models discovery is
|
|
330
|
+
// enabled self-correct on the next successful fetch; static ones need a follow-up refresh.
|
|
331
|
+
const ZAI_GLM_53_MODELS = ["glm-5.3", "glm-5.3[1m]"];
|
|
219
332
|
const ZAI_GLM_52_MODELS = ["glm-5.2", "glm-5.2[1m]"];
|
|
333
|
+
const ZAI_GLM_5X_MODELS = [...ZAI_GLM_53_MODELS, ...ZAI_GLM_52_MODELS];
|
|
220
334
|
const ZAI_GLM_52_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
335
|
+
/**
|
|
336
|
+
* GLM-5.3 does NOT share 5.2's five-tier ladder. docs.z.ai/devpack/latest-model folds every
|
|
337
|
+
* incoming effort into three effective tiers — low/minimal/light -> low, medium/high -> high,
|
|
338
|
+
* xhigh/max/ultra -> max — with max as both the default and the unknown-value fallback.
|
|
339
|
+
* Advertising five levels would publish two picker rows that are indistinguishable on the wire,
|
|
340
|
+
* so only the effective tiers are exposed (same treatment Cursor and Baseten already give GLM).
|
|
341
|
+
*/
|
|
342
|
+
const ZAI_GLM_53_REASONING_EFFORTS = ["low", "high", "max"];
|
|
343
|
+
/** Per-model ladders for the Coding Plan rows: 5.3 gets its three effective tiers, 5.2 keeps five. */
|
|
344
|
+
const ZAI_GLM_5X_REASONING_EFFORTS: Record<string, string[]> = {
|
|
345
|
+
...Object.fromEntries(ZAI_GLM_53_MODELS.map(id => [id, ZAI_GLM_53_REASONING_EFFORTS])),
|
|
346
|
+
...Object.fromEntries(ZAI_GLM_52_MODELS.map(id => [id, ZAI_GLM_52_REASONING_EFFORTS])),
|
|
347
|
+
};
|
|
221
348
|
// 260710 MiniMax models and context windows: Tier-2 evidence in
|
|
222
349
|
// devlog/_plan/260710_provider_hardening/002_research_cn.md.
|
|
223
350
|
const MINIMAX_MODELS = [
|
|
@@ -243,12 +370,6 @@ const MINIMAX_M3_REASONING_EFFORT_MAP: Record<string, string> = {
|
|
|
243
370
|
const OPENAI_GPT56_MODELS = ["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna"];
|
|
244
371
|
const OPENAI_GPT56_PRO_MODELS = ["gpt-5.6-sol-pro", "gpt-5.6-terra-pro", "gpt-5.6-luna-pro"];
|
|
245
372
|
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
373
|
const OPENAI_API_GPT56_CONTEXT_WINDOWS: Record<string, number> = {
|
|
253
374
|
...Object.fromEntries([...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS].map(id => [id, OPENAI_API_GPT56_CONTEXT_WINDOW])),
|
|
254
375
|
"gpt-5.5": OPENAI_API_GPT56_CONTEXT_WINDOW,
|
|
@@ -263,6 +384,37 @@ const OPENAI_API_GPT56_VIRTUAL_MODELS: Record<string, { wireModelId: string; rea
|
|
|
263
384
|
"gpt-5.6-luna-pro": { wireModelId: "gpt-5.6-luna", reasoningMode: "pro" },
|
|
264
385
|
};
|
|
265
386
|
const OPENAI_API_GPT56_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
387
|
+
/**
|
|
388
|
+
* Daybreak program aliases. These `-latest` ids are the stable contract: OpenAI repoints
|
|
389
|
+
* them at newer snapshots over time (red -> gpt-5.6-cyber, blue -> gpt-5.6-sol as of
|
|
390
|
+
* 2026-08-11), so registering the ALIAS inherits future model swaps while a pinned
|
|
391
|
+
* snapshot id would silently go stale. Snapshot ids are deliberately absent here.
|
|
392
|
+
* Responses-only per both published endpoint tables (`v1/chat/completions` is marked
|
|
393
|
+
* Not supported) — never add these to a chat-completions provider. Access needs separate
|
|
394
|
+
* Daybreak approval and provisioning, so neither is ever a default.
|
|
395
|
+
* Verified 2026-08-11: developers.openai.com/api/docs/models/daybreak-red-latest.md
|
|
396
|
+
* and .../daybreak-blue-latest.md
|
|
397
|
+
*/
|
|
398
|
+
const OPENAI_DAYBREAK_MODELS = ["daybreak-red-latest", "daybreak-blue-latest"];
|
|
399
|
+
const OPENAI_DAYBREAK_CONTEXT_WINDOWS: Record<string, number> = {
|
|
400
|
+
"daybreak-red-latest": 400_000,
|
|
401
|
+
"daybreak-blue-latest": 1_050_000,
|
|
402
|
+
};
|
|
403
|
+
const OPENAI_DAYBREAK_MAX_INPUT_TOKENS: Record<string, number> = {
|
|
404
|
+
"daybreak-red-latest": 272_000,
|
|
405
|
+
"daybreak-blue-latest": 922_000,
|
|
406
|
+
};
|
|
407
|
+
/**
|
|
408
|
+
* Neither Daybreak page publishes a reasoning-effort ladder. An explicit empty array means
|
|
409
|
+
* "expose no effort control"; OMITTING the key would instead fall back to the full routed
|
|
410
|
+
* ladder (`configuredReasoningEfforts` returns undefined -> `applyReasoningLevels` uses
|
|
411
|
+
* ROUTED_REASONING_LEVELS), which would advertise efforts the models never documented.
|
|
412
|
+
* `noReasoningModels` is wrong here: both pages document reasoning-token support, so these
|
|
413
|
+
* are reasoning models with no *selectable* ladder.
|
|
414
|
+
*/
|
|
415
|
+
const OPENAI_DAYBREAK_REASONING_EFFORTS: Record<string, string[]> = Object.fromEntries(
|
|
416
|
+
OPENAI_DAYBREAK_MODELS.map(id => [id, [] as string[]]),
|
|
417
|
+
);
|
|
266
418
|
const OPENROUTER_GPT56_MODELS = OPENAI_GPT56_MODELS.map(id => `openai/${id}`);
|
|
267
419
|
// OpenRouter's live /endpoints routes report 1,050,000; keep this separate from the
|
|
268
420
|
// unverified OpenAI API-key seed. Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
|
|
@@ -298,47 +450,137 @@ const OPENCODE_GO_THINKING_TOGGLE_MODELS = [
|
|
|
298
450
|
* images through the proxy's vision sidecar (src/codex/catalog/provider-fetch.ts), a claim nobody
|
|
299
451
|
* has verified for BigModel-hosted GLM.
|
|
300
452
|
*/
|
|
301
|
-
const ZHIPU_BIGMODEL_TEXT_MODELS = ["glm-4.6", "glm-4.7", "glm-4.7-flash", "glm-5", "glm-5.1"];
|
|
453
|
+
const ZHIPU_BIGMODEL_TEXT_MODELS = ["glm-4.6", "glm-4.7", "glm-4.7-flash", "glm-5", "glm-5.1", "glm-5.2", "glm-5.3"];
|
|
302
454
|
const ZHIPU_BIGMODEL_MODELS = [...ZHIPU_BIGMODEL_TEXT_MODELS, "glm-4.6v"];
|
|
303
455
|
const ZHIPU_BIGMODEL_INPUT_MODALITIES: Record<string, string[]> = {
|
|
304
456
|
...Object.fromEntries(ZHIPU_BIGMODEL_TEXT_MODELS.map(id => [id, ["text"]])),
|
|
305
457
|
"glm-4.6v": ["text", "image"],
|
|
306
458
|
};
|
|
307
|
-
const ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS = ["glm-4.6", "glm-4.7", "glm-5", "glm-5.1"];
|
|
459
|
+
const ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS = ["glm-4.6", "glm-4.7", "glm-5", "glm-5.1", "glm-5.2", "glm-5.3"];
|
|
308
460
|
const THINKING_BUDGET_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
461
|
+
// Qwen3.8-Max is the first Qwen3.x model with official direct `reasoning_effort` support.
|
|
462
|
+
// Evidence: https://qwen.ai/blog?id=qwen3.8
|
|
463
|
+
const QWEN38_REASONING_EFFORTS = ["low", "medium", "xhigh"];
|
|
309
464
|
const THINKING_BUDGET_MODELS = [
|
|
310
465
|
"qwen3.5-397b", "qwen3.6-35b",
|
|
311
466
|
"qwen3.5-plus", "qwen3.6-plus", "qwen3.7-max", "qwen3.7-plus",
|
|
312
467
|
];
|
|
313
468
|
const OPENCODE_GO_THINKING_BUDGET_MODELS = ["qwen3.5-plus", "qwen3.6-plus", "qwen3.7-max", "qwen3.7-plus"];
|
|
314
469
|
const DEEPSEEK_THINKING_MODELS = ["deepseek-v4-pro", "deepseek-v4-flash"];
|
|
470
|
+
/*
|
|
471
|
+
* DeepSeek's experimental vision preview (released 2026-08-21, api-docs.deepseek.com):
|
|
472
|
+
* text+image input on the V4 Flash base. DeepSeek positions it as a preview id;
|
|
473
|
+
* the expectation is that vision merges into `deepseek-v4-flash` proper later,
|
|
474
|
+
* at which point this id retires the same way deepseek-chat/reasoner did.
|
|
475
|
+
*/
|
|
476
|
+
const DEEPSEEK_VISION_PREVIEW_MODEL = "deepseek-v4-flash-vision-exp";
|
|
315
477
|
const OPENCODE_FREE_DEEPSEEK_MODELS = ["deepseek-v4-flash-free"];
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
478
|
+
/*
|
|
479
|
+
* OpenCode Zen's free slug for the OpenRouter stealth model "Ox Alpha"
|
|
480
|
+
* (openrouter.ai/stealth/ox-alpha): 1,048,576-token context, multimodal
|
|
481
|
+
* (text+image+video upstream; Zen serves text+image), mandatory reasoning,
|
|
482
|
+
* free during the stealth window. Zen displays it as "Ox Alpha Free" under
|
|
483
|
+
* this exact id (opencode.ai/docs/zen, verified 2026-08-21).
|
|
484
|
+
*/
|
|
485
|
+
const OPENCODE_OX_ALPHA_FREE_MODEL = "x-preview-f-free";
|
|
486
|
+
const OX_ALPHA_CONTEXT_WINDOW = 1_048_576;
|
|
487
|
+
/*
|
|
488
|
+
* Zen free models that reject `image_url` upstream (#1043, and the reproducible
|
|
489
|
+
* half of #1024).
|
|
490
|
+
*
|
|
491
|
+
* Zen publishes NO modality metadata — its `/v1/models` returns only id, object,
|
|
492
|
+
* created, owned_by — so this list is measured, not derived. Each id was probed
|
|
493
|
+
* once against https://opencode.ai/zen/v1 on 2026-08-05 with a text control first
|
|
494
|
+
* and then a 1x1 PNG; the six below failed the image request, four of them with
|
|
495
|
+
* `[404] No endpoints found that support image input` and `big-pickle` with the
|
|
496
|
+
* exact deserialize error quoted in #1043.
|
|
497
|
+
*
|
|
498
|
+
* `mimo-v2.5-free` and `longcat-2.0-free` ACCEPT images and are deliberately
|
|
499
|
+
* absent. Adding them would silently replace a working image with a caption,
|
|
500
|
+
* which is worse than the loud 400 this list exists to prevent — see the negative
|
|
501
|
+
* assertion in tests/provider-registry-parity.test.ts.
|
|
502
|
+
*
|
|
503
|
+
* Zen's roster is discovered live while this list is static, so it is a dated
|
|
504
|
+
* exception list, not a capability model. Re-probe before extending it.
|
|
505
|
+
* Evidence: devlog/_fin/260805_bug_fix_stack/002_zen_modality_probe.md
|
|
506
|
+
*/
|
|
507
|
+
const OPENCODE_ZEN_TEXT_ONLY_MODELS = [
|
|
508
|
+
"big-pickle",
|
|
509
|
+
"nemotron-3-ultra-free",
|
|
510
|
+
"ling-3.0-flash-free",
|
|
511
|
+
"north-mini-code-free",
|
|
512
|
+
"laguna-s-2.1-free",
|
|
513
|
+
"deepseek-v4-flash-free",
|
|
514
|
+
];
|
|
515
|
+
/*
|
|
516
|
+
* DeepSeek's Codex ladder is low/high/max. With the V4 Pro GA release
|
|
517
|
+
* (DeepSeek-V4-Pro-0813) the official thinking-mode table is IDENTICAL for both
|
|
518
|
+
* V4 models (api-docs.deepseek.com/guides/thinking_mode, verified 2026-08-13):
|
|
519
|
+
*
|
|
520
|
+
* requested | v4-flash | v4-pro
|
|
521
|
+
* low | low | low
|
|
522
|
+
* medium | high | high
|
|
523
|
+
* high | high | high
|
|
524
|
+
* xhigh | high | high
|
|
525
|
+
* max | max | max
|
|
526
|
+
*
|
|
527
|
+
* Before GA, Pro silently upgraded low->high and mapped xhigh->max (#1057-era
|
|
528
|
+
* table); the page's footnote about an early-August Pro mapping update landed
|
|
529
|
+
* with this GA, so Pro now advertises the same three real tiers as Flash.
|
|
530
|
+
*
|
|
531
|
+
* Two standing notes (#1057):
|
|
532
|
+
*
|
|
533
|
+
* - `xhigh` is a COMPATIBILITY ALIAS, not a native tier. It stays in the wire maps
|
|
534
|
+
* so existing requests and saved configs keep working, but it is not advertised.
|
|
535
|
+
* - `medium` has no row in the vendor table — mapping it to `high` is OUR
|
|
536
|
+
* compatibility choice for clients that only speak the OpenAI ladder.
|
|
537
|
+
*/
|
|
538
|
+
const DEEPSEEK_FLASH_THINKING_EFFORTS = ["low", "high", "max"];
|
|
539
|
+
const DEEPSEEK_PRO_THINKING_EFFORTS = ["low", "high", "max"];
|
|
540
|
+
const DEEPSEEK_PRO_REASONING_MAP: Record<string, string> = {
|
|
541
|
+
low: "low",
|
|
321
542
|
medium: "high",
|
|
322
543
|
high: "high",
|
|
323
|
-
xhigh: "
|
|
544
|
+
xhigh: "high",
|
|
324
545
|
max: "max",
|
|
325
546
|
};
|
|
547
|
+
const DEEPSEEK_FLASH_REASONING_MAP: Record<string, string> = {
|
|
548
|
+
low: "low",
|
|
549
|
+
medium: "high",
|
|
550
|
+
high: "high",
|
|
551
|
+
xhigh: "high",
|
|
552
|
+
max: "max",
|
|
553
|
+
};
|
|
554
|
+
/**
|
|
555
|
+
* Flash-versus-Pro classification for DeepSeek V4 model ids, including prefixed
|
|
556
|
+
* (`deepseek/deepseek-v4-pro`) and suffixed (`deepseek-v4-flash-free`) forms.
|
|
557
|
+
* `tests/provider-registry-parity.test.ts` enumerates every id the registry
|
|
558
|
+
* actually passes here, so a future id this substring test would misread cannot
|
|
559
|
+
* land silently.
|
|
560
|
+
*/
|
|
561
|
+
const isDeepseekFlashModel = (modelId: string): boolean =>
|
|
562
|
+
modelId.toLowerCase().includes("flash");
|
|
563
|
+
const deepseekThinkingEffortsFor = (modelId: string): string[] =>
|
|
564
|
+
isDeepseekFlashModel(modelId) ? DEEPSEEK_FLASH_THINKING_EFFORTS : DEEPSEEK_PRO_THINKING_EFFORTS;
|
|
565
|
+
const deepseekReasoningMapFor = (modelId: string): Record<string, string> =>
|
|
566
|
+
isDeepseekFlashModel(modelId) ? DEEPSEEK_FLASH_REASONING_MAP : DEEPSEEK_PRO_REASONING_MAP;
|
|
326
567
|
// 260719 Alibaba Token Plan Personal Edition (China/Beijing). Keep it distinct from
|
|
327
568
|
// Coding Plan: the products use different exact allowlists and different base URLs.
|
|
328
569
|
// Evidence: https://help.aliyun.com/en/model-studio/token-plan-personal-overview
|
|
329
570
|
// https://help.aliyun.com/en/model-studio/token-plan-quickstart
|
|
330
571
|
const ALIBABA_TOKEN_PLAN_MODELS = [
|
|
331
|
-
"qwen3.8-max
|
|
332
|
-
"glm-5.2", "deepseek-v4-pro",
|
|
572
|
+
"qwen3.8-max", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-flash",
|
|
573
|
+
"glm-5.3", "glm-5.2", "deepseek-v4-pro",
|
|
333
574
|
];
|
|
334
575
|
const ALIBABA_TOKEN_PLAN_QWEN_MODELS = [
|
|
335
|
-
"qwen3.8-max
|
|
576
|
+
"qwen3.8-max", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-flash",
|
|
336
577
|
];
|
|
337
578
|
const ALIBABA_TOKEN_PLAN_INPUT_MODALITIES: Record<string, string[]> = {
|
|
338
|
-
"qwen3.8-max
|
|
579
|
+
"qwen3.8-max": ["text", "image"],
|
|
339
580
|
"qwen3.7-max": ["text", "image"],
|
|
340
581
|
"qwen3.7-plus": ["text", "image"],
|
|
341
582
|
"qwen3.6-flash": ["text", "image"],
|
|
583
|
+
"glm-5.3": ["text"],
|
|
342
584
|
"glm-5.2": ["text"],
|
|
343
585
|
"deepseek-v4-pro": ["text"],
|
|
344
586
|
};
|
|
@@ -348,14 +590,14 @@ const ALIBABA_TOKEN_PLAN_INPUT_MODALITIES: Record<string, string[]> = {
|
|
|
348
590
|
// Evidence: https://www.alibabacloud.com/help/en/model-studio/token-plan-overview
|
|
349
591
|
// https://qwencloud.com/pricing/token-plan (qwen3.8 metadata)
|
|
350
592
|
const ALIBABA_INTL_TOKEN_PLAN_MODELS = [
|
|
351
|
-
"qwen3.8-max
|
|
593
|
+
"qwen3.8-max", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", "qwen3.6-flash",
|
|
352
594
|
"deepseek-v4-pro", "deepseek-v4-flash", "deepseek-v3.2",
|
|
353
595
|
"kimi-k2.7-code", "kimi-k2.6", "kimi-k2.5",
|
|
354
|
-
"glm-5.2", "glm-5.1", "glm-5",
|
|
596
|
+
"glm-5.3", "glm-5.2", "glm-5.1", "glm-5",
|
|
355
597
|
"MiniMax-M2.5",
|
|
356
598
|
];
|
|
357
599
|
const ALIBABA_INTL_TOKEN_PLAN_QWEN_MODELS = [
|
|
358
|
-
"qwen3.8-max
|
|
600
|
+
"qwen3.8-max", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", "qwen3.6-flash",
|
|
359
601
|
];
|
|
360
602
|
|
|
361
603
|
// 260722 Tencent Cloud Coding Plan. The plan's model set is explicitly dynamic; these are the
|
|
@@ -377,7 +619,7 @@ const TENCENT_CODING_PLAN_MODELS = ["tc-code-latest", "glm-5", "kimi-k2.5", "min
|
|
|
377
619
|
// is documented as grounds for suspension — see the `note` on both Plan entries.
|
|
378
620
|
// Report a break by opening an issue tagging the owner; the three things that rot first are the
|
|
379
621
|
// static catalogs (liveModels:false cannot self-heal), the base URLs, and those Plan terms.
|
|
380
|
-
// Full evidence ledger: devlog/
|
|
622
|
+
// Full evidence ledger: devlog/_fin/260801_pr611_volcengine_evidence/000_evidence_ledger.md
|
|
381
623
|
const VOLCENGINE_ARK_MODELS = [
|
|
382
624
|
"doubao-seed-2-1-pro-260628",
|
|
383
625
|
"doubao-seed-2-1-turbo-260628",
|
|
@@ -385,6 +627,8 @@ const VOLCENGINE_ARK_MODELS = [
|
|
|
385
627
|
"deepseek-v4-pro-260425",
|
|
386
628
|
"deepseek-v4-flash-260425",
|
|
387
629
|
"deepseek-v3-2-251201",
|
|
630
|
+
// No glm-5-3 row: Ark pins date-stamped snapshot ids (glm-5-2-260617) that cannot be
|
|
631
|
+
// guessed ahead of the vendor publishing them. Add it once /api/v3/models lists one.
|
|
388
632
|
"glm-5-2-260617",
|
|
389
633
|
"glm-4-7-251222",
|
|
390
634
|
];
|
|
@@ -398,6 +642,7 @@ const VOLCENGINE_CODING_PLAN_MODELS = [
|
|
|
398
642
|
"doubao-seed-2.0-code",
|
|
399
643
|
"deepseek-v4-pro",
|
|
400
644
|
"deepseek-v4-flash",
|
|
645
|
+
"glm-5.3",
|
|
401
646
|
"glm-5.2",
|
|
402
647
|
"kimi-k2.6",
|
|
403
648
|
"minimax-m3",
|
|
@@ -405,6 +650,7 @@ const VOLCENGINE_CODING_PLAN_MODELS = [
|
|
|
405
650
|
const VOLCENGINE_AGENT_PLAN_MODELS = [
|
|
406
651
|
"deepseek-v4-pro",
|
|
407
652
|
"deepseek-v4-flash",
|
|
653
|
+
"glm-5.3",
|
|
408
654
|
"glm-5.2",
|
|
409
655
|
"kimi-k2.6",
|
|
410
656
|
"minimax-m3",
|
|
@@ -422,11 +668,12 @@ const VOLCENGINE_PLAN_TEXT_ONLY_MODELS = [
|
|
|
422
668
|
"doubao-seed-2.0-code",
|
|
423
669
|
"deepseek-v4-pro",
|
|
424
670
|
"deepseek-v4-flash",
|
|
671
|
+
"glm-5.3",
|
|
425
672
|
"glm-5.2",
|
|
426
673
|
"doubao-seed-2.0-pro",
|
|
427
674
|
];
|
|
428
675
|
const ALIBABA_INTL_TOKEN_PLAN_INPUT_MODALITIES: Record<string, string[]> = {
|
|
429
|
-
"qwen3.8-max
|
|
676
|
+
"qwen3.8-max": ["text", "image"],
|
|
430
677
|
"qwen3.7-max": ["text", "image"],
|
|
431
678
|
"qwen3.7-plus": ["text", "image"],
|
|
432
679
|
"qwen3.6-plus": ["text", "image"],
|
|
@@ -437,6 +684,7 @@ const ALIBABA_INTL_TOKEN_PLAN_INPUT_MODALITIES: Record<string, string[]> = {
|
|
|
437
684
|
"kimi-k2.7-code": ["text", "image"],
|
|
438
685
|
"kimi-k2.6": ["text", "image"],
|
|
439
686
|
"kimi-k2.5": ["text", "image"],
|
|
687
|
+
"glm-5.3": ["text"],
|
|
440
688
|
"glm-5.2": ["text"],
|
|
441
689
|
"glm-5.1": ["text"],
|
|
442
690
|
"glm-5": ["text"],
|
|
@@ -496,6 +744,72 @@ const NVIDIA_NIM_KIMI_MODELS = [
|
|
|
496
744
|
...NVIDIA_NIM_KIMI_THINKING_MODELS,
|
|
497
745
|
"moonshotai/kimi-k2-instruct", "moonshotai/kimi-k2-instruct-0905",
|
|
498
746
|
];
|
|
747
|
+
/**
|
|
748
|
+
* 260804 issue #956: NIM publishes no input-modality metadata on `/v1/models`, so the
|
|
749
|
+
* registry is the only source of truth for which models can see images.
|
|
750
|
+
*
|
|
751
|
+
* Two lists, both verified per-model against NVIDIA documentation on 2026-08-04
|
|
752
|
+
* (build.nvidia.com model pages and docs.api.nvidia.com/nim/reference/*). Evidence and
|
|
753
|
+
* the per-id audit: devlog/_fin/260804_stack7_service_vision/011_nim_id_audit.md.
|
|
754
|
+
*
|
|
755
|
+
* Read `noVisionModels` carefully — it lists models that CANNOT see images, which is
|
|
756
|
+
* what routes them through the proxy's vision sidecar (src/vision/index.ts) and makes the
|
|
757
|
+
* catalog advertise image input for them. Membership is wrong in BOTH directions:
|
|
758
|
+
* - a text-only model missing from it keeps issue #956 (images blocked or rejected);
|
|
759
|
+
* - a vision model wrongly IN it gets its image silently replaced by another model's
|
|
760
|
+
* text description — no error, worse answers, extra cost.
|
|
761
|
+
*
|
|
762
|
+
* A new NIM id must be classified DELIBERATELY against its NVIDIA page, never assumed
|
|
763
|
+
* from its name: `google/gemma-4-31b-it` carries no vision marker yet accepts images,
|
|
764
|
+
* `-vl` also appears on embedding/reranking models, and `google/codegemma-7b` is
|
|
765
|
+
* text-only while `google/codegemma-1.1-7b` has no current page at all. An unclassified
|
|
766
|
+
* id is intentionally left alone rather than defaulted, because NIM serves non-chat
|
|
767
|
+
* endpoints (embeddings, rerankers, guards, OCR) that reach the same code path.
|
|
768
|
+
*/
|
|
769
|
+
const NVIDIA_NIM_VISION_MODELS = [
|
|
770
|
+
"meta/llama-3.2-11b-vision-instruct", "meta/llama-3.2-90b-vision-instruct",
|
|
771
|
+
"nvidia/llama-3.1-nemotron-nano-vl-8b-v1", "nvidia/nemotron-nano-12b-v2-vl",
|
|
772
|
+
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning", "nvidia/cosmos3-nano-reasoner",
|
|
773
|
+
"nvidia/ising-calibration-1.5-31b", "nvidia/ising-calibration-1-35b-a3b",
|
|
774
|
+
"google/gemma-4-31b-it", "google/diffusiongemma-26b-a4b-it",
|
|
775
|
+
"minimaxai/minimax-m3", "moonshotai/kimi-k2.6", "moonshotai/kimi-k2.5",
|
|
776
|
+
"stepfun-ai/step-3.7-flash", "thinkingmachines/inkling",
|
|
777
|
+
"mistralai/mistral-medium-3.5-128b",
|
|
778
|
+
];
|
|
779
|
+
/**
|
|
780
|
+
* The catalog advertises image input only for `noVisionModels` members, so a natively
|
|
781
|
+
* vision-capable model would otherwise be published as text-only and the Codex app would
|
|
782
|
+
* block attachments before the native path ever runs.
|
|
783
|
+
*/
|
|
784
|
+
const NVIDIA_NIM_VISION_INPUT_MODALITIES: Record<string, string[]> = Object.fromEntries(
|
|
785
|
+
NVIDIA_NIM_VISION_MODELS.map(id => [id, ["text", "image"]]),
|
|
786
|
+
);
|
|
787
|
+
/**
|
|
788
|
+
* Text-only NIM chat models — 26 ids, each carrying an explicit `Input Modalities: Text`
|
|
789
|
+
* (or equivalent) on its NVIDIA page. PR #964 proposed ~64; six of those are natively
|
|
790
|
+
* image-capable and live in NVIDIA_NIM_VISION_MODELS above, and 32 more had no current
|
|
791
|
+
* NVIDIA page and were dropped rather than assumed.
|
|
792
|
+
*
|
|
793
|
+
* kimi-k2-thinking and kimi-k2-instruct are text-only while k2.5/k2.6 are not — vision
|
|
794
|
+
* and reasoning are independent axes, so all four stay in NVIDIA_NIM_KIMI_MODELS for
|
|
795
|
+
* reasoning suppression regardless of which list they appear in here.
|
|
796
|
+
*/
|
|
797
|
+
const NVIDIA_NIM_NO_VISION_MODELS = [
|
|
798
|
+
"deepseek-ai/deepseek-v4-flash", "deepseek-ai/deepseek-v4-pro",
|
|
799
|
+
"google/codegemma-7b",
|
|
800
|
+
"meta/llama-3.1-70b-instruct", "meta/llama-3.1-8b-instruct",
|
|
801
|
+
"meta/llama-3.2-1b-instruct", "meta/llama-3.2-3b-instruct",
|
|
802
|
+
"meta/llama-3.3-70b-instruct", "meta/llama2-70b",
|
|
803
|
+
"mistralai/mistral-7b-instruct-v0.3", "mistralai/mistral-nemotron",
|
|
804
|
+
"moonshotai/kimi-k2-thinking", "moonshotai/kimi-k2-instruct",
|
|
805
|
+
"nvidia/llama-3.1-nemotron-nano-8b-v1", "nvidia/llama-3.1-nemotron-ultra-253b-v1",
|
|
806
|
+
"nvidia/llama-3.3-nemotron-super-49b-v1", "nvidia/llama-3.3-nemotron-super-49b-v1.5",
|
|
807
|
+
"nvidia/nemotron-3-nano-30b-a3b", "nvidia/nemotron-3-super-120b-a12b",
|
|
808
|
+
"nvidia/nemotron-3-ultra-550b-a55b", "nvidia/nemotron-mini-4b-instruct",
|
|
809
|
+
"nvidia/nvidia-nemotron-nano-9b-v2",
|
|
810
|
+
"openai/gpt-oss-120b", "openai/gpt-oss-20b",
|
|
811
|
+
"poolside/laguna-xs-2.1", "z-ai/glm-5.3", "z-ai/glm-5.2",
|
|
812
|
+
];
|
|
499
813
|
const KIMI_CODING_MODEL_CONTEXT_WINDOWS: Record<string, number> = Object.fromEntries(
|
|
500
814
|
KIMI_CODING_MODELS.map(id => [id, id === "k3[1m]" ? KIMI_K3_1M_CONTEXT_WINDOW : KIMI_K3_STANDARD_CONTEXT_WINDOW]),
|
|
501
815
|
);
|
|
@@ -503,6 +817,7 @@ const KIMI_CODING_MODEL_INPUT_MODALITIES = Object.fromEntries(
|
|
|
503
817
|
KIMI_CODING_K3_MODELS.map(id => [id, ["text", "image"]]),
|
|
504
818
|
);
|
|
505
819
|
const NEURALWATT_REASONING_HISTORY_MODELS = [
|
|
820
|
+
"glm-5.3", "glm-5.3-short",
|
|
506
821
|
"glm-5.2", "glm-5.2-short",
|
|
507
822
|
"kimi-k2.6", "kimi-k2.7-code",
|
|
508
823
|
"qwen3.5-397b", "qwen3.6-35b",
|
|
@@ -521,6 +836,9 @@ const BASETEN_MODEL_REASONING_EFFORTS: Record<string, string[]> = {
|
|
|
521
836
|
"thinkingmachines/inkling": BASETEN_FULL_REASONING_EFFORTS,
|
|
522
837
|
"openai/gpt-oss-120b": BASETEN_FULL_REASONING_EFFORTS,
|
|
523
838
|
"moonshotai/Kimi-K3": ["low", "high", "max"],
|
|
839
|
+
// 260814: GLM-5.3 honours low/high/max upstream, unlike 5.2's high/max on Baseten.
|
|
840
|
+
"zai-org/GLM-5.3": ["low", "high", "max"],
|
|
841
|
+
"zai-org/GLM-5.3-Fast": ["low", "high", "max"],
|
|
524
842
|
"zai-org/GLM-5.2": ["high", "max"],
|
|
525
843
|
"zai-org/GLM-5.2-Fast": ["high", "max"],
|
|
526
844
|
};
|
|
@@ -529,6 +847,8 @@ const BASETEN_MODEL_REASONING_EFFORT_MAP: Record<string, Record<string, string>>
|
|
|
529
847
|
"thinkingmachines/inkling": { none: "none", minimal: "minimal" },
|
|
530
848
|
"openai/gpt-oss-120b": { none: "none", minimal: "minimal" },
|
|
531
849
|
"moonshotai/Kimi-K3": { none: "none" },
|
|
850
|
+
"zai-org/GLM-5.3": { none: "none" },
|
|
851
|
+
"zai-org/GLM-5.3-Fast": { none: "none" },
|
|
532
852
|
"zai-org/GLM-5.2": { none: "none" },
|
|
533
853
|
"zai-org/GLM-5.2-Fast": { none: "none" },
|
|
534
854
|
};
|
|
@@ -544,21 +864,84 @@ const BASETEN_MODEL_INPUT_MODALITIES: Record<string, string[]> = {
|
|
|
544
864
|
"moonshotai/Kimi-K2.7-Code": ["text", "image"],
|
|
545
865
|
"moonshotai/Kimi-K3": ["text", "image"],
|
|
546
866
|
};
|
|
867
|
+
|
|
868
|
+
// 260801 DigitalOcean and Scaleway expose OpenAI-shaped `/v1/models` rows with only
|
|
869
|
+
// id/object/created/owned_by, while their shared serverless catalogs also contain
|
|
870
|
+
// non-chat and endpoint-specific models. Fail closed by intersecting live discovery
|
|
871
|
+
// with ids that the providers' current first-party model tables establish for Chat
|
|
872
|
+
// Completions. A newly listed id therefore needs a docs-backed registry refresh before
|
|
873
|
+
// it can enter the Codex catalog.
|
|
874
|
+
// Evidence: https://docs.digitalocean.com/products/inference/details/models/
|
|
875
|
+
// https://docs.digitalocean.com/reference/api/reference/serverless-inference/
|
|
876
|
+
// https://www.scaleway.com/en/docs/generative-apis/reference-content/supported-models/
|
|
877
|
+
const DIGITALOCEAN_CHAT_COMPLETION_MODELS = [
|
|
878
|
+
"arcee-trinity-large-thinking",
|
|
879
|
+
"openai-gpt-5.6-sol",
|
|
880
|
+
"openai-gpt-5.6-terra",
|
|
881
|
+
"openai-gpt-5.6-luna",
|
|
882
|
+
"qwen3-coder-flash",
|
|
883
|
+
"qwen3.5-397b-a17b",
|
|
884
|
+
"deepseek-v4-pro",
|
|
885
|
+
"deepseek-4-flash",
|
|
886
|
+
"deepseek-3.2",
|
|
887
|
+
"gemma-4-31B-it",
|
|
888
|
+
"minimax-m2.5",
|
|
889
|
+
"kimi-k3",
|
|
890
|
+
"kimi-k2.6",
|
|
891
|
+
"kimi-k2.5",
|
|
892
|
+
"llama3.3-70b-instruct",
|
|
893
|
+
"llama-4-maverick",
|
|
894
|
+
"mistral-3-14B",
|
|
895
|
+
"nemotron-3-ultra-550b",
|
|
896
|
+
"nvidia-nemotron-3-super-120b",
|
|
897
|
+
"nemotron-3-nano-omni",
|
|
898
|
+
"nemotron-nano-12b-v2-vl",
|
|
899
|
+
"mimo-v2.5-pro",
|
|
900
|
+
"glm-5.3",
|
|
901
|
+
"glm-5.2",
|
|
902
|
+
"glm-5.1",
|
|
903
|
+
"glm-5",
|
|
904
|
+
// The API reference uses this native slash id in its Chat Completions example.
|
|
905
|
+
"meta-llama/Meta-Llama-3.1-8B-Instruct",
|
|
906
|
+
] as const;
|
|
907
|
+
const SCALEWAY_SERVERLESS_CHAT_MODELS = [
|
|
908
|
+
"glm-5.3",
|
|
909
|
+
"glm-5.2",
|
|
910
|
+
// gpt-oss-120b is intentionally omitted: Scaleway requires Responses API for tool calling,
|
|
911
|
+
// while this preset routes Codex agent tools through Chat Completions.
|
|
912
|
+
"qwen3.6-35b-a3b",
|
|
913
|
+
"qwen3.5-397b-a17b",
|
|
914
|
+
"qwen3-235b-a22b-instruct-2507",
|
|
915
|
+
"qwen3-coder-30b-a3b-instruct",
|
|
916
|
+
"gemma-4-26b-a4b-it",
|
|
917
|
+
"llama-3.3-70b-instruct",
|
|
918
|
+
"mistral-medium-3.5-128b",
|
|
919
|
+
"mistral-small-3.2-24b-instruct-2506",
|
|
920
|
+
"pixtral-12b-2409",
|
|
921
|
+
] as const;
|
|
922
|
+
const SCALEWAY_MODEL_INPUT_MODALITIES: Record<string, string[]> = {
|
|
923
|
+
"pixtral-12b-2409": ["text", "image"],
|
|
924
|
+
};
|
|
547
925
|
const UMANS_MODELS = [
|
|
548
926
|
"umans-coder",
|
|
549
927
|
"umans-kimi-k2.7",
|
|
550
928
|
"umans-flash",
|
|
929
|
+
"umans-glm-5.3",
|
|
551
930
|
"umans-glm-5.2",
|
|
552
931
|
"umans-glm-5.1",
|
|
553
932
|
"umans-qwen3.6-35b-a3b",
|
|
554
933
|
];
|
|
555
934
|
const UMANS_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
556
935
|
const UMANS_GLM_REASONING_EFFORTS = ["high", "xhigh", "max"];
|
|
557
|
-
|
|
936
|
+
// 260814: Z.AI folds GLM-5.3 efforts into low/high/max, so `low` is a real tier here and
|
|
937
|
+
// `xhigh` is not distinct from `max` (docs.z.ai/devpack/latest-model).
|
|
938
|
+
const UMANS_GLM_53_REASONING_EFFORTS = ["low", "high", "max"];
|
|
939
|
+
const UMANS_TEXT_ONLY_MODELS = ["umans-glm-5.3", "umans-glm-5.2", "umans-glm-5.1"];
|
|
558
940
|
const UMANS_MODEL_CONTEXT_WINDOWS: Record<string, number> = {
|
|
559
941
|
"umans-coder": 262_144,
|
|
560
942
|
"umans-kimi-k2.7": 262_144,
|
|
561
943
|
"umans-flash": 262_144,
|
|
944
|
+
"umans-glm-5.3": 405_504,
|
|
562
945
|
"umans-glm-5.2": 405_504,
|
|
563
946
|
"umans-glm-5.1": 202_752,
|
|
564
947
|
"umans-qwen3.6-35b-a3b": 262_144,
|
|
@@ -566,6 +949,48 @@ const UMANS_MODEL_CONTEXT_WINDOWS: Record<string, number> = {
|
|
|
566
949
|
const UMANS_MODEL_INPUT_MODALITIES: Record<string, string[]> = Object.fromEntries(
|
|
567
950
|
UMANS_MODELS.map(id => [id, UMANS_TEXT_ONLY_MODELS.includes(id) ? ["text"] : ["text", "image"]]),
|
|
568
951
|
);
|
|
952
|
+
const CLINE_PASS_MODELS = [
|
|
953
|
+
"cline-pass/glm-5.3",
|
|
954
|
+
"cline-pass/glm-5.2",
|
|
955
|
+
"cline-pass/kimi-k3",
|
|
956
|
+
"cline-pass/kimi-k2.7-code",
|
|
957
|
+
"cline-pass/kimi-k2.6",
|
|
958
|
+
"cline-pass/deepseek-v4-pro",
|
|
959
|
+
"cline-pass/deepseek-v4-flash",
|
|
960
|
+
"cline-pass/mimo-v2.5",
|
|
961
|
+
"cline-pass/mimo-v2.5-pro",
|
|
962
|
+
"cline-pass/minimax-m3",
|
|
963
|
+
"cline-pass/qwen3.8-max",
|
|
964
|
+
"cline-pass/qwen3.7-max",
|
|
965
|
+
"cline-pass/qwen3.7-plus",
|
|
966
|
+
];
|
|
967
|
+
const CLINE_PASS_MODEL_CONTEXT_WINDOWS: Record<string, number> = {
|
|
968
|
+
"cline-pass/glm-5.3": 1_048_576,
|
|
969
|
+
"cline-pass/glm-5.2": 1_048_576,
|
|
970
|
+
"cline-pass/kimi-k3": 1_048_576,
|
|
971
|
+
"cline-pass/kimi-k2.7-code": 262_144,
|
|
972
|
+
"cline-pass/kimi-k2.6": 262_144,
|
|
973
|
+
"cline-pass/deepseek-v4-pro": 1_048_576,
|
|
974
|
+
"cline-pass/deepseek-v4-flash": 1_048_576,
|
|
975
|
+
"cline-pass/mimo-v2.5": 1_050_000,
|
|
976
|
+
"cline-pass/mimo-v2.5-pro": 1_050_000,
|
|
977
|
+
"cline-pass/minimax-m3": 1_048_576,
|
|
978
|
+
"cline-pass/qwen3.7-max": 1_000_000,
|
|
979
|
+
"cline-pass/qwen3.7-plus": 1_000_000,
|
|
980
|
+
};
|
|
981
|
+
const CLINE_PASS_IMAGE_MODELS = new Set([
|
|
982
|
+
"cline-pass/kimi-k3",
|
|
983
|
+
"cline-pass/kimi-k2.7-code",
|
|
984
|
+
"cline-pass/kimi-k2.6",
|
|
985
|
+
"cline-pass/mimo-v2.5",
|
|
986
|
+
"cline-pass/minimax-m3",
|
|
987
|
+
"cline-pass/qwen3.7-plus",
|
|
988
|
+
]);
|
|
989
|
+
const CLINE_PASS_MODALITY_KNOWN_MODELS = CLINE_PASS_MODELS.filter(id => id !== "cline-pass/qwen3.8-max");
|
|
990
|
+
const CLINE_PASS_TEXT_ONLY_MODELS = CLINE_PASS_MODALITY_KNOWN_MODELS.filter(id => !CLINE_PASS_IMAGE_MODELS.has(id));
|
|
991
|
+
const CLINE_PASS_MODEL_INPUT_MODALITIES: Record<string, string[]> = Object.fromEntries(
|
|
992
|
+
CLINE_PASS_MODALITY_KNOWN_MODELS.map(id => [id, CLINE_PASS_IMAGE_MODELS.has(id) ? ["text", "image"] : ["text"]]),
|
|
993
|
+
);
|
|
569
994
|
|
|
570
995
|
export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
571
996
|
{
|
|
@@ -575,6 +1000,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
575
1000
|
baseUrl: "https://chatgpt.com/backend-api/codex",
|
|
576
1001
|
authKind: "forward",
|
|
577
1002
|
codexAccountMode: "pool",
|
|
1003
|
+
supportsServiceTier: true,
|
|
578
1004
|
featured: true,
|
|
579
1005
|
note: "Codex login account pool (default) or Direct main-account mode via codexAccountMode",
|
|
580
1006
|
},
|
|
@@ -599,11 +1025,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
599
1025
|
// no-effort fallback to `kimi-k3-max` would never be reached. Mirrors the other K3
|
|
600
1026
|
// routes (kimi, kimi-code, opencode-go).
|
|
601
1027
|
modelDefaultReasoningEfforts: { "kimi-k3": "max" },
|
|
602
|
-
// Cursor
|
|
603
|
-
//
|
|
604
|
-
//
|
|
605
|
-
|
|
606
|
-
noVisionModels: cursorModelIds(CURSOR_STATIC_MODELS),
|
|
1028
|
+
// Blind Cursor models (Auto routers, Composer, GLM-5.2, GLM-5.3) go through the vision sidecar;
|
|
1029
|
+
// multimodal hosts (Claude/Gemini/GPT/Kimi/Grok) take native SelectedImage. The catalog
|
|
1030
|
+
// still advertises image for noVision members so Codex can attach (sidecar option B).
|
|
1031
|
+
noVisionModels: [...CURSOR_NO_VISION_MODELS],
|
|
607
1032
|
},
|
|
608
1033
|
{
|
|
609
1034
|
id: "xai",
|
|
@@ -612,9 +1037,21 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
612
1037
|
baseUrl: "https://api.x.ai/v1",
|
|
613
1038
|
authKind: "oauth",
|
|
614
1039
|
allowKeyAuthOverride: true,
|
|
1040
|
+
// Priority Processing is documented for xAI's public API-key Chat Completions and
|
|
1041
|
+
// Responses endpoints. OAuth is a separate Grok CLI subscription gateway and remains
|
|
1042
|
+
// unclassified; do not turn this into a provider-wide supportsServiceTier declaration.
|
|
1043
|
+
keyAuthServiceTier: {
|
|
1044
|
+
supportsServiceTier: true,
|
|
1045
|
+
chatServiceTier: true,
|
|
1046
|
+
},
|
|
1047
|
+
fastTierDescription: "Priority processing, 2x token price",
|
|
615
1048
|
featured: true,
|
|
616
1049
|
oauthId: "xai",
|
|
617
1050
|
jawcodeBundle: "xai",
|
|
1051
|
+
supportsOpenAiWebSearchToolFields: false,
|
|
1052
|
+
// Live A/B on 2026-08-20: xAI rejects native custom/custom_tool_call shapes while accepting
|
|
1053
|
+
// the otherwise-identical request after the custom tool is lowered to a function.
|
|
1054
|
+
supportsResponsesCustomTools: false,
|
|
618
1055
|
note: "Log in with your Grok account",
|
|
619
1056
|
// Parallel tool calls: officially supported and default-on per docs.x.ai function-calling
|
|
620
1057
|
// (verified 260709, devlog/_plan/260709_parallel_tool_calls). Streamed calls arrive whole
|
|
@@ -628,8 +1065,27 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
628
1065
|
// devlog/model_update/260709_model_refresh/001_xai_lineup.md.
|
|
629
1066
|
// grok-4.20-multi-agent-0309 is intentionally absent: the OAuth chat-completions
|
|
630
1067
|
// transport returns 400 ("Multi Agent requests are not allowed on chat completions").
|
|
631
|
-
|
|
1068
|
+
// 260813: grok-4.6 added per docs.x.ai/developers/grok-4-6. Context/vision still match
|
|
1069
|
+
// grok-4.5; the reasoning ladder does not — 4.6 adds the documented xhigh rung.
|
|
1070
|
+
models: ["grok-4.6", "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
1071
|
defaultModel: "grok-4.5",
|
|
1072
|
+
// Keep Codex Responses callers on the compatibility Chat wire until xAI can replay
|
|
1073
|
+
// opaque reasoning continuation and compaction state across later turns. The scoped
|
|
1074
|
+
// declaration also keeps caller-owned service tiers off the OAuth subscription route.
|
|
1075
|
+
modelWireDefaults: {
|
|
1076
|
+
"grok-4.6": {
|
|
1077
|
+
wire: "openai-chat",
|
|
1078
|
+
inbound: ["responses"],
|
|
1079
|
+
authModes: ["oauth"],
|
|
1080
|
+
forwardCallerServiceTier: false,
|
|
1081
|
+
},
|
|
1082
|
+
"grok-4.5": {
|
|
1083
|
+
wire: "openai-chat",
|
|
1084
|
+
inbound: ["responses"],
|
|
1085
|
+
authModes: ["oauth"],
|
|
1086
|
+
forwardCallerServiceTier: false,
|
|
1087
|
+
},
|
|
1088
|
+
},
|
|
633
1089
|
// Vision lineup per docs.x.ai model-capabilities/images/understanding: the grok-4.x chat
|
|
634
1090
|
// models accept image input (JPEG/PNG, URL or base64). Without this the catalog leaves
|
|
635
1091
|
// inputModalities undefined, and deriveComboCatalogModel defaults an undefined member to
|
|
@@ -637,6 +1093,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
637
1093
|
// the app blocks attachments client-side. grok-build-0.1 / grok-composer-2.5-fast stay out
|
|
638
1094
|
// (they are already listed in noVisionModels below).
|
|
639
1095
|
modelInputModalities: {
|
|
1096
|
+
"grok-4.6": ["text", "image"],
|
|
640
1097
|
"grok-4.5": ["text", "image"],
|
|
641
1098
|
"grok-4.3": ["text", "image"],
|
|
642
1099
|
"grok-4.20-0309-reasoning": ["text", "image"],
|
|
@@ -647,10 +1104,14 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
647
1104
|
// reasoning_content as the top cause of prompt-cache misses on multi-turn conversations
|
|
648
1105
|
// (docs.x.ai prompt-caching/multi-turn, verified 2026-07-13 — devlog/_plan/260713_grok_caching).
|
|
649
1106
|
// 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
|
|
652
|
-
|
|
1107
|
+
preserveReasoningContentModels: ["grok-4.6", "grok-4.5", "grok-4.3", "grok-4.20-0309-reasoning"],
|
|
1108
|
+
// grok-4.5 reasoning is always-on with low/medium/high (no off tier, no xhigh).
|
|
1109
|
+
// grok-4.6 adds xhigh per docs.x.ai/developers/model-capabilities/text/reasoning;
|
|
1110
|
+
// xAI documents high as the upstream default.
|
|
1111
|
+
modelReasoningEfforts: { "grok-4.6": ["low", "medium", "high", "xhigh"], "grok-4.5": ["low", "medium", "high"] },
|
|
1112
|
+
modelDefaultReasoningEfforts: { "grok-4.6": "high" },
|
|
653
1113
|
modelContextWindows: {
|
|
1114
|
+
"grok-4.6": 500_000,
|
|
654
1115
|
"grok-4.5": 500_000,
|
|
655
1116
|
"grok-4.3": 1_000_000,
|
|
656
1117
|
"grok-4.20-0309-reasoning": 1_000_000,
|
|
@@ -659,12 +1120,50 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
659
1120
|
},
|
|
660
1121
|
noVisionModels: ["grok-build-0.1", "grok-composer-2.5-fast"],
|
|
661
1122
|
},
|
|
1123
|
+
{
|
|
1124
|
+
id: "command-code",
|
|
1125
|
+
label: "Command Code - Auth",
|
|
1126
|
+
adapter: "command-code",
|
|
1127
|
+
baseUrl: "https://api.commandcode.ai",
|
|
1128
|
+
authKind: "oauth",
|
|
1129
|
+
oauthId: "command-code",
|
|
1130
|
+
featured: true,
|
|
1131
|
+
note: "Log in with your Command Code account",
|
|
1132
|
+
// OAuth needs one initial selection, but the exposed catalog is always discovered from the
|
|
1133
|
+
// signed-in account. Do not add a static model list here.
|
|
1134
|
+
defaultModel: "deepseek/deepseek-v4-flash",
|
|
1135
|
+
liveModels: true,
|
|
1136
|
+
modelDiscovery: {
|
|
1137
|
+
url: "https://api.commandcode.ai/provider/v1/models",
|
|
1138
|
+
maxResponseBytes: 262_144,
|
|
1139
|
+
maxModels: 256,
|
|
1140
|
+
},
|
|
1141
|
+
// These are capability facts from official Command Code model profiles, not seeded models.
|
|
1142
|
+
// Unknown/new live models deliberately do not advertise a reasoning picker.
|
|
1143
|
+
reasoningEfforts: [],
|
|
1144
|
+
modelReasoningEfforts: COMMAND_CODE_MODEL_REASONING_EFFORTS,
|
|
1145
|
+
// Ox Alpha (stealth preview, changelog v1.31.0): free 1M multimodal reasoning
|
|
1146
|
+
// model on every plan. DeepSeek vision preview id is preemptive metadata —
|
|
1147
|
+
// it is expected to merge into deepseek-v4-flash later.
|
|
1148
|
+
modelContextWindows: {
|
|
1149
|
+
"stealth/ox-alpha": OX_ALPHA_CONTEXT_WINDOW,
|
|
1150
|
+
[`deepseek/${DEEPSEEK_VISION_PREVIEW_MODEL}`]: 1_048_576,
|
|
1151
|
+
},
|
|
1152
|
+
modelInputModalities: {
|
|
1153
|
+
"stealth/ox-alpha": ["text", "image"],
|
|
1154
|
+
[`deepseek/${DEEPSEEK_VISION_PREVIEW_MODEL}`]: ["text", "image"],
|
|
1155
|
+
},
|
|
1156
|
+
defaultMaxOutputTokens: 64_000,
|
|
1157
|
+
// The proprietary generate wire has no verified per-request serialization flag.
|
|
1158
|
+
parallelToolCalls: false,
|
|
1159
|
+
},
|
|
662
1160
|
{
|
|
663
1161
|
id: "anthropic",
|
|
664
1162
|
label: "Anthropic Claude",
|
|
665
1163
|
adapter: "anthropic",
|
|
666
1164
|
baseUrl: "https://api.anthropic.com",
|
|
667
1165
|
authKind: "oauth",
|
|
1166
|
+
allowBaseUrlOverride: true,
|
|
668
1167
|
featured: true,
|
|
669
1168
|
oauthId: "anthropic",
|
|
670
1169
|
jawcodeBundle: "anthropic",
|
|
@@ -739,25 +1238,69 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
739
1238
|
modelContextWindows: KIRO_MODEL_CONTEXT_WINDOWS,
|
|
740
1239
|
modelReasoningEfforts: KIRO_MODEL_REASONING_EFFORTS,
|
|
741
1240
|
},
|
|
1241
|
+
{
|
|
1242
|
+
// Nous Portal — Nous Research subscription gateway (same backend Hermes Agent
|
|
1243
|
+
// uses). OAuth is a device grant (src/oauth/nous.ts): the access token IS the
|
|
1244
|
+
// per-request inference JWT (scope inference:invoke), refresh tokens are
|
|
1245
|
+
// single-use and rotated on every refresh. Catalog is a mix of paid models
|
|
1246
|
+
// (billed against the Portal subscription) and `:free` slugs (e.g.
|
|
1247
|
+
// tencent/hy3:free, stepfun/step-3.7-flash:free, inclusionai/ling-3.0-flash:free);
|
|
1248
|
+
// free-tier gating is decided live by the Portal per account, so discovery
|
|
1249
|
+
// from the signed-in account is authoritative; the static seed below is the
|
|
1250
|
+
// logged-out fallback and only lists free models verified on a real account
|
|
1251
|
+
// (2026-08-10): the Portal free list is authoritative and currently has
|
|
1252
|
+
// exactly 4 :free models: tencent/hy3:free, poolside/laguna-s-2.1:free,
|
|
1253
|
+
// stepfun/step-3.7-flash:free, poolside/laguna-xs-2.1:free.
|
|
1254
|
+
// inclusionai/ling-3.0-flash:free was removed from the Portal free list
|
|
1255
|
+
// (404 on the inference API since 2026-08-07) and must not be seeded.
|
|
1256
|
+
id: "nous",
|
|
1257
|
+
label: "Nous Portal",
|
|
1258
|
+
adapter: "openai-chat",
|
|
1259
|
+
baseUrl: "https://inference-api.nousresearch.com/v1",
|
|
1260
|
+
authKind: "oauth",
|
|
1261
|
+
oauthId: "nous",
|
|
1262
|
+
featured: true,
|
|
1263
|
+
// Mixed free + paid provider: the free tier is per-model (the `:free`
|
|
1264
|
+
// slugs), not a property of the whole provider, so freeTier stays false to
|
|
1265
|
+
// avoid implying every model is free.
|
|
1266
|
+
freeTier: false,
|
|
1267
|
+
dashboardUrl: "https://portal.nousresearch.com",
|
|
1268
|
+
defaultModel: "tencent/hy3:free",
|
|
1269
|
+
liveModels: true,
|
|
1270
|
+
models: ["tencent/hy3:free", "poolside/laguna-s-2.1:free", "stepfun/step-3.7-flash:free", "poolside/laguna-xs-2.1:free"],
|
|
1271
|
+
modelDiscovery: {
|
|
1272
|
+
// Resolves against effectiveBaseUrl (registry baseUrl .../v1) to the same
|
|
1273
|
+
// canonical endpoint https://inference-api.nousresearch.com/v1/models.
|
|
1274
|
+
path: "models",
|
|
1275
|
+
maxResponseBytes: 262_144,
|
|
1276
|
+
maxModels: 512,
|
|
1277
|
+
},
|
|
1278
|
+
note: "Nous Research subscription gateway. OAuth device login with your own Portal account; mixed paid + :free models discovered live (fallback seed 2026-08-10: tencent/hy3:free, poolside/laguna-s-2.1:free, stepfun/step-3.7-flash:free, poolside/laguna-xs-2.1:free).",
|
|
1279
|
+
},
|
|
742
1280
|
{
|
|
743
1281
|
id: "openai-apikey",
|
|
744
1282
|
label: "OpenAI API",
|
|
745
1283
|
adapter: "openai-responses",
|
|
746
1284
|
baseUrl: "https://api.openai.com/v1",
|
|
747
1285
|
authKind: "key",
|
|
1286
|
+
supportsServiceTier: true,
|
|
748
1287
|
featured: true,
|
|
749
1288
|
dashboardUrl: "https://platform.openai.com/api-keys",
|
|
750
1289
|
defaultModel: "gpt-5.5",
|
|
751
|
-
models: ["gpt-5.5", ...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS],
|
|
1290
|
+
models: ["gpt-5.5", ...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS, ...OPENAI_DAYBREAK_MODELS],
|
|
752
1291
|
liveModels: true,
|
|
753
|
-
modelContextWindows: OPENAI_API_GPT56_CONTEXT_WINDOWS,
|
|
754
|
-
modelMaxInputTokens: OPENAI_API_GPT56_MAX_INPUT_TOKENS,
|
|
1292
|
+
modelContextWindows: { ...OPENAI_API_GPT56_CONTEXT_WINDOWS, ...OPENAI_DAYBREAK_CONTEXT_WINDOWS },
|
|
1293
|
+
modelMaxInputTokens: { ...OPENAI_API_GPT56_MAX_INPUT_TOKENS, ...OPENAI_DAYBREAK_MAX_INPUT_TOKENS },
|
|
755
1294
|
modelInputModalities: Object.fromEntries(
|
|
756
|
-
["gpt-5.5", ...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS
|
|
757
|
-
|
|
758
|
-
modelReasoningEfforts: Object.fromEntries(
|
|
759
|
-
[...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS].map(id => [id, OPENAI_API_GPT56_REASONING_EFFORTS]),
|
|
1295
|
+
["gpt-5.5", ...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS, ...OPENAI_DAYBREAK_MODELS]
|
|
1296
|
+
.map(id => [id, ["text", "image"]]),
|
|
760
1297
|
),
|
|
1298
|
+
modelReasoningEfforts: {
|
|
1299
|
+
...Object.fromEntries(
|
|
1300
|
+
[...OPENAI_GPT56_MODELS, ...OPENAI_GPT56_PRO_MODELS].map(id => [id, OPENAI_API_GPT56_REASONING_EFFORTS]),
|
|
1301
|
+
),
|
|
1302
|
+
...OPENAI_DAYBREAK_REASONING_EFFORTS,
|
|
1303
|
+
},
|
|
761
1304
|
virtualModels: OPENAI_API_GPT56_VIRTUAL_MODELS,
|
|
762
1305
|
},
|
|
763
1306
|
{
|
|
@@ -777,6 +1320,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
777
1320
|
"umans-coder": UMANS_REASONING_EFFORTS,
|
|
778
1321
|
"umans-kimi-k2.7": UMANS_REASONING_EFFORTS,
|
|
779
1322
|
"umans-flash": UMANS_REASONING_EFFORTS,
|
|
1323
|
+
"umans-glm-5.3": UMANS_GLM_53_REASONING_EFFORTS,
|
|
780
1324
|
"umans-glm-5.2": UMANS_GLM_REASONING_EFFORTS,
|
|
781
1325
|
"umans-glm-5.1": UMANS_GLM_REASONING_EFFORTS,
|
|
782
1326
|
"umans-qwen3.6-35b-a3b": UMANS_REASONING_EFFORTS,
|
|
@@ -788,16 +1332,41 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
788
1332
|
id: "opencode-go", label: "opencode go", adapter: "openai-chat", baseUrl: "https://opencode.ai/zen/go/v1",
|
|
789
1333
|
authKind: "key", featured: true, dashboardUrl: "https://opencode.ai/auth", defaultModel: "kimi-k2.7-code",
|
|
790
1334
|
jawcodeBundle: "opencode-go", note: "GLM, DeepSeek, Kimi, Qwen, MiMo…",
|
|
791
|
-
|
|
792
|
-
|
|
1335
|
+
// Zen Go can close a Chat stream after a fully assembled function call without sending
|
|
1336
|
+
// finish_reason or [DONE] (#2260). The adapter still rejects incomplete argument JSON.
|
|
1337
|
+
openaiChatEofTolerance: true,
|
|
1338
|
+
/* [Decision Log]
|
|
1339
|
+
- 목적과 의도: Route GPT 5.6 Luna to the Responses endpoint that OpenCode Go documents for that exact model.
|
|
1340
|
+
- 기존 구현 및 제약 조건: The provider is mixed-wire but its provider-wide `openai-chat` adapter sent Luna to `/chat/completions`; explicit user `modelAdapters` entries must remain authoritative.
|
|
1341
|
+
- 검토한 주요 대안: Change the whole provider to Responses; infer the wire from model-family names; add one registry-only exact-model default.
|
|
1342
|
+
- 선택한 방식: Declare only `gpt-5.6-luna` as `openai-responses` through the existing registry default mechanism.
|
|
1343
|
+
- 다른 대안 대신 이 방식을 선택한 이유: OpenCode Go documents sibling models on Chat or Anthropic endpoints, and an exact registry default preserves both those routes and explicit opt-out precedence.
|
|
1344
|
+
- 장점, 단점 및 영향: Luna reaches `/responses` from every inbound surface without changing siblings; a future upstream endpoint change requires an evidence-backed registry update.
|
|
1345
|
+
*/
|
|
1346
|
+
modelWireDefaults: { "gpt-5.6-luna": "openai-responses" },
|
|
1347
|
+
modelContextWindows: {
|
|
1348
|
+
"kimi-k3": KIMI_K3_STANDARD_CONTEXT_WINDOW,
|
|
1349
|
+
// Ox Alpha (stealth 1M multimodal) and the DeepSeek vision preview are
|
|
1350
|
+
// metadata-only here: the Go roster is discovered live, so these apply
|
|
1351
|
+
// the moment the gateway starts serving the ids.
|
|
1352
|
+
[OPENCODE_OX_ALPHA_FREE_MODEL]: OX_ALPHA_CONTEXT_WINDOW,
|
|
1353
|
+
[DEEPSEEK_VISION_PREVIEW_MODEL]: 1_048_576,
|
|
1354
|
+
},
|
|
1355
|
+
modelInputModalities: {
|
|
1356
|
+
"kimi-k3": ["text", "image"],
|
|
1357
|
+
[OPENCODE_OX_ALPHA_FREE_MODEL]: ["text", "image"],
|
|
1358
|
+
// Experimental DeepSeek vision preview — expected to merge into deepseek-v4-flash later.
|
|
1359
|
+
[DEEPSEEK_VISION_PREVIEW_MODEL]: ["text", "image"],
|
|
1360
|
+
},
|
|
793
1361
|
modelReasoningEfforts: {
|
|
1362
|
+
"glm-5.3": ZAI_GLM_53_REASONING_EFFORTS,
|
|
794
1363
|
"glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
|
|
795
1364
|
"kimi-k3": KIMI_CODING_K3_REASONING_EFFORTS,
|
|
796
1365
|
"kimi-k2.7-code": [],
|
|
797
1366
|
"kimi-k2.7-code-highspeed": [],
|
|
798
1367
|
...Object.fromEntries(OPENCODE_GO_THINKING_TOGGLE_MODELS.map(id => [id, THINKING_TOGGLE_EFFORTS])),
|
|
799
1368
|
...Object.fromEntries(OPENCODE_GO_THINKING_BUDGET_MODELS.map(id => [id, THINKING_BUDGET_EFFORTS])),
|
|
800
|
-
...Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id,
|
|
1369
|
+
...Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id, deepseekThinkingEffortsFor(id)])),
|
|
801
1370
|
},
|
|
802
1371
|
modelDefaultReasoningEfforts: { "kimi-k3": "max" },
|
|
803
1372
|
// glm-5.2 uses identity labels now that `max` is a native Codex level (no alias map);
|
|
@@ -805,7 +1374,14 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
805
1374
|
modelReasoningEffortMap: {
|
|
806
1375
|
"kimi-k3": KIMI_CODING_K3_REASONING_EFFORT_MAP,
|
|
807
1376
|
...Object.fromEntries(OPENCODE_GO_THINKING_TOGGLE_MODELS.map(id => [id, THINKING_TOGGLE_MAP])),
|
|
808
|
-
...Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id,
|
|
1377
|
+
...Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id, deepseekReasoningMapFor(id)])),
|
|
1378
|
+
},
|
|
1379
|
+
modelSupportsReasoningSummaries: {
|
|
1380
|
+
"glm-5.3": true,
|
|
1381
|
+
"glm-5.2": true,
|
|
1382
|
+
"glm-5.1": true,
|
|
1383
|
+
"glm-5": true,
|
|
1384
|
+
...Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id, true])),
|
|
809
1385
|
},
|
|
810
1386
|
thinkingToggleModels: OPENCODE_GO_THINKING_TOGGLE_MODELS,
|
|
811
1387
|
thinkingBudgetModels: THINKING_BUDGET_MODELS,
|
|
@@ -814,7 +1390,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
814
1390
|
// every model listed here (and the catalog advertises image input on their behalf).
|
|
815
1391
|
// Kimi K2.7 Code accepts text+image+video: do NOT list it here.
|
|
816
1392
|
noVisionModels: [
|
|
817
|
-
"glm-5.2", "glm-5", "glm-5.1",
|
|
1393
|
+
"glm-5.3", "glm-5.2", "glm-5", "glm-5.1",
|
|
818
1394
|
"deepseek-v4-flash", "deepseek-v4-pro",
|
|
819
1395
|
"mimo-v2-pro", "mimo-v2.5-pro",
|
|
820
1396
|
"minimax-m2.5", "minimax-m2.7",
|
|
@@ -825,7 +1401,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
825
1401
|
noPenaltyModels: ["kimi-k3", "kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
|
|
826
1402
|
autoToolChoiceOnlyModels: ["kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
|
|
827
1403
|
// 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],
|
|
1404
|
+
preserveReasoningContentModels: ["glm-5.3", "glm-5.2", "kimi-k3", "kimi-k2.7-code", "kimi-k2.7-code-highspeed", ...DEEPSEEK_THINKING_MODELS],
|
|
829
1405
|
},
|
|
830
1406
|
{
|
|
831
1407
|
id: "neuralwatt",
|
|
@@ -834,10 +1410,13 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
834
1410
|
baseUrl: "https://api.neuralwatt.com/v1",
|
|
835
1411
|
authKind: "key",
|
|
836
1412
|
dashboardUrl: "https://portal.neuralwatt.com",
|
|
837
|
-
defaultModel: "glm-5.
|
|
1413
|
+
defaultModel: "glm-5.3",
|
|
838
1414
|
// 2026-07-10 live /v1/models: K2.5 rows were removed and GLM-5.2 short variants added.
|
|
1415
|
+
// 260814: the glm-5.3 quartet is speculative; live discovery is authoritative and drops
|
|
1416
|
+
// any id Neuralwatt has not published yet.
|
|
839
1417
|
// Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md and https://api.neuralwatt.com/v1/models.
|
|
840
1418
|
models: [
|
|
1419
|
+
"glm-5.3", "glm-5.3-fast", "glm-5.3-short", "glm-5.3-short-fast",
|
|
841
1420
|
"glm-5.2", "glm-5.2-fast", "glm-5.2-short", "glm-5.2-short-fast",
|
|
842
1421
|
"kimi-k2.6", "kimi-k2.6-fast",
|
|
843
1422
|
"kimi-k2.7-code",
|
|
@@ -845,6 +1424,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
845
1424
|
],
|
|
846
1425
|
// Neuralwatt's /v1/models metadata is authoritative; these static hints are the offline fallback.
|
|
847
1426
|
modelReasoningEfforts: {
|
|
1427
|
+
"glm-5.3": ZAI_GLM_53_REASONING_EFFORTS,
|
|
1428
|
+
"glm-5.3-fast": [],
|
|
1429
|
+
"glm-5.3-short": ZAI_GLM_53_REASONING_EFFORTS,
|
|
1430
|
+
"glm-5.3-short-fast": [],
|
|
848
1431
|
"glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
|
|
849
1432
|
"glm-5.2-fast": [],
|
|
850
1433
|
"glm-5.2-short": ZAI_GLM_52_REASONING_EFFORTS,
|
|
@@ -860,15 +1443,96 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
860
1443
|
"qwen3.6-35b-fast": [],
|
|
861
1444
|
},
|
|
862
1445
|
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"],
|
|
1446
|
+
noReasoningModels: ["glm-5.3-fast", "glm-5.3-short-fast", "glm-5.2-fast", "glm-5.2-short-fast", "kimi-k2.6-fast", "qwen3.5-397b-fast", "qwen3.6-35b-fast"],
|
|
1447
|
+
noVisionModels: ["glm-5.3", "glm-5.3-fast", "glm-5.3-short", "glm-5.3-short-fast", "glm-5.2", "glm-5.2-fast", "glm-5.2-short", "glm-5.2-short-fast", "qwen3.5-397b", "qwen3.5-397b-fast"],
|
|
865
1448
|
noTemperatureModels: ["kimi-k2.7-code"],
|
|
866
1449
|
noTopPModels: ["kimi-k2.7-code"],
|
|
867
1450
|
noPenaltyModels: ["kimi-k2.7-code"],
|
|
868
1451
|
autoToolChoiceOnlyModels: ["kimi-k2.7-code"],
|
|
869
1452
|
preserveReasoningContentModels: NEURALWATT_REASONING_HISTORY_MODELS,
|
|
870
1453
|
},
|
|
871
|
-
{
|
|
1454
|
+
{
|
|
1455
|
+
id: "openrouter",
|
|
1456
|
+
label: "OpenRouter",
|
|
1457
|
+
adapter: "openai-chat",
|
|
1458
|
+
baseUrl: "https://openrouter.ai/api/v1",
|
|
1459
|
+
authKind: "key",
|
|
1460
|
+
featured: true,
|
|
1461
|
+
dashboardUrl: "https://openrouter.ai/keys",
|
|
1462
|
+
jawcodeBundle: "openrouter",
|
|
1463
|
+
// stealth/ox-alpha: free stealth-window frontier model (launched 2026-08-20).
|
|
1464
|
+
// /api/v1/models reports 1,048,576 context, 131,072 max output, text+image+video
|
|
1465
|
+
// input, $0 pricing, mandatory reasoning. Single provider slug: `stealth`.
|
|
1466
|
+
models: ["anthropic/claude-sonnet-5", "stealth/ox-alpha", ...OPENROUTER_GPT56_MODELS],
|
|
1467
|
+
modelContextWindows: {
|
|
1468
|
+
"anthropic/claude-sonnet-5": 1_000_000,
|
|
1469
|
+
"stealth/ox-alpha": OX_ALPHA_CONTEXT_WINDOW,
|
|
1470
|
+
...OPENROUTER_GPT56_CONTEXT_WINDOWS,
|
|
1471
|
+
},
|
|
1472
|
+
modelInputModalities: { "stealth/ox-alpha": ["text", "image"] },
|
|
1473
|
+
// OpenRouter documents priority support for OpenAI endpoints, but not Anthropic. Keep the
|
|
1474
|
+
// provider unclassified and opt in only the exact OpenAI-backed slugs we ship. These facts
|
|
1475
|
+
// belong only to the canonical destination; a same-named custom gateway is unknown to us.
|
|
1476
|
+
modelServiceTierCapabilityBaseUrlGuard: isCanonicalOpenRouterTarget,
|
|
1477
|
+
modelSupportsServiceTier: {
|
|
1478
|
+
"openai/gpt-5.6-sol": true,
|
|
1479
|
+
"openai/gpt-5.6-terra": true,
|
|
1480
|
+
"openai/gpt-5.6-luna": true,
|
|
1481
|
+
},
|
|
1482
|
+
// Deliberately no OpenRouter route pin: it bills the endpoint actually used and reports the
|
|
1483
|
+
// actual service_tier. B0 confirmation therefore owns downgrade safety. Forcing `only` plus
|
|
1484
|
+
// `allow_fallbacks:false` would turn a graceful priority-capacity fallback into a hard failure.
|
|
1485
|
+
},
|
|
1486
|
+
{
|
|
1487
|
+
// Primary sources checked 2026-08-02:
|
|
1488
|
+
// - docs.cline.bot/getting-started/clinepass publishes this exact catalog and explicitly
|
|
1489
|
+
// authorizes using the full slugs through Cline's external API.
|
|
1490
|
+
// - docs.cline.bot/api/chat-completions and /api/errors define the endpoint, reasoning delta,
|
|
1491
|
+
// and choice-scoped mid-stream error contract.
|
|
1492
|
+
// - Cline's official catalog source resolves per-model capabilities through OpenRouter data;
|
|
1493
|
+
// the static context/modality snapshot below was cross-checked against that catalog.
|
|
1494
|
+
// - cline.bot/tos identifies Cline Bot Inc. as the operator. Maintenance owner: @lidge-jun.
|
|
1495
|
+
id: "cline-pass",
|
|
1496
|
+
label: "ClinePass",
|
|
1497
|
+
adapter: "openai-chat",
|
|
1498
|
+
baseUrl: "https://api.cline.bot/api/v1",
|
|
1499
|
+
authKind: "key",
|
|
1500
|
+
dashboardUrl: "https://app.cline.bot",
|
|
1501
|
+
defaultModel: "cline-pass/kimi-k3",
|
|
1502
|
+
models: CLINE_PASS_MODELS,
|
|
1503
|
+
modelContextWindows: CLINE_PASS_MODEL_CONTEXT_WINDOWS,
|
|
1504
|
+
modelInputModalities: CLINE_PASS_MODEL_INPUT_MODALITIES,
|
|
1505
|
+
noVisionModels: CLINE_PASS_TEXT_ONLY_MODELS,
|
|
1506
|
+
// Live-probed 2026-08-13 across every static ClinePass model: the gateway accepts and
|
|
1507
|
+
// validates low/medium/high/xhigh/max, and rejects an invalid sentinel. Preserve the
|
|
1508
|
+
// caller's requested tier and let ClinePass own any backend-specific normalization.
|
|
1509
|
+
reasoningEfforts: ["low", "medium", "high", "xhigh", "max"],
|
|
1510
|
+
reasoningWireFormat: "gateway-object",
|
|
1511
|
+
preserveCustomDestination: true,
|
|
1512
|
+
note: "ClinePass subscription API. Uses a Cline API key and the full cline-pass/<model> upstream slug; quota is shared across the account's rolling 5-hour, weekly, and monthly limits.",
|
|
1513
|
+
},
|
|
1514
|
+
// Cline API (usage-billing): OpenAI-compatible Chat Completions. Model IDs follow the
|
|
1515
|
+
// OpenRouter-style `provider/model` convention. Live /models discovery is key-gated (401
|
|
1516
|
+
// without auth), so the static seed is the cold-start fallback. Evidence: docs.cline.bot/api/*.
|
|
1517
|
+
{
|
|
1518
|
+
id: "cline",
|
|
1519
|
+
label: "Cline",
|
|
1520
|
+
adapter: "openai-chat",
|
|
1521
|
+
baseUrl: "https://api.cline.bot/api/v1",
|
|
1522
|
+
authKind: "key",
|
|
1523
|
+
dashboardUrl: "https://app.cline.bot",
|
|
1524
|
+
liveModels: true,
|
|
1525
|
+
defaultModel: "anthropic/claude-sonnet-4-6",
|
|
1526
|
+
models: [
|
|
1527
|
+
"anthropic/claude-sonnet-4-6",
|
|
1528
|
+
"openai/gpt-4o",
|
|
1529
|
+
"google/gemini-2.5-pro",
|
|
1530
|
+
"deepseek/deepseek-chat",
|
|
1531
|
+
"minimax/minimax-m2.5",
|
|
1532
|
+
],
|
|
1533
|
+
preserveCustomDestination: true,
|
|
1534
|
+
note: "Cline usage-billing API: one key, 100+ models, OpenRouter-style ids. Promotional free models are IDE/CLI-only per Cline docs; minimax/minimax-m2.5 is the documented API free experimentation model.",
|
|
1535
|
+
},
|
|
872
1536
|
{
|
|
873
1537
|
// OrcaRouter: OpenAI-compatible adaptive router (api.orcarouter.ai). Model ids are
|
|
874
1538
|
// vendor-namespaced (`<vendor>/<model>`) and pass through to the upstream as-is.
|
|
@@ -896,9 +1560,9 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
896
1560
|
// returned 200), so no noTemperatureModels entry is warranted here.
|
|
897
1561
|
modelReasoningEfforts: {
|
|
898
1562
|
"openai/gpt-5.5": ["low", "medium", "high", "xhigh"],
|
|
899
|
-
"deepseek/deepseek-v4-pro":
|
|
1563
|
+
"deepseek/deepseek-v4-pro": deepseekThinkingEffortsFor("deepseek/deepseek-v4-pro"),
|
|
900
1564
|
},
|
|
901
|
-
modelReasoningEffortMap: { "deepseek/deepseek-v4-pro":
|
|
1565
|
+
modelReasoningEffortMap: { "deepseek/deepseek-v4-pro": deepseekReasoningMapFor("deepseek/deepseek-v4-pro") },
|
|
902
1566
|
preserveReasoningContentModels: ["deepseek/deepseek-v4-pro"],
|
|
903
1567
|
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
1568
|
},
|
|
@@ -919,12 +1583,13 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
919
1583
|
// devlog/_plan/260710_provider_hardening/001_research_frontier.md.
|
|
920
1584
|
{
|
|
921
1585
|
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"] },
|
|
1586
|
+
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", "gemini-3.7-flash"],
|
|
1587
|
+
modelContextWindows: { "gemini-3.6-flash": 1_048_576, "gemini-3.5-flash": 1_000_000, "gemini-3.5-flash-lite": 1_048_576, "gemini-3.7-flash": 1_048_576 },
|
|
1588
|
+
modelInputModalities: { "gemini-3.6-flash": ["text", "image"], "gemini-3.5-flash-lite": ["text", "image"], "gemini-3.7-flash": ["text", "image"] },
|
|
925
1589
|
modelReasoningEfforts: {
|
|
926
1590
|
"gemini-3.6-flash": ["minimal", "low", "medium", "high"],
|
|
927
1591
|
"gemini-3.5-flash": ["minimal", "low", "medium", "high"],
|
|
1592
|
+
"gemini-3.7-flash": ["minimal", "low", "medium", "high"],
|
|
928
1593
|
"gemini-3.1-pro-preview": ["low", "medium", "high"],
|
|
929
1594
|
},
|
|
930
1595
|
jawcodeBundle: "google", extraMetadataAliases: ["gemini"],
|
|
@@ -932,7 +1597,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
932
1597
|
// 2026-07-10: defaultModel is frozen pending Vertex-specific Tier-2 evidence; Gemini API
|
|
933
1598
|
// evidence from ai.google.dev does not establish Vertex publisher availability.
|
|
934
1599
|
{ 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:
|
|
1600
|
+
{ id: "google-antigravity", label: "Google Antigravity", adapter: "google", baseUrl: "https://daily-cloudcode-pa.googleapis.com", authKind: "oauth", allowBaseUrlOverride: true, dashboardUrl: "https://antigravity.google", models: ANTIGRAVITY_MODELS, liveModels: true, defaultModel: "gemini-3.7-flash", modelContextWindows: ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, modelInputModalities: ANTIGRAVITY_MODEL_INPUT_MODALITIES, modelReasoningEfforts: ANTIGRAVITY_MODEL_EFFORTS, googleMode: "cloud-code-assist", jawcodeBundle: "google", extraMetadataAliases: ["antigravity", "gemini-antigravity"] },
|
|
936
1601
|
{ 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
1602
|
{ 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
1603
|
{ 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" },
|
|
@@ -944,13 +1609,29 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
944
1609
|
adapter: "openai-chat",
|
|
945
1610
|
authKind: "key",
|
|
946
1611
|
dashboardUrl: "https://platform.deepseek.com/api_keys",
|
|
947
|
-
//
|
|
948
|
-
//
|
|
949
|
-
|
|
1612
|
+
// Route DeepSeek's own catalog bundle so routed rebuilds restore the official
|
|
1613
|
+
// context window from the vendored model-metadata bundle instead of falling
|
|
1614
|
+
// back to the 128k strict-fields default (scripts/model-metadata.source.json,
|
|
1615
|
+
// verified 2026-08-08).
|
|
1616
|
+
jawcodeBundle: "deepseek",
|
|
1617
|
+
// deepseek-chat/deepseek-reasoner were deprecated upstream on 2026-07-24 15:59 UTC;
|
|
1618
|
+
// official identifiers are now deepseek-v4-flash / deepseek-v4-pro. They stay in
|
|
1619
|
+
// the list only as compatibility aliases so existing saved configs and requests
|
|
1620
|
+
// keep validating and routing (they previously mapped to v4-flash; devlog
|
|
1621
|
+
// _fin/260710_provider_hardening/002_research_cn.md). The current offerings are
|
|
1622
|
+
// the V4 ids — defaultModel and the model-specific wiring above use them.
|
|
1623
|
+
// deepseek-v4-flash-vision-exp: experimental vision preview (2026-08-21) —
|
|
1624
|
+
// expected to merge into deepseek-v4-flash later; see DEEPSEEK_VISION_PREVIEW_MODEL.
|
|
1625
|
+
models: ["deepseek-chat", "deepseek-reasoner", ...DEEPSEEK_THINKING_MODELS, DEEPSEEK_VISION_PREVIEW_MODEL],
|
|
950
1626
|
defaultModel: "deepseek-v4-flash",
|
|
951
|
-
|
|
952
|
-
//
|
|
953
|
-
|
|
1627
|
+
// Official DeepSeek Codex setup (codex-deepseek-setup.sh) advertises 1,048,576
|
|
1628
|
+
// for both V4 models; the older 1,000,000 figure was a rounded approximation.
|
|
1629
|
+
modelContextWindows: { "deepseek-v4-flash": 1_048_576, "deepseek-v4-pro": 1_048_576, [DEEPSEEK_VISION_PREVIEW_MODEL]: 1_048_576 },
|
|
1630
|
+
modelInputModalities: { [DEEPSEEK_VISION_PREVIEW_MODEL]: ["text", "image"] },
|
|
1631
|
+
// DeepSeek documents both V4 models as native Responses API models adapted for Codex
|
|
1632
|
+
// (model table marks Responses API ✓ for flash and pro; the /responses reference lists
|
|
1633
|
+
// both ids as accepted `model` values — verified 2026-08-13 with the V4 Pro GA,
|
|
1634
|
+
// version label DeepSeek-V4-Pro-0813).
|
|
954
1635
|
modelWireDefaults: {
|
|
955
1636
|
// Codex speaks Responses natively and DeepSeek ships a Codex-compatible
|
|
956
1637
|
// apply_patch tool on that wire, so a Responses inbound goes straight out with
|
|
@@ -959,22 +1640,56 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
959
1640
|
// translating them into Responses would add a hop onto our newest upstream path
|
|
960
1641
|
// for no gain.
|
|
961
1642
|
"deepseek-v4-flash": { wire: "openai-responses", inbound: ["responses"] },
|
|
1643
|
+
"deepseek-v4-pro": { wire: "openai-responses", inbound: ["responses"] },
|
|
962
1644
|
},
|
|
1645
|
+
// The #875-era bounded-JSON force (`modelResponsesUpstreamStreaming`) is retired
|
|
1646
|
+
// for this entry: the official guide documents a `response.completed` /
|
|
1647
|
+
// `response.incomplete` / `response.failed` terminal with NO `data: [DONE]`
|
|
1648
|
+
// sentinel, and live probes (2026-08-07, including the tool-result replay shape
|
|
1649
|
+
// that originally stalled) close on the terminal. The relay's terminal boundary
|
|
1650
|
+
// (src/server/relay.ts) already cuts the stream at that event and synthesizes
|
|
1651
|
+
// `[DONE]`, so forcing stream:false only delayed every byte until generation
|
|
1652
|
+
// finished (28-46 s of silence on long turns). The registry knob itself remains
|
|
1653
|
+
// for providers that need it — re-adding one line here restores the old policy.
|
|
1654
|
+
// Evidence: https://api-docs.deepseek.com/guides/responses_api/ +
|
|
1655
|
+
// devlog/_fin/260807_deepseek_responses_streaming/000_plan.md.
|
|
1656
|
+
// Current official streams normally carry a real terminal; retain a narrow grace
|
|
1657
|
+
// repair for the historical shape that closes after a complete graph without one.
|
|
1658
|
+
modelResponsesTerminalRepair: { "deepseek-v4-flash": { graceMs: 5_000 }, "deepseek-v4-pro": { graceMs: 5_000 } },
|
|
1659
|
+
// DeepSeek's Responses route emits bare UUID item ids, which leave Codex
|
|
1660
|
+
// clients stuck on an uncommitted turn (#938). Client-facing only — raw
|
|
1661
|
+
// continuation snapshots keep the upstream ids.
|
|
1662
|
+
responsesItemIdRepair: { repairInvalidIds: true, repairMissingTerminalIds: true },
|
|
963
1663
|
// DeepSeek's Responses route is `POST /responses` with no `/v1` segment. Without
|
|
964
1664
|
// this the passthrough adapter falls back to its legacy `/v1/responses`
|
|
965
1665
|
// construction and the wire above can never route.
|
|
966
1666
|
// Evidence: https://api-docs.deepseek.com/api/create-response/
|
|
967
1667
|
responsesPath: "/responses",
|
|
1668
|
+
// DeepSeek's Responses reference does not list `service_tier`; unsupported
|
|
1669
|
+
// parameters are documented as silently ignored, but the fail-closed policy
|
|
1670
|
+
// strips the field rather than forwarding a knob the upstream never asked for.
|
|
1671
|
+
supportsServiceTier: false,
|
|
1672
|
+
// DeepSeek's Responses compatibility guide accepts plaintext reasoning items and
|
|
1673
|
+
// merges them into the adjacent assistant message, so replayed reasoning must
|
|
1674
|
+
// not be blanked the way the ChatGPT backend requires. (Whether the Responses
|
|
1675
|
+
// route REQUIRES replay on tool-call continuations is an inference from the
|
|
1676
|
+
// Chat Thinking-Mode docs, not a confirmed Responses contract.)
|
|
1677
|
+
preserveResponsesReasoningContent: true,
|
|
968
1678
|
// "The API is stateless: responses and conversations are not stored on the
|
|
969
1679
|
// server." https://api-docs.deepseek.com/api/create-response/
|
|
970
1680
|
statelessResponses: true,
|
|
1681
|
+
// DeepSeek rejects a valid Codex continuation when hook-provided developer
|
|
1682
|
+
// context splits a call from its result (#1292); parallel calls remain one
|
|
1683
|
+
// reasoning-bearing assistant batch rather than being split per pair (#1477).
|
|
1684
|
+
requiresAdjacentResponsesToolResults: true,
|
|
971
1685
|
/* [Decision Log]
|
|
972
1686
|
- 목적: DeepSeek V4 thinking mode multi-turn/tool-call requests must replay prior assistant reasoning_content.
|
|
973
1687
|
- 대안 분석: 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
1688
|
- 선택 근거: 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
1689
|
*/
|
|
976
|
-
modelReasoningEfforts: Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id,
|
|
977
|
-
modelReasoningEffortMap: Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id,
|
|
1690
|
+
modelReasoningEfforts: Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id, deepseekThinkingEffortsFor(id)])),
|
|
1691
|
+
modelReasoningEffortMap: Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id, deepseekReasoningMapFor(id)])),
|
|
1692
|
+
modelSupportsReasoningSummaries: Object.fromEntries(DEEPSEEK_THINKING_MODELS.map(id => [id, true])),
|
|
978
1693
|
preserveReasoningContentModels: DEEPSEEK_THINKING_MODELS,
|
|
979
1694
|
// Issue #88: every DeepSeek API model is text-only input (no image support upstream) — the
|
|
980
1695
|
// vision sidecar describes attached images for them, and the catalog advertises image input
|
|
@@ -983,6 +1698,40 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
983
1698
|
},
|
|
984
1699
|
// llama-3.3-70b was deprecated by Cerebras on 2026-02-16. Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
|
|
985
1700
|
{ 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" },
|
|
1701
|
+
{
|
|
1702
|
+
// Primary sources checked 2026-08-08:
|
|
1703
|
+
// - https://chutes.ai/pricing documents the shared llm.chutes.ai/v1 OpenAI-compatible
|
|
1704
|
+
// gateway, Bearer API keys, and chat completions. Its public
|
|
1705
|
+
// https://llm.chutes.ai/v1/models response supplies supported_features for filtering.
|
|
1706
|
+
// - https://chutes.ai/terms identifies Chutes Global Corp as the platform operator, applies
|
|
1707
|
+
// to API consumers, and directs production/high-volume automated inference to PAYGO.
|
|
1708
|
+
// Maintainer: @olddonkey; no affiliation with Chutes.
|
|
1709
|
+
id: "chutes",
|
|
1710
|
+
label: "Chutes",
|
|
1711
|
+
baseUrl: "https://llm.chutes.ai/v1",
|
|
1712
|
+
adapter: "openai-chat",
|
|
1713
|
+
authKind: "key",
|
|
1714
|
+
dashboardUrl: "https://chutes.ai/auth/start",
|
|
1715
|
+
liveModels: true,
|
|
1716
|
+
preserveCustomDestination: true,
|
|
1717
|
+
// The public model catalog cannot prove that a supplied Bearer key is valid.
|
|
1718
|
+
apiKeyValidation: "unknown",
|
|
1719
|
+
// Chutes documents tool calling, but not a provider-wide parallel tool-call contract.
|
|
1720
|
+
parallelToolCalls: false,
|
|
1721
|
+
// The live catalog reports reasoning support, but not a stable effort ladder.
|
|
1722
|
+
reasoningEfforts: [],
|
|
1723
|
+
modelDiscovery: {
|
|
1724
|
+
path: "models",
|
|
1725
|
+
maxResponseBytes: 256 * 1024,
|
|
1726
|
+
maxModels: 128,
|
|
1727
|
+
filter: {
|
|
1728
|
+
// The shared LLM catalog also contains rows without native tool support. Codex needs a
|
|
1729
|
+
// complete agent loop, so admit only rows whose live metadata advertises tools.
|
|
1730
|
+
allOf: [{ path: ["supported_features"], containsAny: ["tools"] }],
|
|
1731
|
+
},
|
|
1732
|
+
},
|
|
1733
|
+
note: "Shared OpenAI-compatible LLM gateway only; live discovery exposes tool-capable rows. User-deployed custom Chute endpoints and non-LLM APIs require a custom provider.",
|
|
1734
|
+
},
|
|
986
1735
|
{
|
|
987
1736
|
id: "deepinfra",
|
|
988
1737
|
label: "DeepInfra",
|
|
@@ -1020,6 +1769,69 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1020
1769
|
},
|
|
1021
1770
|
note: "Serverless text and vision-language chat models only; Hyperbolic's separate image, audio, and GPU endpoints are out of scope.",
|
|
1022
1771
|
},
|
|
1772
|
+
{
|
|
1773
|
+
// Primary sources checked 2026-08-03:
|
|
1774
|
+
// - docs.nscale.com documents the production OpenAI-compatible endpoint, bearer service
|
|
1775
|
+
// tokens, /v1/models, and a tool-calling request using this exact Llama model id.
|
|
1776
|
+
// - nscale.com/policies/terms-conditions identifies Nscale AS as the service operator and
|
|
1777
|
+
// covers customers using its public-cloud inference offering. Maintainer: @olddonkey;
|
|
1778
|
+
// no affiliation with Nscale.
|
|
1779
|
+
id: "nscale",
|
|
1780
|
+
label: "Nscale Serverless Inference",
|
|
1781
|
+
baseUrl: "https://inference.api.nscale.com/v1",
|
|
1782
|
+
adapter: "openai-chat",
|
|
1783
|
+
authKind: "key",
|
|
1784
|
+
dashboardUrl: "https://console.nscale.com",
|
|
1785
|
+
defaultModel: "meta-llama/Llama-3.1-8B-Instruct",
|
|
1786
|
+
models: ["meta-llama/Llama-3.1-8B-Instruct"],
|
|
1787
|
+
liveModels: true,
|
|
1788
|
+
preserveCustomDestination: true,
|
|
1789
|
+
// Nscale documents tools but not parallel tool calls. Keep requests serialized.
|
|
1790
|
+
parallelToolCalls: false,
|
|
1791
|
+
// The API schema accepts reasoning_effort, but does not publish per-model tiers.
|
|
1792
|
+
reasoningEfforts: [],
|
|
1793
|
+
modelDiscovery: {
|
|
1794
|
+
path: "models",
|
|
1795
|
+
maxResponseBytes: 256 * 1024,
|
|
1796
|
+
maxModels: 256,
|
|
1797
|
+
filter: {
|
|
1798
|
+
// Nscale's catalog mixes chat, image, and embedding rows without a modality field.
|
|
1799
|
+
// Admit only the exact model used in its official tool-calling API example.
|
|
1800
|
+
allOf: [{ path: ["id"], equalsAny: ["meta-llama/Llama-3.1-8B-Instruct"] }],
|
|
1801
|
+
},
|
|
1802
|
+
},
|
|
1803
|
+
note: "Serverless OpenAI-compatible inference. Live discovery admits only the tool-capable model established by Nscale's official API example; other mixed-catalog rows remain hidden pending equivalent evidence.",
|
|
1804
|
+
},
|
|
1805
|
+
{
|
|
1806
|
+
// Primary sources checked 2026-08-03:
|
|
1807
|
+
// - docs.vultr.com documents the fixed OpenAI-compatible base URL, per-subscription bearer
|
|
1808
|
+
// key, /v1/models, and states that tool calling is currently limited to kimi-k2-instruct.
|
|
1809
|
+
// - Vultr's official properties identify VULTR as a The Constant Company, LLC trademark and
|
|
1810
|
+
// document customer API integrations. Maintainer: @olddonkey; no affiliation with Vultr.
|
|
1811
|
+
id: "vultr",
|
|
1812
|
+
label: "Vultr Serverless Inference",
|
|
1813
|
+
baseUrl: "https://api.vultrinference.com/v1",
|
|
1814
|
+
adapter: "openai-chat",
|
|
1815
|
+
authKind: "key",
|
|
1816
|
+
dashboardUrl: "https://my.vultr.com",
|
|
1817
|
+
defaultModel: "kimi-k2-instruct",
|
|
1818
|
+
models: ["kimi-k2-instruct"],
|
|
1819
|
+
liveModels: true,
|
|
1820
|
+
preserveCustomDestination: true,
|
|
1821
|
+
parallelToolCalls: false,
|
|
1822
|
+
reasoningEfforts: [],
|
|
1823
|
+
modelDiscovery: {
|
|
1824
|
+
path: "models",
|
|
1825
|
+
maxResponseBytes: 256 * 1024,
|
|
1826
|
+
maxModels: 256,
|
|
1827
|
+
filter: {
|
|
1828
|
+
// Vultr explicitly limits tool calling to this model. A coding agent must not select
|
|
1829
|
+
// another chat model that cannot complete its tool loop.
|
|
1830
|
+
allOf: [{ path: ["id"], equalsAny: ["kimi-k2-instruct"] }],
|
|
1831
|
+
},
|
|
1832
|
+
},
|
|
1833
|
+
note: "Serverless Inference subscription API. Live discovery exposes only kimi-k2-instruct because Vultr documents it as the sole tool-calling model.",
|
|
1834
|
+
},
|
|
1023
1835
|
{
|
|
1024
1836
|
id: "baseten",
|
|
1025
1837
|
label: "Baseten Model APIs",
|
|
@@ -1045,6 +1857,234 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1045
1857
|
},
|
|
1046
1858
|
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
1859
|
},
|
|
1860
|
+
{
|
|
1861
|
+
id: "commandcode",
|
|
1862
|
+
label: "Command Code - API",
|
|
1863
|
+
adapter: "openai-chat",
|
|
1864
|
+
baseUrl: "https://api.commandcode.ai/provider/v1",
|
|
1865
|
+
authKind: "key",
|
|
1866
|
+
dashboardUrl: "https://commandcode.ai/studio/",
|
|
1867
|
+
liveModels: true,
|
|
1868
|
+
preserveCustomDestination: true,
|
|
1869
|
+
defaultModel: "deepseek/deepseek-v4-flash",
|
|
1870
|
+
// The default is also the cold-start seed: live discovery failure must not empty the catalog
|
|
1871
|
+
// for a freshly configured provider with no stale cache (issue #308 pattern).
|
|
1872
|
+
models: ["deepseek/deepseek-v4-flash"],
|
|
1873
|
+
// The public model catalog is unauthenticated, so a Bearer probe cannot prove key validity.
|
|
1874
|
+
apiKeyValidation: "unknown",
|
|
1875
|
+
// The public catalog reports ids/context windows only; no trustworthy reasoning contract.
|
|
1876
|
+
reasoningEfforts: [],
|
|
1877
|
+
// Official Command Code model-profile reasoning facts (shared with the OAuth
|
|
1878
|
+
// `command-code` entry). Without them the API-key preset never advertises a
|
|
1879
|
+
// reasoning picker, and the router's known-ids decode source misses the native
|
|
1880
|
+
// slash ids — so a Codex-facing slug like `commandcode/deepseek-deepseek-v4-pro`
|
|
1881
|
+
// is sent upstream verbatim and rejected with `unsupported_model`.
|
|
1882
|
+
modelReasoningEfforts: COMMAND_CODE_MODEL_REASONING_EFFORTS,
|
|
1883
|
+
// Ox Alpha (stealth preview, Command Code changelog v1.31.0) ships with a
|
|
1884
|
+
// 1.05M-token multimodal context; the DeepSeek vision preview id is
|
|
1885
|
+
// preemptive for when the catalog serves it (merges into v4-flash later).
|
|
1886
|
+
modelContextWindows: {
|
|
1887
|
+
"stealth/ox-alpha": OX_ALPHA_CONTEXT_WINDOW,
|
|
1888
|
+
[`deepseek/${DEEPSEEK_VISION_PREVIEW_MODEL}`]: 1_048_576,
|
|
1889
|
+
},
|
|
1890
|
+
modelInputModalities: {
|
|
1891
|
+
"stealth/ox-alpha": ["text", "image"],
|
|
1892
|
+
[`deepseek/${DEEPSEEK_VISION_PREVIEW_MODEL}`]: ["text", "image"],
|
|
1893
|
+
},
|
|
1894
|
+
modelDiscovery: {
|
|
1895
|
+
path: "models",
|
|
1896
|
+
maxResponseBytes: 256 * 1024,
|
|
1897
|
+
maxModels: 256,
|
|
1898
|
+
},
|
|
1899
|
+
// Verified 2026-08-03: public /provider/v1/models returns 51 rows; /chat/completions returns
|
|
1900
|
+
// 401 UNAUTHORIZED without a Bearer key. Primary source: https://commandcode.ai/docs/provider.
|
|
1901
|
+
note: "Command Code Provider API (OpenAI-compatible); API access requires the Provider plan. Use `ocx login command-code` for OAuth account login (imports an existing local Command Code CLI credential when present). Docs: https://commandcode.ai/docs/provider.",
|
|
1902
|
+
},
|
|
1903
|
+
{
|
|
1904
|
+
id: "sambanova",
|
|
1905
|
+
label: "SambaNova Cloud",
|
|
1906
|
+
baseUrl: "https://api.sambanova.ai/v1",
|
|
1907
|
+
adapter: "openai-chat",
|
|
1908
|
+
authKind: "key",
|
|
1909
|
+
dashboardUrl: "https://cloud.sambanova.ai/apis",
|
|
1910
|
+
liveModels: true,
|
|
1911
|
+
preserveCustomDestination: true,
|
|
1912
|
+
apiKeyValidation: "unknown",
|
|
1913
|
+
// SambaNova documents this request field but does not yet support parallel function calls.
|
|
1914
|
+
parallelToolCalls: false,
|
|
1915
|
+
// The public catalog does not report a trustworthy per-model reasoning contract.
|
|
1916
|
+
reasoningEfforts: [],
|
|
1917
|
+
modelDiscovery: {
|
|
1918
|
+
path: "models",
|
|
1919
|
+
maxResponseBytes: 128 * 1024,
|
|
1920
|
+
maxModels: 128,
|
|
1921
|
+
},
|
|
1922
|
+
note: "SambaNova Cloud text-generation models only; private SambaStudio deployment endpoints are outside this preset.",
|
|
1923
|
+
},
|
|
1924
|
+
{
|
|
1925
|
+
id: "nebius",
|
|
1926
|
+
label: "Nebius Token Factory",
|
|
1927
|
+
baseUrl: "https://api.tokenfactory.nebius.com/v1",
|
|
1928
|
+
adapter: "openai-chat",
|
|
1929
|
+
authKind: "key",
|
|
1930
|
+
dashboardUrl: "https://tokenfactory.nebius.com",
|
|
1931
|
+
liveModels: true,
|
|
1932
|
+
preserveCustomDestination: true,
|
|
1933
|
+
// The public tools guide documents single function selection, not parallel tool calls.
|
|
1934
|
+
parallelToolCalls: false,
|
|
1935
|
+
// Missing reasoning metadata must not promote a model to Codex's full fallback ladder.
|
|
1936
|
+
reasoningEfforts: [],
|
|
1937
|
+
modelDiscovery: {
|
|
1938
|
+
path: "models",
|
|
1939
|
+
query: { verbose: "true" },
|
|
1940
|
+
maxResponseBytes: 512 * 1024,
|
|
1941
|
+
maxModels: 512,
|
|
1942
|
+
filter: {
|
|
1943
|
+
// Keep rows whose reported architecture output includes text (for example,
|
|
1944
|
+
// text->text or text+image->text); embedding and image-generation rows are excluded.
|
|
1945
|
+
allOf: [{ path: ["architecture", "modality"], containsAny: ["->text"] }],
|
|
1946
|
+
},
|
|
1947
|
+
},
|
|
1948
|
+
note: "Shared Token Factory text-output inference only; live discovery excludes embedding and image-generation rows.",
|
|
1949
|
+
},
|
|
1950
|
+
{
|
|
1951
|
+
id: "digitalocean",
|
|
1952
|
+
label: "DigitalOcean Serverless Inference",
|
|
1953
|
+
baseUrl: "https://inference.do-ai.run/v1",
|
|
1954
|
+
adapter: "openai-chat",
|
|
1955
|
+
authKind: "key",
|
|
1956
|
+
dashboardUrl: "https://cloud.digitalocean.com/model-studio/manage-keys",
|
|
1957
|
+
liveModels: true,
|
|
1958
|
+
preserveCustomDestination: true,
|
|
1959
|
+
// The Chat Completions contract documents function calls but not universal parallel support.
|
|
1960
|
+
parallelToolCalls: false,
|
|
1961
|
+
// Unknown catalog rows must not inherit Codex's full fallback reasoning ladder.
|
|
1962
|
+
reasoningEfforts: [],
|
|
1963
|
+
modelDiscovery: {
|
|
1964
|
+
path: "models",
|
|
1965
|
+
maxResponseBytes: 256 * 1024,
|
|
1966
|
+
maxModels: 256,
|
|
1967
|
+
filter: {
|
|
1968
|
+
allOf: [{ path: ["id"], equalsAny: DIGITALOCEAN_CHAT_COMPLETION_MODELS }],
|
|
1969
|
+
},
|
|
1970
|
+
},
|
|
1971
|
+
note: "Shared Serverless Inference Chat Completions only; agent-specific, dedicated, Responses-only, embedding, and media-generation models are outside this preset.",
|
|
1972
|
+
},
|
|
1973
|
+
{
|
|
1974
|
+
id: "scaleway",
|
|
1975
|
+
label: "Scaleway Generative APIs",
|
|
1976
|
+
baseUrl: "https://api.scaleway.ai/v1",
|
|
1977
|
+
adapter: "openai-chat",
|
|
1978
|
+
authKind: "key",
|
|
1979
|
+
dashboardUrl: "https://console.scaleway.com/generative-api",
|
|
1980
|
+
liveModels: true,
|
|
1981
|
+
freeTier: true,
|
|
1982
|
+
preserveCustomDestination: true,
|
|
1983
|
+
// Parallel support varies by model; avoid advertising it as a provider-wide capability.
|
|
1984
|
+
parallelToolCalls: false,
|
|
1985
|
+
// The generic `/models` rows carry no trustworthy reasoning metadata.
|
|
1986
|
+
reasoningEfforts: [],
|
|
1987
|
+
modelInputModalities: SCALEWAY_MODEL_INPUT_MODALITIES,
|
|
1988
|
+
modelDiscovery: {
|
|
1989
|
+
path: "models",
|
|
1990
|
+
maxResponseBytes: 128 * 1024,
|
|
1991
|
+
maxModels: 128,
|
|
1992
|
+
filter: {
|
|
1993
|
+
allOf: [{ path: ["id"], equalsAny: SCALEWAY_SERVERLESS_CHAT_MODELS }],
|
|
1994
|
+
},
|
|
1995
|
+
},
|
|
1996
|
+
note: "Shared Generative APIs Serverless Chat Completions only; project-qualified and dedicated deployment hosts require a custom provider.",
|
|
1997
|
+
},
|
|
1998
|
+
{
|
|
1999
|
+
// Primary sources checked 2026-08-08:
|
|
2000
|
+
// - https://featherless.ai/docs/api-overview-and-common-options documents the fixed
|
|
2001
|
+
// OpenAI-compatible base URL, Bearer keys, and Chat Completions.
|
|
2002
|
+
// - https://featherless.ai/docs/api-reference-models documents authenticated plan filtering,
|
|
2003
|
+
// chat capability filtering, popularity sorting, pagination, and per-row tool metadata.
|
|
2004
|
+
// - https://featherless.ai/legal/terms-of-service identifies Featherless as a Delaware LLC,
|
|
2005
|
+
// covers developers building on its APIs, and reserves arbitrary applications for Scale
|
|
2006
|
+
// plans. Maintainer: @olddonkey; no affiliation with Featherless.
|
|
2007
|
+
id: "featherless",
|
|
2008
|
+
label: "Featherless AI",
|
|
2009
|
+
baseUrl: "https://api.featherless.ai/v1",
|
|
2010
|
+
adapter: "openai-chat",
|
|
2011
|
+
authKind: "key",
|
|
2012
|
+
dashboardUrl: "https://featherless.ai/account/api-keys",
|
|
2013
|
+
liveModels: true,
|
|
2014
|
+
preserveCustomDestination: true,
|
|
2015
|
+
// /v1/models is documented as callable authenticated or unauthenticated, so a 2xx catalog
|
|
2016
|
+
// response cannot prove that the supplied Bearer key is valid.
|
|
2017
|
+
apiKeyValidation: "unknown",
|
|
2018
|
+
// Featherless documents tool calling, but not a provider-wide parallel tool-call contract.
|
|
2019
|
+
parallelToolCalls: false,
|
|
2020
|
+
// Reasoning controls use model-specific chat_template_kwargs, not OpenAI reasoning_effort.
|
|
2021
|
+
reasoningEfforts: [],
|
|
2022
|
+
modelDiscovery: {
|
|
2023
|
+
path: "models",
|
|
2024
|
+
query: {
|
|
2025
|
+
available_on_current_plan: "true",
|
|
2026
|
+
capabilities: "chat",
|
|
2027
|
+
page: "1",
|
|
2028
|
+
per_page: "100",
|
|
2029
|
+
sort: "-popularity",
|
|
2030
|
+
},
|
|
2031
|
+
maxResponseBytes: 128 * 1024,
|
|
2032
|
+
maxModels: 100,
|
|
2033
|
+
filter: {
|
|
2034
|
+
// Treat server-side filters as a size optimization, not an authority boundary. A row must
|
|
2035
|
+
// independently prove plan availability, no separate Hugging Face gate, and tool support.
|
|
2036
|
+
allOf: [
|
|
2037
|
+
{ path: ["available_on_current_plan"], equalsAny: [true] },
|
|
2038
|
+
{ path: ["is_gated"], equalsAny: [false] },
|
|
2039
|
+
{ path: ["features", "tool_use"], equalsAny: [true] },
|
|
2040
|
+
],
|
|
2041
|
+
},
|
|
2042
|
+
},
|
|
2043
|
+
note: "Authenticated first page of popular chat models only; live discovery admits at most 100 plan-available, ungated rows whose metadata explicitly reports tool use.",
|
|
2044
|
+
},
|
|
2045
|
+
{
|
|
2046
|
+
// Primary sources checked 2026-08-08:
|
|
2047
|
+
// - https://novita.ai/docs/api-reference/model-apis-llm-create-chat-completion and
|
|
2048
|
+
// https://novita.ai/docs/api-reference/model-apis-llm-list-models document the fixed
|
|
2049
|
+
// OpenAI-compatible Chat Completions and model-list endpoints.
|
|
2050
|
+
// - https://novita.ai/docs/api-reference/basic-authentication documents Bearer API keys.
|
|
2051
|
+
// - https://novita.ai/legal/terms-of-service (updated 2026-08-05) expressly covers AI
|
|
2052
|
+
// inference APIs, third-party Model Providers, and customer Input/Output processing.
|
|
2053
|
+
// - https://huggingface.co/docs/inference-providers/main/providers/novita lists Novita as an
|
|
2054
|
+
// Inference Providers partner for chat/VLM traffic, independently supporting routing use.
|
|
2055
|
+
// - https://tsdr.uspto.gov/statusview/sn99255805 is the official use-in-commerce record
|
|
2056
|
+
// connecting the NOVITA AI mark to Hivemind Labs, Inc., a Delaware corporation. The mark
|
|
2057
|
+
// application is now abandoned; it is cited only as the public operator-identity record.
|
|
2058
|
+
// Maintainer: @olddonkey; no affiliation with Novita AI or Hivemind Labs, Inc.
|
|
2059
|
+
id: "novita",
|
|
2060
|
+
label: "Novita AI",
|
|
2061
|
+
baseUrl: "https://api.novita.ai/openai/v1",
|
|
2062
|
+
adapter: "openai-chat",
|
|
2063
|
+
authKind: "key",
|
|
2064
|
+
dashboardUrl: "https://novita.ai/settings/key-management",
|
|
2065
|
+
liveModels: true,
|
|
2066
|
+
preserveCustomDestination: true,
|
|
2067
|
+
// The live catalog is public even though the reference shows an Authorization header, so a
|
|
2068
|
+
// successful model fetch cannot prove that a supplied key is valid.
|
|
2069
|
+
apiKeyValidation: "unknown",
|
|
2070
|
+
// The request reference documents tools but not a provider-wide parallel-tool contract.
|
|
2071
|
+
parallelToolCalls: false,
|
|
2072
|
+
// Novita exposes model-specific thinking flags, not an OpenAI reasoning_effort contract.
|
|
2073
|
+
reasoningEfforts: [],
|
|
2074
|
+
modelDiscovery: {
|
|
2075
|
+
path: "models",
|
|
2076
|
+
maxResponseBytes: 512 * 1024,
|
|
2077
|
+
maxModels: 256,
|
|
2078
|
+
filter: {
|
|
2079
|
+
// Require both Novita's chat classification and the exact configured wire endpoint.
|
|
2080
|
+
allOf: [
|
|
2081
|
+
{ path: ["model_type"], equalsAny: ["chat"] },
|
|
2082
|
+
{ path: ["endpoints"], containsAny: ["chat/completions"] },
|
|
2083
|
+
],
|
|
2084
|
+
},
|
|
2085
|
+
},
|
|
2086
|
+
note: "Public live catalog filtered to rows that explicitly report chat type and Chat Completions support; key validity remains unknown until an authenticated inference request.",
|
|
2087
|
+
},
|
|
1048
2088
|
// FREEZE 2026-07-10: exact serverless ids remain auth-gated/unverified. Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
|
|
1049
2089
|
{ id: "together", label: "Together", baseUrl: "https://api.together.xyz/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://api.together.xyz/settings/api-keys" },
|
|
1050
2090
|
{ id: "fireworks", label: "Fireworks", baseUrl: "https://api.fireworks.ai/inference/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://fireworks.ai/account/api-keys" },
|
|
@@ -1054,7 +2094,9 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1054
2094
|
note: "Model data frozen pending Tier-2 entitlement proof",
|
|
1055
2095
|
},
|
|
1056
2096
|
{
|
|
1057
|
-
id: "moonshot", label: "Moonshot (Kimi API)", baseUrl:
|
|
2097
|
+
id: "moonshot", label: "Moonshot (Kimi API)", baseUrl: MOONSHOT_INTL_BASE_URL, adapter: "openai-chat", authKind: "key",
|
|
2098
|
+
allowBaseUrlOverride: true,
|
|
2099
|
+
baseUrlChoices: MOONSHOT_BASE_URL_CHOICES,
|
|
1058
2100
|
dashboardUrl: "https://platform.moonshot.ai/console/api-keys", defaultModel: "kimi-k2.7-code", jawcodeBundle: "moonshot",
|
|
1059
2101
|
models: KIMI_API_MODELS,
|
|
1060
2102
|
modelContextWindows: KIMI_API_MODEL_CONTEXT_WINDOWS,
|
|
@@ -1066,6 +2108,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1066
2108
|
noPenaltyModels: KIMI_API_MODELS,
|
|
1067
2109
|
autoToolChoiceOnlyModels: ["kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
|
|
1068
2110
|
preserveReasoningContentModels: KIMI_API_MODELS,
|
|
2111
|
+
note: "International default (api.moonshot.ai). China accounts: choose China (.cn) or Custom for api.moonshot.cn.",
|
|
1069
2112
|
},
|
|
1070
2113
|
{ id: "huggingface", label: "Hugging Face", baseUrl: "https://router.huggingface.co/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://huggingface.co/settings/tokens" },
|
|
1071
2114
|
// 260715 NIM hardening (issue #126, devlog/_plan/260715_issue126_nim_kimi):
|
|
@@ -1081,6 +2124,11 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1081
2124
|
// Free pricing, but an API key is still required (free key from build.nvidia.com).
|
|
1082
2125
|
freeTier: true,
|
|
1083
2126
|
parallelToolCalls: false,
|
|
2127
|
+
// 260804 issue #956: NIM exposes no input modalities, so vision capability is
|
|
2128
|
+
// classified here. Both lists are verified per-model; unlisted ids stay unclassified
|
|
2129
|
+
// by design (see the comment on NVIDIA_NIM_VISION_MODELS).
|
|
2130
|
+
noVisionModels: NVIDIA_NIM_NO_VISION_MODELS,
|
|
2131
|
+
modelInputModalities: NVIDIA_NIM_VISION_INPUT_MODALITIES,
|
|
1084
2132
|
noReasoningModels: NVIDIA_NIM_KIMI_MODELS,
|
|
1085
2133
|
modelReasoningEfforts: Object.fromEntries(NVIDIA_NIM_KIMI_MODELS.map(id => [id, []])),
|
|
1086
2134
|
preserveReasoningContentModels: NVIDIA_NIM_KIMI_THINKING_MODELS,
|
|
@@ -1089,17 +2137,26 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1089
2137
|
{ id: "venice", label: "Venice", baseUrl: "https://api.venice.ai/api/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://venice.ai/settings/api" },
|
|
1090
2138
|
// 260710 GLM-5.2 context and path-specific ids: Tier-2 evidence in
|
|
1091
2139
|
// devlog/_plan/260710_provider_hardening/002_research_cn.md.
|
|
2140
|
+
// 260814: glm-5.3 / glm-5.3[1m] added per docs.z.ai/devpack/latest-model, which lists them as
|
|
2141
|
+
// Coding Plan ids on this same endpoint.
|
|
2142
|
+
// 260815: docs.z.ai/guides/llm/glm-5.3 now publishes the capability table (thinking, streaming,
|
|
2143
|
+
// function calling, caching, structured output) and a 128K output budget, recorded here as the
|
|
2144
|
+
// exact 131_072 every other source in this repo uses for that model. Coding Plan pricing stays
|
|
2145
|
+
// unpublished, so no cost entry is asserted.
|
|
1092
2146
|
{
|
|
1093
2147
|
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.
|
|
1095
|
-
note: "GLM-5.
|
|
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 },
|
|
2148
|
+
dashboardUrl: "https://z.ai/manage-apikey/apikey-list", defaultModel: "glm-5.3",
|
|
2149
|
+
note: "GLM-5.3 coding subscription",
|
|
2150
|
+
models: ["glm-5.3", "glm-5.3[1m]", "glm-5.2", "glm-5.2[1m]", "glm-5.1", "glm-5", "glm-4.6"],
|
|
2151
|
+
modelContextWindows: { "glm-5.3": 1_000_000, "glm-5.3[1m]": 1_000_000, "glm-5.2": 1_000_000, "glm-5.2[1m]": 1_000_000 },
|
|
1098
2152
|
// Z.AI's OpenAI path returns 400 code 1211 for bracketed model ids.
|
|
1099
2153
|
modelSuffixBracketStrip: true,
|
|
1100
|
-
noVisionModels:
|
|
1101
|
-
modelReasoningEfforts:
|
|
1102
|
-
|
|
2154
|
+
noVisionModels: ZAI_GLM_5X_MODELS,
|
|
2155
|
+
modelReasoningEfforts: ZAI_GLM_5X_REASONING_EFFORTS,
|
|
2156
|
+
modelDefaultReasoningEfforts: Object.fromEntries(ZAI_GLM_53_MODELS.map(id => [id, "max"])),
|
|
2157
|
+
modelMaxOutputTokens: Object.fromEntries(ZAI_GLM_53_MODELS.map(id => [id, 131_072])),
|
|
2158
|
+
modelSupportsReasoningSummaries: Object.fromEntries(ZAI_GLM_5X_MODELS.map(id => [id, true])),
|
|
2159
|
+
preserveReasoningContentModels: ZAI_GLM_5X_MODELS,
|
|
1103
2160
|
},
|
|
1104
2161
|
// Zhipu's domestic BigModel platform: OpenAI-compatible pay-as-you-go on open.bigmodel.cn — a
|
|
1105
2162
|
// different host and billing product from the `zai` coding-plan subscription above.
|
|
@@ -1135,11 +2192,54 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1135
2192
|
modelReasoningEffortMap: Object.fromEntries(
|
|
1136
2193
|
ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS.map(id => [id, THINKING_TOGGLE_MAP]),
|
|
1137
2194
|
),
|
|
2195
|
+
modelSupportsReasoningSummaries: Object.fromEntries(
|
|
2196
|
+
ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS.map(id => [id, true]),
|
|
2197
|
+
),
|
|
1138
2198
|
preserveReasoningContentModels: ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS,
|
|
2199
|
+
// GLM thinking is a binary toggle (low maps to disabled), so a legitimate
|
|
2200
|
+
// tool round can carry no reasoning at all; never fabricate a placeholder
|
|
2201
|
+
// for it, only replay real recorded text (P2 on #1205).
|
|
2202
|
+
requiresReasoningPlaceholderModels: [],
|
|
1139
2203
|
// No liveModels: GET /api/paas/v4/models has not been observed to answer on this host, and a
|
|
1140
2204
|
// false live claim yields an empty picker at runtime. Flip it on once someone verifies it.
|
|
1141
2205
|
note: "Domestic BigModel pay-as-you-go endpoint (open.bigmodel.cn)",
|
|
1142
2206
|
},
|
|
2207
|
+
// BigModel's Coding Plan is a SEPARATE endpoint from the pay-as-you-go row above, and that is
|
|
2208
|
+
// the whole reason this one exists. #1100 was reported against
|
|
2209
|
+
// `https://open.bigmodel.cn/api/coding/paas/v4`; the row above covers only `/api/paas/v4`, so
|
|
2210
|
+
// destination enrichment matched nothing, `modelSupportsReasoningSummaries` stayed unset, and
|
|
2211
|
+
// Codex kept dropping the inbound reasoning object — effort displayed as `-`.
|
|
2212
|
+
//
|
|
2213
|
+
// A prefix or fuzzy endpoint match would have been the shortcut. It is also how a config
|
|
2214
|
+
// pointed at one vendor route silently inherits another route's metadata, so endpoints stay
|
|
2215
|
+
// exact and each one gets its own row.
|
|
2216
|
+
//
|
|
2217
|
+
// The id is NOT `glm-cn`, which the free-provider directory already binds to this same coding
|
|
2218
|
+
// path: registering it here would let routedProviderConfig() canonicalize a saved `glm-cn`
|
|
2219
|
+
// config onto this baseUrl. Same reasoning as `zhipu-bigmodel` above.
|
|
2220
|
+
//
|
|
2221
|
+
// Models follow Z.AI's coding-plan list rather than the pay-as-you-go one. This endpoint is
|
|
2222
|
+
// the subscription product, and the reporter's `glm-5.2` is only on that side.
|
|
2223
|
+
{
|
|
2224
|
+
id: "zhipu-bigmodel-coding",
|
|
2225
|
+
label: "Zhipu AI — BigModel Coding Plan",
|
|
2226
|
+
baseUrl: "https://open.bigmodel.cn/api/coding/paas/v4",
|
|
2227
|
+
adapter: "openai-chat",
|
|
2228
|
+
authKind: "key",
|
|
2229
|
+
dashboardUrl: "https://bigmodel.cn/console/usercenter/apikeys",
|
|
2230
|
+
defaultModel: "glm-5.3",
|
|
2231
|
+
models: ["glm-5.3", "glm-5.3[1m]", "glm-5.2", "glm-5.2[1m]", "glm-5.1", "glm-5", "glm-4.6"],
|
|
2232
|
+
jawcodeBundle: "zai",
|
|
2233
|
+
modelContextWindows: { "glm-5.3": 1_000_000, "glm-5.3[1m]": 1_000_000, "glm-5.2": 1_000_000, "glm-5.2[1m]": 1_000_000 },
|
|
2234
|
+
modelSuffixBracketStrip: true,
|
|
2235
|
+
noVisionModels: ZAI_GLM_5X_MODELS,
|
|
2236
|
+
modelReasoningEfforts: ZAI_GLM_5X_REASONING_EFFORTS,
|
|
2237
|
+
modelSupportsReasoningSummaries: Object.fromEntries(ZAI_GLM_5X_MODELS.map(id => [id, true])),
|
|
2238
|
+
preserveReasoningContentModels: ZAI_GLM_5X_MODELS,
|
|
2239
|
+
// No liveModels: the same reasoning as the pay-as-you-go row — an unverified live claim
|
|
2240
|
+
// yields an empty picker at runtime.
|
|
2241
|
+
note: "Domestic BigModel Coding Plan endpoint (open.bigmodel.cn)",
|
|
2242
|
+
},
|
|
1143
2243
|
{ id: "nanogpt", label: "NanoGPT", baseUrl: "https://nano-gpt.com/api/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://nano-gpt.com/api" },
|
|
1144
2244
|
{ id: "synthetic", label: "Synthetic", baseUrl: "https://api.synthetic.new/openai/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://synthetic.new" },
|
|
1145
2245
|
// SiliconFlow publishes an OpenAI-compatible chat endpoint and a dynamic model catalog. Do not
|
|
@@ -1230,10 +2330,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1230
2330
|
modelInputModalities: VOLCENGINE_PLAN_INPUT_MODALITIES,
|
|
1231
2331
|
noVisionModels: VOLCENGINE_PLAN_TEXT_ONLY_MODELS,
|
|
1232
2332
|
modelReasoningEfforts: Object.fromEntries(
|
|
1233
|
-
DEEPSEEK_THINKING_MODELS.map(id => [id,
|
|
2333
|
+
DEEPSEEK_THINKING_MODELS.map(id => [id, deepseekThinkingEffortsFor(id)]),
|
|
1234
2334
|
),
|
|
1235
2335
|
modelReasoningEffortMap: Object.fromEntries(
|
|
1236
|
-
DEEPSEEK_THINKING_MODELS.map(id => [id,
|
|
2336
|
+
DEEPSEEK_THINKING_MODELS.map(id => [id, deepseekReasoningMapFor(id)]),
|
|
1237
2337
|
),
|
|
1238
2338
|
preserveReasoningContentModels: DEEPSEEK_THINKING_MODELS,
|
|
1239
2339
|
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.",
|
|
@@ -1245,6 +2345,8 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1245
2345
|
responsesPath: "/responses",
|
|
1246
2346
|
adapter: "openai-responses",
|
|
1247
2347
|
authKind: "key",
|
|
2348
|
+
// Ark's plan route does not document `service_tier`; fail closed like DeepSeek.
|
|
2349
|
+
supportsServiceTier: false,
|
|
1248
2350
|
preserveCustomDestination: true,
|
|
1249
2351
|
dashboardUrl: "https://console.volcengine.com/ark/region:ark+cn-beijing/overview",
|
|
1250
2352
|
defaultModel: "deepseek-v4-pro",
|
|
@@ -1265,24 +2367,28 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1265
2367
|
adapter: "openai-chat",
|
|
1266
2368
|
authKind: "key",
|
|
1267
2369
|
dashboardUrl: "https://bailian.console.aliyun.com/cn-beijing?tab=plan",
|
|
1268
|
-
defaultModel: "qwen3.8-max
|
|
2370
|
+
defaultModel: "qwen3.8-max",
|
|
1269
2371
|
models: ALIBABA_TOKEN_PLAN_MODELS,
|
|
1270
2372
|
liveModels: false,
|
|
1271
2373
|
note: "Token Plan Personal Edition · China (Beijing)",
|
|
1272
2374
|
modelInputModalities: ALIBABA_TOKEN_PLAN_INPUT_MODALITIES,
|
|
1273
2375
|
modelContextWindows: {
|
|
1274
|
-
"qwen3.8-max
|
|
1275
|
-
"qwen3.6-flash": 1_000_000, "glm-5.2": 1_000_000, "deepseek-v4-pro": 1_000_000,
|
|
2376
|
+
"qwen3.8-max": 983_616, "qwen3.7-max": 1_000_000, "qwen3.7-plus": 1_000_000,
|
|
2377
|
+
"qwen3.6-flash": 1_000_000, "glm-5.3": 1_000_000, "glm-5.2": 1_000_000, "deepseek-v4-pro": 1_000_000,
|
|
1276
2378
|
},
|
|
1277
2379
|
modelReasoningEfforts: {
|
|
1278
2380
|
...Object.fromEntries(ALIBABA_TOKEN_PLAN_QWEN_MODELS.map(id => [id, THINKING_BUDGET_EFFORTS])),
|
|
2381
|
+
"qwen3.8-max": QWEN38_REASONING_EFFORTS,
|
|
2382
|
+
"glm-5.3": ZAI_GLM_53_REASONING_EFFORTS,
|
|
1279
2383
|
"glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
|
|
1280
|
-
"deepseek-v4-pro":
|
|
2384
|
+
"deepseek-v4-pro": deepseekThinkingEffortsFor("deepseek-v4-pro"),
|
|
1281
2385
|
},
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
2386
|
+
modelDefaultReasoningEfforts: { "qwen3.8-max": "xhigh" },
|
|
2387
|
+
modelReasoningEffortMap: { "deepseek-v4-pro": deepseekReasoningMapFor("deepseek-v4-pro") },
|
|
2388
|
+
directReasoningEffortModels: ["qwen3.8-max"],
|
|
2389
|
+
thinkingBudgetModels: ALIBABA_TOKEN_PLAN_QWEN_MODELS.filter(id => id !== "qwen3.8-max"),
|
|
2390
|
+
preserveReasoningContentModels: ["glm-5.3", "glm-5.2", "deepseek-v4-pro", "qwen3.8-max", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-flash"],
|
|
2391
|
+
noVisionModels: ["glm-5.3", "glm-5.2", "deepseek-v4-pro"],
|
|
1286
2392
|
},
|
|
1287
2393
|
{
|
|
1288
2394
|
id: "alibaba-token-plan-intl",
|
|
@@ -1300,29 +2406,31 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1300
2406
|
metadataModelIdNormalize: "case-insensitive",
|
|
1301
2407
|
modelInputModalities: ALIBABA_INTL_TOKEN_PLAN_INPUT_MODALITIES,
|
|
1302
2408
|
modelContextWindows: {
|
|
1303
|
-
"qwen3.8-max
|
|
2409
|
+
"qwen3.8-max": 983_616,
|
|
1304
2410
|
"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
2411
|
"deepseek-v4-pro": 1_000_000, "deepseek-v4-flash": 1_000_000, "deepseek-v3.2": 131_072,
|
|
1306
2412
|
"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,
|
|
2413
|
+
"glm-5.3": 1_000_000, "glm-5.2": 1_000_000, "glm-5.1": 1_000_000, "glm-5": 1_000_000,
|
|
1308
2414
|
"MiniMax-M2.5": 204_800,
|
|
1309
2415
|
},
|
|
1310
2416
|
modelReasoningEfforts: {
|
|
1311
2417
|
...Object.fromEntries(ALIBABA_INTL_TOKEN_PLAN_QWEN_MODELS.map(id => [id, THINKING_BUDGET_EFFORTS])),
|
|
1312
|
-
"qwen3.8-max
|
|
2418
|
+
"qwen3.8-max": QWEN38_REASONING_EFFORTS,
|
|
2419
|
+
"glm-5.3": ZAI_GLM_53_REASONING_EFFORTS,
|
|
1313
2420
|
"glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
|
|
1314
|
-
"deepseek-v4-pro":
|
|
1315
|
-
"deepseek-v4-flash":
|
|
2421
|
+
"deepseek-v4-pro": deepseekThinkingEffortsFor("deepseek-v4-pro"),
|
|
2422
|
+
"deepseek-v4-flash": deepseekThinkingEffortsFor("deepseek-v4-flash"),
|
|
1316
2423
|
},
|
|
1317
2424
|
modelReasoningEffortMap: {
|
|
1318
|
-
"deepseek-v4-pro":
|
|
1319
|
-
"deepseek-v4-flash":
|
|
2425
|
+
"deepseek-v4-pro": deepseekReasoningMapFor("deepseek-v4-pro"),
|
|
2426
|
+
"deepseek-v4-flash": deepseekReasoningMapFor("deepseek-v4-flash"),
|
|
1320
2427
|
},
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
2428
|
+
directReasoningEffortModels: ["qwen3.8-max"],
|
|
2429
|
+
thinkingBudgetModels: ALIBABA_INTL_TOKEN_PLAN_QWEN_MODELS.filter(id => id !== "qwen3.8-max"),
|
|
2430
|
+
preserveReasoningContentModels: ["glm-5.3", "glm-5.2", "deepseek-v4-pro", "deepseek-v4-flash", "qwen3.8-max", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", "qwen3.6-flash"],
|
|
2431
|
+
noVisionModels: ["deepseek-v4-pro", "deepseek-v4-flash", "deepseek-v3.2", "glm-5.3", "glm-5.2", "glm-5.1", "glm-5", "MiniMax-M2.5"],
|
|
1324
2432
|
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
|
|
2433
|
+
modelDefaultReasoningEfforts: { "qwen3.8-max": "xhigh" },
|
|
1326
2434
|
},
|
|
1327
2435
|
// NEEDS_HUMAN 2026-07-10: kept for config compatibility, but this is a dashboard URL,
|
|
1328
2436
|
// no /models endpoint is documented, and tools are silently ignored upstream per docs.parallel.ai.
|
|
@@ -1352,10 +2460,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1352
2460
|
authKind: "key",
|
|
1353
2461
|
dashboardUrl: "https://ollama.com/settings/keys",
|
|
1354
2462
|
// 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.
|
|
2463
|
+
models: ["glm-5.3", "glm-5.2", "deepseek-v4-pro", "qwen3-coder:480b", "gpt-oss:120b", "kimi-k2.6", "minimax-m3", "qwen3.5:397b", "gemma4:31b"],
|
|
2464
|
+
defaultModel: "glm-5.3",
|
|
1357
2465
|
noVisionModels: [
|
|
1358
|
-
"glm-5.2", "glm-5.1", "glm-5", "glm-4.7",
|
|
2466
|
+
"glm-5.3", "glm-5.2", "glm-5.1", "glm-5", "glm-4.7",
|
|
1359
2467
|
"minimax-m2.7", "minimax-m2.5", "minimax-m2.1",
|
|
1360
2468
|
"nemotron-3-ultra", "nemotron-3-super",
|
|
1361
2469
|
"deepseek-v4-pro", "deepseek-v4-flash",
|
|
@@ -1372,6 +2480,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1372
2480
|
modelDefaultReasoningEfforts: { "MiniMax-M3": "medium" },
|
|
1373
2481
|
modelReasoningEffortMap: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORT_MAP },
|
|
1374
2482
|
preserveReasoningContentModels: MINIMAX_MODELS,
|
|
2483
|
+
// MiniMax-M3 low effort maps to thinking disabled, so a legitimate tool
|
|
2484
|
+
// round can carry no reasoning at all; only replay real recorded text,
|
|
2485
|
+
// never a fabricated placeholder (chatgpt-codex-connector P2 on #1205).
|
|
2486
|
+
requiresReasoningPlaceholderModels: [],
|
|
1375
2487
|
reasoningSplitModels: MINIMAX_MODELS,
|
|
1376
2488
|
thinkingToggleModels: ["MiniMax-M3"],
|
|
1377
2489
|
jawcodeBundle: "minimax", metadataModelIdNormalize: "case-insensitive", note: "Subscription Key or API Key",
|
|
@@ -1384,6 +2496,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1384
2496
|
modelDefaultReasoningEfforts: { "MiniMax-M3": "medium" },
|
|
1385
2497
|
modelReasoningEffortMap: { "MiniMax-M3": MINIMAX_M3_REASONING_EFFORT_MAP },
|
|
1386
2498
|
preserveReasoningContentModels: MINIMAX_MODELS,
|
|
2499
|
+
requiresReasoningPlaceholderModels: [],
|
|
1387
2500
|
reasoningSplitModels: MINIMAX_MODELS,
|
|
1388
2501
|
thinkingToggleModels: ["MiniMax-M3"],
|
|
1389
2502
|
jawcodeBundle: "minimax", metadataModelIdNormalize: "case-insensitive", note: "中国区 Subscription Key",
|
|
@@ -1407,7 +2520,33 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1407
2520
|
autoToolChoiceOnlyModels: KIMI_AUTO_TOOL_CHOICE_ONLY_MODELS,
|
|
1408
2521
|
preserveReasoningContentModels: KIMI_THINKING_MODELS,
|
|
1409
2522
|
},
|
|
1410
|
-
{
|
|
2523
|
+
{
|
|
2524
|
+
id: "opencode-zen", label: "opencode zen", baseUrl: "https://opencode.ai/zen/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://opencode.ai/auth",
|
|
2525
|
+
// Same opencode.ai/zen/v1 gateway as `opencode-free` (keyed tier): DeepSeek thinking mode
|
|
2526
|
+
// requires the assistant's original reasoning_content to be replayed on tool-call
|
|
2527
|
+
// continuations, or the gateway answers HTTP 400 (issues #950/#994). Mirror the DeepSeek
|
|
2528
|
+
// reasoning + thinking metadata so `opencode-zen/deepseek-v4-flash-free` — and the other
|
|
2529
|
+
// Zen DeepSeek thinking models — never serialize a bare tool-call turn.
|
|
2530
|
+
note: "Keyed OpenCode Zen gateway. Free models on this tier are often short-window rate-limited at roughly 15-20 requests/minute (community-measured; OpenCode does not publish RPM). Zen may return generic 429s without Retry-After / X-RateLimit headers; when Retry-After is omitted, opencodex adds a synthetic backoff hint (upstream Retry-After still wins). Distinct from the keyless opencode-free desktop quota (~200 Big Pickle/free-model requests per 5 hours). Docs: https://opencode.ai/docs/zen/. Free-model prompts may be retained for training — do not send confidential material.",
|
|
2531
|
+
modelReasoningEfforts: Object.fromEntries(
|
|
2532
|
+
[...DEEPSEEK_THINKING_MODELS, ...OPENCODE_FREE_DEEPSEEK_MODELS].map(id => [id, deepseekThinkingEffortsFor(id)]),
|
|
2533
|
+
),
|
|
2534
|
+
modelReasoningEffortMap: Object.fromEntries(
|
|
2535
|
+
[...DEEPSEEK_THINKING_MODELS, ...OPENCODE_FREE_DEEPSEEK_MODELS].map(id => [id, deepseekReasoningMapFor(id)]),
|
|
2536
|
+
),
|
|
2537
|
+
preserveReasoningContentModels: [...DEEPSEEK_THINKING_MODELS, ...OPENCODE_FREE_DEEPSEEK_MODELS],
|
|
2538
|
+
// Same Zen gateway as opencode-free: Ox Alpha Free (1M multimodal stealth model)
|
|
2539
|
+
// and the DeepSeek vision preview (merges into deepseek-v4-flash later).
|
|
2540
|
+
modelContextWindows: {
|
|
2541
|
+
[OPENCODE_OX_ALPHA_FREE_MODEL]: OX_ALPHA_CONTEXT_WINDOW,
|
|
2542
|
+
[DEEPSEEK_VISION_PREVIEW_MODEL]: 1_048_576,
|
|
2543
|
+
},
|
|
2544
|
+
modelInputModalities: {
|
|
2545
|
+
[OPENCODE_OX_ALPHA_FREE_MODEL]: ["text", "image"],
|
|
2546
|
+
[DEEPSEEK_VISION_PREVIEW_MODEL]: ["text", "image"],
|
|
2547
|
+
},
|
|
2548
|
+
noVisionModels: [...OPENCODE_ZEN_TEXT_ONLY_MODELS, ...DEEPSEEK_THINKING_MODELS],
|
|
2549
|
+
},
|
|
1411
2550
|
{ 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
2551
|
{
|
|
1413
2552
|
id: "opencode-free",
|
|
@@ -1418,17 +2557,59 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1418
2557
|
keyOptional: true,
|
|
1419
2558
|
featured: true,
|
|
1420
2559
|
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.",
|
|
2560
|
+
note: "No key needed — public desktop tier. OpenCode currently advertises about 200 Big Pickle/free-model requests per 5 hours. The same Zen gateway can also short-window rate-limit free models at roughly 15-20 requests/minute, and may return generic 429s without Retry-After (opencodex synthesizes backoff only when that header is omitted). 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
2561
|
dashboardUrl: "https://opencode.ai",
|
|
1423
2562
|
staticHeaders: {
|
|
2563
|
+
// Zen answers a bare runtime User-Agent (Bun/x.y.z) more aggressively than a client
|
|
2564
|
+
// that identifies itself, which is what the 429 in #2067 traced to. The value is
|
|
2565
|
+
// deliberately unversioned: a pinned "opencode-cli/<version>" is a claim about an
|
|
2566
|
+
// install we do not have and goes stale on the vendor's schedule, not ours.
|
|
2567
|
+
// Corroboration, not authority: OmniRoute — an independent open-source broker against
|
|
2568
|
+
// the same Zen upstream — defaults to exactly this pair (userAgent "opencode", client
|
|
2569
|
+
// "desktop") in open-sse/executors/opencode.ts, and got there by RETREATING from its
|
|
2570
|
+
// own earlier "opencode-cli/1.0.0" pin. An operator can still override either value
|
|
2571
|
+
// through the provider headers API; user headers win case-insensitively at route time.
|
|
2572
|
+
"User-Agent": "opencode",
|
|
1424
2573
|
"x-opencode-client": "desktop",
|
|
1425
2574
|
},
|
|
1426
|
-
modelReasoningEfforts: Object.fromEntries(OPENCODE_FREE_DEEPSEEK_MODELS.map(id => [id,
|
|
1427
|
-
modelReasoningEffortMap: Object.fromEntries(OPENCODE_FREE_DEEPSEEK_MODELS.map(id => [id,
|
|
2575
|
+
modelReasoningEfforts: Object.fromEntries(OPENCODE_FREE_DEEPSEEK_MODELS.map(id => [id, deepseekThinkingEffortsFor(id)])),
|
|
2576
|
+
modelReasoningEffortMap: Object.fromEntries(OPENCODE_FREE_DEEPSEEK_MODELS.map(id => [id, deepseekReasoningMapFor(id)])),
|
|
1428
2577
|
preserveReasoningContentModels: OPENCODE_FREE_DEEPSEEK_MODELS,
|
|
1429
|
-
|
|
2578
|
+
// Ox Alpha Free (`x-preview-f-free`): the OpenRouter stealth model on Zen's
|
|
2579
|
+
// free tier — 1,048,576 context, text+image input. Deliberately NOT in the
|
|
2580
|
+
// text-only list below. The DeepSeek vision preview id is preemptive
|
|
2581
|
+
// metadata for when Zen starts serving it (merges into v4-flash later).
|
|
2582
|
+
modelContextWindows: {
|
|
2583
|
+
[OPENCODE_OX_ALPHA_FREE_MODEL]: OX_ALPHA_CONTEXT_WINDOW,
|
|
2584
|
+
[DEEPSEEK_VISION_PREVIEW_MODEL]: 1_048_576,
|
|
2585
|
+
},
|
|
2586
|
+
modelInputModalities: {
|
|
2587
|
+
[OPENCODE_OX_ALPHA_FREE_MODEL]: ["text", "image"],
|
|
2588
|
+
[DEEPSEEK_VISION_PREVIEW_MODEL]: ["text", "image"],
|
|
2589
|
+
},
|
|
2590
|
+
// Same Zen roster behind the same base URL, so it carries the same measured
|
|
2591
|
+
// text-only list rather than only its DeepSeek member (#1043).
|
|
2592
|
+
noVisionModels: OPENCODE_ZEN_TEXT_ONLY_MODELS,
|
|
1430
2593
|
},
|
|
1431
2594
|
{ id: "xiaomi", label: "Xiaomi MiMo", baseUrl: "https://api.xiaomimimo.com/anthropic", adapter: "anthropic", authKind: "key", dashboardUrl: "https://xiaomimimo.com", defaultModel: "mimo-v2.5-pro" },
|
|
2595
|
+
// Xiaomi's public OpenAI-compatible endpoint is a distinct transport from both the Anthropic
|
|
2596
|
+
// preset above and the paid token-plan host below. Keep a separate fixed-destination contract
|
|
2597
|
+
// so existing custom providers are never retargeted while the official route receives the
|
|
2598
|
+
// strict reasoning ladder its validator enforces (#1483).
|
|
2599
|
+
{
|
|
2600
|
+
id: "xiaomi-mimo",
|
|
2601
|
+
label: "Xiaomi MiMo (OpenAI Chat)",
|
|
2602
|
+
baseUrl: "https://api.xiaomimimo.com/v1",
|
|
2603
|
+
adapter: "openai-chat",
|
|
2604
|
+
authKind: "key",
|
|
2605
|
+
dashboardUrl: "https://platform.xiaomimimo.com/console/balance",
|
|
2606
|
+
defaultModel: "mimo-v2.5",
|
|
2607
|
+
models: ["mimo-v2.5"],
|
|
2608
|
+
reasoningEfforts: ["low", "medium", "high"],
|
|
2609
|
+
reasoningEffortMap: { xhigh: "high", max: "high", ultra: "high" },
|
|
2610
|
+
preserveCustomDestination: true,
|
|
2611
|
+
note: "Official Xiaomi MiMo OpenAI-compatible Chat endpoint. The upstream validator accepts reasoning_effort none/low/medium/high; higher Codex tiers are clamped to high.",
|
|
2612
|
+
},
|
|
1432
2613
|
{ id: "kilo", label: "Kilo", baseUrl: "https://api.kilo.ai/api/gateway", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://kilo.ai" },
|
|
1433
2614
|
{
|
|
1434
2615
|
id: "mimo-free",
|
|
@@ -1442,13 +2623,48 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1442
2623
|
dashboardUrl: "https://xiaomimimo.com",
|
|
1443
2624
|
defaultModel: "mimo-auto",
|
|
1444
2625
|
models: ["mimo-auto"],
|
|
2626
|
+
reasoningEfforts: ["low", "medium", "high"],
|
|
2627
|
+
reasoningEffortMap: { xhigh: "high", max: "high", ultra: "high" },
|
|
1445
2628
|
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
2629
|
},
|
|
2630
|
+
// Xiaomi MiMo paid token plan. Separate host and wire from both `xiaomi` (Anthropic) and
|
|
2631
|
+
// `mimo-free` (free tier, bespoke adapter), so it needs its own entry rather than a variant.
|
|
2632
|
+
//
|
|
2633
|
+
// Pinned to openai-chat deliberately (#1158). The endpoint answers the Responses wire for
|
|
2634
|
+
// plain turns, which is why users configuring it by hand pick `openai-responses` — MiMo
|
|
2635
|
+
// documents Responses support. But its gateway rejects `type: "custom"` tools with
|
|
2636
|
+
// `400 responses_feature_not_supported`, and `apply_patch` is a custom tool, so every agentic
|
|
2637
|
+
// turn fails while chat turns succeed. The Chat path lowers custom tools to `{input: string}`
|
|
2638
|
+
// functions and restores them as `custom_tool_call`, so the capability survives intact.
|
|
2639
|
+
// Stripping the tools instead would stop the 400 and disable the agent loop.
|
|
2640
|
+
{
|
|
2641
|
+
id: "mimo",
|
|
2642
|
+
label: "Xiaomi MiMo (token plan)",
|
|
2643
|
+
baseUrl: "https://token-plan-cn.xiaomimimo.com/v1",
|
|
2644
|
+
adapter: "openai-chat",
|
|
2645
|
+
authKind: "key",
|
|
2646
|
+
dashboardUrl: "https://xiaomimimo.com",
|
|
2647
|
+
defaultModel: "mimo-v2.5-pro",
|
|
2648
|
+
models: ["mimo-v2.5-pro", "mimo-v2.5"],
|
|
2649
|
+
// The gateway validates the ladder strictly and rejects anything above `high`.
|
|
2650
|
+
reasoningEfforts: ["low", "medium", "high"],
|
|
2651
|
+
reasoningEffortMap: { xhigh: "high", max: "high", ultra: "high" },
|
|
2652
|
+
// Live token-plan verification (#1927): the Pro route rejects image input while
|
|
2653
|
+
// mimo-v2.5 accepts it natively. Keep this provider-scoped so a hand-rolled
|
|
2654
|
+
// provider with the same id but another destination does not inherit the claim.
|
|
2655
|
+
noVisionModels: ["mimo-v2.5-pro"],
|
|
2656
|
+
// A user may already have hand-rolled a provider under this id against a different host;
|
|
2657
|
+
// without this, routedProviderConfig() would canonicalize their base URL onto ours and send
|
|
2658
|
+
// their key somewhere they did not choose.
|
|
2659
|
+
preserveCustomDestination: true,
|
|
2660
|
+
note: "Xiaomi MiMo paid token plan. Pinned to the Chat wire: the Responses endpoint rejects freeform (custom) tools such as apply_patch with 400 responses_feature_not_supported, so agentic turns fail there while plain turns succeed. Reasoning tiers above high are clamped.",
|
|
2661
|
+
},
|
|
1447
2662
|
{ 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
2663
|
{
|
|
1449
2664
|
// Cloudflare Workers AI: OpenAI-compatible endpoint. The base URL contains {account_id}
|
|
1450
2665
|
// which must be resolved by the user at setup time. Model IDs use the @cf/ prefix.
|
|
1451
2666
|
// Live-verified 2026-07-21 against https://developers.cloudflare.com/workers-ai/models/
|
|
2667
|
+
// Official search is sibling to /ai/v1 (GET .../ai/models/search?format=openrouter).
|
|
1452
2668
|
id: "cloudflare-workers-ai", label: "Cloudflare Workers AI",
|
|
1453
2669
|
baseUrl: "https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/v1",
|
|
1454
2670
|
adapter: "openai-chat", authKind: "key", freeTier: true,
|
|
@@ -1459,9 +2675,17 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1459
2675
|
"@cf/qwen/qwq-32b",
|
|
1460
2676
|
"@cf/deepseek-ai/deepseek-r1-distill-qwen-32b",
|
|
1461
2677
|
"@cf/moonshotai/kimi-k2.7-code",
|
|
2678
|
+
"@cf/zai-org/glm-5.3",
|
|
1462
2679
|
"@cf/zai-org/glm-5.2",
|
|
1463
2680
|
"@cf/mistralai/mistral-small-3.1-24b-instruct",
|
|
1464
2681
|
],
|
|
2682
|
+
liveModels: true,
|
|
2683
|
+
modelDiscovery: {
|
|
2684
|
+
path: "../models/search",
|
|
2685
|
+
query: { format: "openrouter", per_page: "1000" },
|
|
2686
|
+
stripIdPrefix: "workers-ai/",
|
|
2687
|
+
maxModels: 256,
|
|
2688
|
+
},
|
|
1465
2689
|
note: "Workers AI · Free tier included · Account ID required in base URL",
|
|
1466
2690
|
},
|
|
1467
2691
|
// FREEZE 2026-07-10: /models was auth-gated under key login. OAuth device-flow + copilot_internal
|
|
@@ -1476,18 +2700,83 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1476
2700
|
featured: false,
|
|
1477
2701
|
dashboardUrl: "https://github.com/settings/copilot",
|
|
1478
2702
|
liveModels: true,
|
|
1479
|
-
models: ["gpt-4o", "gpt-4.1", "gpt-4.1-mini", "claude-sonnet-4", "gemini-2.5-pro"],
|
|
2703
|
+
models: ["gpt-4o", "gpt-4.1", "gpt-4.1-mini", "claude-sonnet-4", "gemini-2.5-pro", "gpt-5-mini", "gpt-5.3-codex", "gpt-5.4", "gpt-5.4-mini", "gpt-5.5", "gpt-5.6-luna", "gpt-5.6-sol", "gpt-5.6-terra"],
|
|
1480
2704
|
defaultModel: "gpt-4o",
|
|
2705
|
+
// Copilot fronts a mixed-wire catalog: these models reject /chat/completions for
|
|
2706
|
+
// real Codex-agent traffic (function tools + reasoning), so every inbound wire
|
|
2707
|
+
// rides Responses. Evidence: issue #748 field runs, pi.dev/models/github-copilot/*
|
|
2708
|
+
// wire declarations, BerriAI/litellm#23332 (gpt-5.4), JetBrains LLM-29711
|
|
2709
|
+
// (gpt-5.6-sol). gpt-5.4-nano is deliberately absent — it has no field report; a
|
|
2710
|
+
// user can opt it in with an explicit modelAdapters entry, which always wins.
|
|
2711
|
+
modelWireDefaults: {
|
|
2712
|
+
"gpt-5.3-codex": "openai-responses",
|
|
2713
|
+
"gpt-5.4": "openai-responses",
|
|
2714
|
+
"gpt-5.4-mini": "openai-responses",
|
|
2715
|
+
"gpt-5.5": "openai-responses",
|
|
2716
|
+
"gpt-5.6-luna": "openai-responses",
|
|
2717
|
+
"gpt-5.6-sol": "openai-responses",
|
|
2718
|
+
"gpt-5.6-terra": "openai-responses",
|
|
2719
|
+
},
|
|
1481
2720
|
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
2721
|
},
|
|
1483
2722
|
// FREEZE 2026-07-10: no public OpenAI-compatible endpoint is documented. Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
|
|
1484
2723
|
{ 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
2724
|
];
|
|
1486
2725
|
|
|
2726
|
+
export function providerRegistryFastWireError(
|
|
2727
|
+
entry: Pick<ProviderRegistryEntry, "fastWire" | "supportsServiceTier" | "modelSupportsServiceTier">,
|
|
2728
|
+
): string | null {
|
|
2729
|
+
return fastWireDeclarationError(entry);
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
for (const entry of PROVIDER_REGISTRY) {
|
|
2733
|
+
const error = providerRegistryFastWireError(entry);
|
|
2734
|
+
if (error) throw new TypeError(`Invalid provider registry entry ${entry.id}: ${error}`);
|
|
2735
|
+
}
|
|
2736
|
+
|
|
1487
2737
|
export function getProviderRegistryEntry(id: string): ProviderRegistryEntry | undefined {
|
|
1488
2738
|
return PROVIDER_REGISTRY.find(entry => entry.id === id);
|
|
1489
2739
|
}
|
|
1490
2740
|
|
|
2741
|
+
/**
|
|
2742
|
+
* Merge a registry row's `staticHeaders` beneath a provider's own headers.
|
|
2743
|
+
*
|
|
2744
|
+
* The field is documented as "merged into every upstream request for this provider", but that
|
|
2745
|
+
* was only ever true for a freshly seeded config: `providerConfigSeed` copies the block once
|
|
2746
|
+
* (`derive.ts`), `enrichProviderFromCatalog` fills it only when the whole block is absent, and
|
|
2747
|
+
* nothing merged it at request time. So an install that predates a header — or that saved any
|
|
2748
|
+
* header of its own — never received the new one, which is exactly what #2067 would have
|
|
2749
|
+
* shipped for every existing opencode-free user.
|
|
2750
|
+
*
|
|
2751
|
+
* The comparison is case-insensitive on purpose. HTTP header names are case-insensitive, but a
|
|
2752
|
+
* plain object spread is not: merging a registry `User-Agent` over a user's `user-agent`
|
|
2753
|
+
* produces two entries that `Headers` serializes as one comma-joined value
|
|
2754
|
+
* ("opencode, custom-agent"), which is a corrupted request rather than an override. The user's
|
|
2755
|
+
* spelling and value both win; the registry only fills names the user has not spoken for.
|
|
2756
|
+
*/
|
|
2757
|
+
export function mergeRegistryStaticHeaders(
|
|
2758
|
+
staticHeaders: Record<string, string> | undefined,
|
|
2759
|
+
userHeaders: Record<string, string> | undefined,
|
|
2760
|
+
): Record<string, string> | undefined {
|
|
2761
|
+
if (!staticHeaders) return userHeaders;
|
|
2762
|
+
if (!userHeaders) return { ...staticHeaders };
|
|
2763
|
+
const claimed = new Set(Object.keys(userHeaders).map(name => name.toLowerCase()));
|
|
2764
|
+
const merged: Record<string, string> = { ...userHeaders };
|
|
2765
|
+
for (const [name, value] of Object.entries(staticHeaders)) {
|
|
2766
|
+
if (!claimed.has(name.toLowerCase())) merged[name] = value;
|
|
2767
|
+
}
|
|
2768
|
+
return merged;
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
/** Whether this registry row's per-model service-tier evidence applies to one configured target. */
|
|
2772
|
+
export function registryModelServiceTierCapabilityApplies(
|
|
2773
|
+
entry: Pick<ProviderRegistryEntry, "modelServiceTierCapabilityBaseUrlGuard">,
|
|
2774
|
+
provider: Pick<OcxProviderConfig, "baseUrl">,
|
|
2775
|
+
): boolean {
|
|
2776
|
+
const guard = entry.modelServiceTierCapabilityBaseUrlGuard;
|
|
2777
|
+
return guard === undefined || guard(provider.baseUrl);
|
|
2778
|
+
}
|
|
2779
|
+
|
|
1491
2780
|
function normalizedProviderEndpoint(value: string): string {
|
|
1492
2781
|
const trimmed = value.trim();
|
|
1493
2782
|
try {
|
|
@@ -1567,12 +2856,41 @@ export function providerModelWireDefault(
|
|
|
1567
2856
|
if (!entry?.modelWireDefaults || !providerMatchesRegistryTransport(id, provider)) return undefined;
|
|
1568
2857
|
const declared = entry.modelWireDefaults[modelId.trim().toLowerCase()];
|
|
1569
2858
|
if (declared === undefined) return undefined;
|
|
1570
|
-
// A bare string applies to every inbound; the object form
|
|
1571
|
-
if (typeof declared !== "string"
|
|
2859
|
+
// A bare string applies to every inbound/auth mode; the object form may narrow either.
|
|
2860
|
+
if (typeof declared !== "string") {
|
|
2861
|
+
if (!declared.inbound.includes(inbound)) return undefined;
|
|
2862
|
+
const authMode = provider.authMode ?? entry.authKind;
|
|
2863
|
+
if (declared.authModes && !declared.authModes.includes(authMode)) return undefined;
|
|
2864
|
+
}
|
|
1572
2865
|
const wire = typeof declared === "string" ? declared : declared.wire;
|
|
1573
2866
|
return wire !== undefined && allowedWires.has(wire) ? wire : undefined;
|
|
1574
2867
|
}
|
|
1575
2868
|
|
|
2869
|
+
/** Resolve a registry-only upstream-streaming compatibility hint for Responses turns. */
|
|
2870
|
+
export function providerModelResponsesUpstreamStreaming(
|
|
2871
|
+
id: string,
|
|
2872
|
+
provider: Pick<OcxProviderConfig, "baseUrl" | "adapter"> & Partial<Pick<OcxProviderConfig, "authMode">>,
|
|
2873
|
+
modelId: string,
|
|
2874
|
+
): boolean | undefined {
|
|
2875
|
+
const entry = getProviderRegistryEntry(id);
|
|
2876
|
+
if (!entry?.modelResponsesUpstreamStreaming || !providerMatchesRegistryTransport(id, provider)) return undefined;
|
|
2877
|
+
return entry.modelResponsesUpstreamStreaming[modelId.trim().toLowerCase()];
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
/** Resolve a registry-only terminal-repair policy for native Responses streams. */
|
|
2881
|
+
export function providerModelResponsesTerminalRepair(
|
|
2882
|
+
id: string,
|
|
2883
|
+
provider: Pick<OcxProviderConfig, "baseUrl" | "adapter"> & Partial<Pick<OcxProviderConfig, "authMode">>,
|
|
2884
|
+
modelId: string,
|
|
2885
|
+
): ResponsesTerminalRepairPolicy | undefined {
|
|
2886
|
+
const entry = getProviderRegistryEntry(id);
|
|
2887
|
+
if (!entry?.modelResponsesTerminalRepair || !providerMatchesRegistryTransport(id, provider)) return undefined;
|
|
2888
|
+
const policy = entry.modelResponsesTerminalRepair[modelId.trim().toLowerCase()];
|
|
2889
|
+
const graceMs = Math.floor(policy?.graceMs ?? 0);
|
|
2890
|
+
if (!Number.isFinite(graceMs) || graceMs <= 0) return undefined;
|
|
2891
|
+
return { graceMs };
|
|
2892
|
+
}
|
|
2893
|
+
|
|
1576
2894
|
/**
|
|
1577
2895
|
* Effective Codex account mode for a provider. For canonical `openai`, a valid persisted
|
|
1578
2896
|
* `codexAccountMode` on the provider config wins and a missing/invalid value defaults to
|