@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,9 +1,11 @@
|
|
|
1
1
|
import { resolveEnvValue } from "../config";
|
|
2
2
|
import {
|
|
3
|
+
CodexPoolAuthenticationError,
|
|
3
4
|
headersForCodexAuthContext,
|
|
4
5
|
hasCallerCodexBearer,
|
|
5
6
|
isCodexAuthContextUsable,
|
|
6
7
|
resolveCodexAuthContext,
|
|
8
|
+
type CodexAccountSelectionAdmission,
|
|
7
9
|
type CodexAuthContext,
|
|
8
10
|
} from "../codex/auth-context";
|
|
9
11
|
import { recordCodexUpstreamOutcome, type CodexUpstreamOutcome } from "../codex/routing";
|
|
@@ -11,6 +13,7 @@ import { extractAccountId } from "../oauth/chatgpt";
|
|
|
11
13
|
import { ForwardAdmissionCredentialError, validateForwardAdmissionCredential } from "../server/auth-cors";
|
|
12
14
|
import type { CodexAccountMode, OcxConfig, OcxProviderConfig } from "../types";
|
|
13
15
|
import {
|
|
16
|
+
CODEX_FORWARD_BASE_URL,
|
|
14
17
|
isCanonicalOpenAiForwardProvider,
|
|
15
18
|
OPENAI_API_PROVIDER_ID,
|
|
16
19
|
OPENAI_CODEX_PROVIDER_ID,
|
|
@@ -29,6 +32,17 @@ export interface ResolvedOpenAiForwardSidecar extends OpenAiForwardSidecarCandid
|
|
|
29
32
|
recordOutcome?: (outcome: CodexUpstreamOutcome) => void;
|
|
30
33
|
}
|
|
31
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Server-resolved exact account selection for a ChatGPT sidecar call.
|
|
37
|
+
* `accountId` must come from a validated account-qualified route; request headers
|
|
38
|
+
* are never trusted as account ids. `modelId` is the sidecar's actual upstream
|
|
39
|
+
* model so cooldown admission and outcome recording use the correct quota scope.
|
|
40
|
+
*/
|
|
41
|
+
export interface ExactOpenAiSidecarAccount {
|
|
42
|
+
accountId: string;
|
|
43
|
+
modelId: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
32
46
|
export interface OpenAiImagesProviderSelection {
|
|
33
47
|
forwardCandidates: OpenAiForwardSidecarCandidate[];
|
|
34
48
|
keyed?: {
|
|
@@ -41,11 +55,24 @@ export interface OpenAiImagesProviderSelection {
|
|
|
41
55
|
|
|
42
56
|
export function listOpenAiForwardSidecarCandidates(config: OcxConfig): OpenAiForwardSidecarCandidate[] {
|
|
43
57
|
const provider = config.providers[OPENAI_CODEX_PROVIDER_ID];
|
|
44
|
-
if (!provider || provider.disabled === true
|
|
58
|
+
if (!provider || provider.disabled === true) return [];
|
|
59
|
+
// The built-in registry defaults an omitted authMode to forward. Normalize only that
|
|
60
|
+
// missing field before the strict adapter/destination check; explicit key mode and
|
|
61
|
+
// noncanonical destinations remain ineligible for ChatGPT credential injection.
|
|
62
|
+
const canonicalProvider = provider.authMode === undefined
|
|
63
|
+
? { ...provider, authMode: "forward" as const }
|
|
64
|
+
: provider;
|
|
65
|
+
if (!isCanonicalOpenAiForwardProvider(canonicalProvider)) return [];
|
|
66
|
+
// The predicate accepts harmless trailing-slash variants. Pin the provider returned
|
|
67
|
+
// to credential-bearing sidecars so every consumer builds one exact ChatGPT path
|
|
68
|
+
// instead of independently concatenating the operator's equivalent spelling.
|
|
69
|
+
const pinnedProvider = canonicalProvider.baseUrl === CODEX_FORWARD_BASE_URL
|
|
70
|
+
? canonicalProvider
|
|
71
|
+
: { ...canonicalProvider, baseUrl: CODEX_FORWARD_BASE_URL };
|
|
45
72
|
return [{
|
|
46
73
|
providerName: OPENAI_CODEX_PROVIDER_ID,
|
|
47
|
-
provider,
|
|
48
|
-
accountMode: providerCodexAccountMode(OPENAI_CODEX_PROVIDER_ID,
|
|
74
|
+
provider: pinnedProvider,
|
|
75
|
+
accountMode: providerCodexAccountMode(OPENAI_CODEX_PROVIDER_ID, pinnedProvider) ?? "pool",
|
|
49
76
|
}];
|
|
50
77
|
}
|
|
51
78
|
|
|
@@ -70,7 +97,12 @@ export async function resolveFirstUsableOpenAiSidecar(
|
|
|
70
97
|
candidates: readonly OpenAiForwardSidecarCandidate[],
|
|
71
98
|
incomingHeaders: Headers,
|
|
72
99
|
config: OcxConfig,
|
|
100
|
+
options: {
|
|
101
|
+
exactAccount?: ExactOpenAiSidecarAccount;
|
|
102
|
+
beginCodexAccountSelection?: () => CodexAccountSelectionAdmission | undefined;
|
|
103
|
+
} = {},
|
|
73
104
|
): Promise<ResolvedOpenAiForwardSidecar | undefined> {
|
|
105
|
+
const { exactAccount } = options;
|
|
74
106
|
let callerBearerMayBeForwarded = true;
|
|
75
107
|
try {
|
|
76
108
|
validateForwardAdmissionCredential(incomingHeaders, config);
|
|
@@ -79,6 +111,39 @@ export async function resolveFirstUsableOpenAiSidecar(
|
|
|
79
111
|
callerBearerMayBeForwarded = false;
|
|
80
112
|
}
|
|
81
113
|
for (const candidate of candidates) {
|
|
114
|
+
if (exactAccount) {
|
|
115
|
+
// An account-qualified model is an explicit user choice. Resolve the stored
|
|
116
|
+
// credential directly even when the provider is globally Direct, and never
|
|
117
|
+
// consult Pool active state, affinity, probes, or alternates.
|
|
118
|
+
const authContext = await resolveCodexAuthContext(incomingHeaders, config, "pool", {
|
|
119
|
+
accountId: exactAccount.accountId,
|
|
120
|
+
modelId: exactAccount.modelId,
|
|
121
|
+
beginCodexAccountSelection: options.beginCodexAccountSelection,
|
|
122
|
+
});
|
|
123
|
+
if ((authContext.kind !== "pool" && authContext.kind !== "main-pool")
|
|
124
|
+
|| !isCodexAuthContextUsable(authContext, config)) {
|
|
125
|
+
// Exact selection is fail-closed. A generation/runtime-state race must not fall through
|
|
126
|
+
// to the caller-bearer error or let a later candidate select another account.
|
|
127
|
+
throw new CodexPoolAuthenticationError("Selected Codex account is unavailable");
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
...candidate,
|
|
131
|
+
authContext,
|
|
132
|
+
headers: headersForCodexAuthContext(incomingHeaders, authContext),
|
|
133
|
+
recordOutcome: (outcome: CodexUpstreamOutcome) => recordCodexUpstreamOutcome(
|
|
134
|
+
config,
|
|
135
|
+
authContext.accountId,
|
|
136
|
+
outcome,
|
|
137
|
+
{
|
|
138
|
+
modelId: exactAccount.modelId,
|
|
139
|
+
fixedAccount: true,
|
|
140
|
+
probeLeaseId: authContext.probeLeaseId,
|
|
141
|
+
probeQuotaScope: authContext.probeQuotaScope,
|
|
142
|
+
writerGeneration: authContext.writerGeneration,
|
|
143
|
+
},
|
|
144
|
+
),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
82
147
|
if (candidate.accountMode === "direct") {
|
|
83
148
|
if (!callerBearerMayBeForwarded || !hasCallerCodexBearer(incomingHeaders)) continue;
|
|
84
149
|
const headers = directSidecarHeaders(incomingHeaders);
|
|
@@ -89,7 +154,9 @@ export async function resolveFirstUsableOpenAiSidecar(
|
|
|
89
154
|
headers,
|
|
90
155
|
};
|
|
91
156
|
}
|
|
92
|
-
const authContext = await resolveCodexAuthContext(incomingHeaders, config, candidate.accountMode
|
|
157
|
+
const authContext = await resolveCodexAuthContext(incomingHeaders, config, candidate.accountMode, {
|
|
158
|
+
beginCodexAccountSelection: options.beginCodexAccountSelection,
|
|
159
|
+
});
|
|
93
160
|
if (!isCodexAuthContextUsable(authContext, config)) continue;
|
|
94
161
|
return {
|
|
95
162
|
...candidate,
|
|
@@ -102,6 +169,7 @@ export async function resolveFirstUsableOpenAiSidecar(
|
|
|
102
169
|
authContext.accountId,
|
|
103
170
|
outcome,
|
|
104
171
|
{
|
|
172
|
+
threadId: authContext.affinityKey,
|
|
105
173
|
probeLeaseId: authContext.probeLeaseId,
|
|
106
174
|
writerGeneration: authContext.writerGeneration,
|
|
107
175
|
},
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
backupConfigBeforeOpenAiTierMigration,
|
|
3
|
+
OpenAiTierBackupCollisionError,
|
|
4
|
+
OpenAiTierRollbackPreserveError,
|
|
5
|
+
preserveOpenAiTierRollbackSnapshot,
|
|
6
|
+
saveConfig,
|
|
7
|
+
} from "../config";
|
|
2
8
|
import type { OcxConfig } from "../types";
|
|
3
9
|
import { projectOpenAiTierMigration } from "./openai-tiers";
|
|
4
10
|
|
|
@@ -6,6 +12,23 @@ export interface OpenAiTierStartupDeps {
|
|
|
6
12
|
project: typeof projectOpenAiTierMigration;
|
|
7
13
|
backup: () => void;
|
|
8
14
|
save: (config: OcxConfig) => void;
|
|
15
|
+
preserveRollback?: (error: OpenAiTierBackupCollisionError) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function defaultPreserveRollback(error: OpenAiTierBackupCollisionError): void {
|
|
19
|
+
if (!error.configPath) throw error;
|
|
20
|
+
try {
|
|
21
|
+
const preserved = preserveOpenAiTierRollbackSnapshot(error.configPath);
|
|
22
|
+
console.warn(`[openai-provider-migration] Preserved rollback snapshot at ${preserved}`);
|
|
23
|
+
} catch (cause) {
|
|
24
|
+
if (
|
|
25
|
+
cause instanceof OpenAiTierRollbackPreserveError
|
|
26
|
+
&& (cause.code === "missing" || cause.code === "not-rollback")
|
|
27
|
+
) {
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
throw cause;
|
|
31
|
+
}
|
|
9
32
|
}
|
|
10
33
|
|
|
11
34
|
const DEFAULT_DEPS: OpenAiTierStartupDeps = {
|
|
@@ -20,7 +43,13 @@ export function runOpenAiTierStartupMigration(
|
|
|
20
43
|
): OcxConfig {
|
|
21
44
|
const projection = deps.project(config);
|
|
22
45
|
if (!projection.changed) return projection.config;
|
|
23
|
-
|
|
46
|
+
try {
|
|
47
|
+
deps.backup();
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (!(error instanceof OpenAiTierBackupCollisionError)) throw error;
|
|
50
|
+
(deps.preserveRollback ?? defaultPreserveRollback)(error);
|
|
51
|
+
deps.backup();
|
|
52
|
+
}
|
|
24
53
|
deps.save(projection.config);
|
|
25
54
|
for (const warning of projection.warnings) console.warn(`[openai-provider-migration] ${warning}`);
|
|
26
55
|
return projection.config;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import type { CodexAccountMode, OcxConfig, OcxProviderConfig } from "../types";
|
|
1
|
+
import type { CodexAccountMode, OcxConfig, OcxProviderConfig, ProviderCostOverlay } from "../types";
|
|
2
2
|
import { OPENAI_PROVIDER_TIER_VERSION } from "../types";
|
|
3
|
+
import { openaiResponsesUrl } from "../adapters/openai-responses-url";
|
|
4
|
+
import { MAX_COST4_RATE } from "../usage/expected-prices";
|
|
3
5
|
|
|
4
6
|
export const OPENAI_CODEX_PROVIDER_ID = "openai";
|
|
5
7
|
export const LEGACY_OPENAI_MULTI_PROVIDER_ID = "openai-multi";
|
|
@@ -35,7 +37,35 @@ export function isCanonicalOpenAiForwardProvider(provider: OcxProviderConfig): b
|
|
|
35
37
|
&& normalizedBaseUrl(provider.baseUrl) === CODEX_FORWARD_BASE_URL;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
const
|
|
40
|
+
const OPENAI_API_ORIGIN = "https://api.openai.com";
|
|
41
|
+
const OPENAI_API_BASE_URL = `${OPENAI_API_ORIGIN}/v1`;
|
|
42
|
+
const OPENAI_API_RESPONSES_URL = `${OPENAI_API_BASE_URL}/responses`;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The Responses endpoint the adapter would actually POST key-auth traffic to, normalized.
|
|
46
|
+
*
|
|
47
|
+
* Mirrors the adapter's own construction (`src/adapters/openai-responses.ts`): a configured
|
|
48
|
+
* `responsesPath` is appended to the base verbatim, and only the default branch runs the
|
|
49
|
+
* `/v1/responses` suffix normalization. Classifying on the base URL alone would call
|
|
50
|
+
* `baseUrl: "https://api.openai.com"` with `responsesPath: "/other"` official even though that
|
|
51
|
+
* request never reaches the official Responses endpoint.
|
|
52
|
+
*/
|
|
53
|
+
function resolvedResponsesEndpoint(provider: OcxProviderConfig): string | undefined {
|
|
54
|
+
try {
|
|
55
|
+
const raw = provider.responsesPath === undefined
|
|
56
|
+
? openaiResponsesUrl(provider.baseUrl)
|
|
57
|
+
: `${provider.baseUrl.replace(/\/$/, "")}${provider.responsesPath}`;
|
|
58
|
+
return normalizedBaseUrl(raw);
|
|
59
|
+
} catch {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isOfficialOpenAiResponsesDestination(provider: OcxProviderConfig): boolean {
|
|
65
|
+
// Exact normalized URL keeps lookalike/suffix hosts out of this set: `api.openai.com.evil.test`
|
|
66
|
+
// resolves to its own origin, never to the official one.
|
|
67
|
+
return resolvedResponsesEndpoint(provider) === OPENAI_API_RESPONSES_URL;
|
|
68
|
+
}
|
|
39
69
|
|
|
40
70
|
/**
|
|
41
71
|
* Whether this provider can serve `POST /responses/compact`. The canonical ChatGPT
|
|
@@ -53,6 +83,36 @@ export function supportsNativeResponsesCompactEndpoint(
|
|
|
53
83
|
&& normalizedBaseUrl(provider.baseUrl) === OPENAI_API_BASE_URL;
|
|
54
84
|
}
|
|
55
85
|
|
|
86
|
+
/**
|
|
87
|
+
* Whether this destination is an OpenAI-operated Responses backend — the canonical ChatGPT Codex
|
|
88
|
+
* surface or the official OpenAI API.
|
|
89
|
+
*
|
|
90
|
+
* Deliberately not keyed on `authMode === "forward"`: a noncanonical forward provider does not
|
|
91
|
+
* receive the caller's credentials (see the forward-header gate in the Responses adapter), so
|
|
92
|
+
* forward auth says nothing about which backend is on the other end.
|
|
93
|
+
*/
|
|
94
|
+
export function isOpenAiOperatedResponsesDestination(provider: OcxProviderConfig): boolean {
|
|
95
|
+
if (isCanonicalOpenAiForwardProvider(provider)) return true;
|
|
96
|
+
return provider.adapter === "openai-responses"
|
|
97
|
+
&& isOfficialOpenAiResponsesDestination(provider);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Whether this destination can decode a native (non-`ocx1:`) compaction blob.
|
|
102
|
+
*
|
|
103
|
+
* Only the backend that minted a blob can decode it. `authMode: "forward"` alone is not a signal:
|
|
104
|
+
* the adapter forwards caller credentials only to the canonical ChatGPT Codex surface, while a
|
|
105
|
+
* noncanonical forward provider receives no caller credentials and may point at any backend.
|
|
106
|
+
*
|
|
107
|
+
* Relay only to an OpenAI-operated destination or a destination whose operator explicitly opts in.
|
|
108
|
+
* Keyed by destination rather than provider id: a blob's issuer is the URL that produced it, not the
|
|
109
|
+
* local config key a replay travels under.
|
|
110
|
+
*/
|
|
111
|
+
export function destinationDecodesNativeCompactionBlob(provider: OcxProviderConfig): boolean {
|
|
112
|
+
return isOpenAiOperatedResponsesDestination(provider)
|
|
113
|
+
|| provider.decodesNativeCompactionBlobs === true;
|
|
114
|
+
}
|
|
115
|
+
|
|
56
116
|
export interface OpenAiTierMigrationProjection {
|
|
57
117
|
config: OcxConfig;
|
|
58
118
|
changed: boolean;
|
|
@@ -69,11 +129,17 @@ export class OpenAiTierMigrationCollisionError extends Error {
|
|
|
69
129
|
}
|
|
70
130
|
}
|
|
71
131
|
|
|
72
|
-
function managedLegacyMultiOverlay(
|
|
73
|
-
|
|
132
|
+
function managedLegacyMultiOverlay(
|
|
133
|
+
provider: OcxProviderConfig,
|
|
134
|
+
): Pick<OcxProviderConfig, "disabled" | "selectedModels" | "modelCosts"> | null {
|
|
135
|
+
const allowed = new Set(["adapter", "authMode", "baseUrl", "disabled", "selectedModels", "modelCosts"]);
|
|
74
136
|
if (!Object.keys(provider).every(key => allowed.has(key))) return null;
|
|
75
137
|
if (!isCanonicalOpenAiForwardProvider(provider)) return null;
|
|
76
138
|
if (provider.disabled !== undefined && typeof provider.disabled !== "boolean") return null;
|
|
139
|
+
// Keep the migration self-contained: a malformed overlay is a collision, not
|
|
140
|
+
// something to carry into the canonical row (importing config.ts here would
|
|
141
|
+
// create an import cycle — config.ts already imports this module).
|
|
142
|
+
if (provider.modelCosts !== undefined && !validLegacyOverlayCosts(provider.modelCosts)) return null;
|
|
77
143
|
if (provider.selectedModels !== undefined && (
|
|
78
144
|
!Array.isArray(provider.selectedModels)
|
|
79
145
|
|| provider.selectedModels.some(model => typeof model !== "string")
|
|
@@ -81,9 +147,26 @@ function managedLegacyMultiOverlay(provider: OcxProviderConfig): Pick<OcxProvide
|
|
|
81
147
|
return {
|
|
82
148
|
...(provider.disabled !== undefined ? { disabled: provider.disabled } : {}),
|
|
83
149
|
...(provider.selectedModels !== undefined ? { selectedModels: [...provider.selectedModels] } : {}),
|
|
150
|
+
...(provider.modelCosts !== undefined ? { modelCosts: provider.modelCosts } : {}),
|
|
84
151
|
};
|
|
85
152
|
}
|
|
86
153
|
|
|
154
|
+
/** Shape check for a legacy overlay: a plain record of complete non-negative finite Cost4 rows. */
|
|
155
|
+
function validLegacyOverlayCosts(value: unknown): boolean {
|
|
156
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
157
|
+
const fields = ["input", "output", "cacheRead", "cacheWrite"] as const;
|
|
158
|
+
return Object.values(value as Record<string, unknown>).every(entry => {
|
|
159
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return false;
|
|
160
|
+
const rates = entry as Record<string, unknown>;
|
|
161
|
+
return Object.keys(rates).length === fields.length
|
|
162
|
+
&& fields.every(key => Object.hasOwn(rates, key)
|
|
163
|
+
&& typeof rates[key] === "number"
|
|
164
|
+
&& Number.isFinite(rates[key])
|
|
165
|
+
&& (rates[key] as number) >= 0
|
|
166
|
+
&& (rates[key] as number) <= MAX_COST4_RATE);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
87
170
|
function rewriteLegacyOpenAiSelectedId(value: string): string {
|
|
88
171
|
return value.startsWith(LEGACY_OPENAI_MULTI_PREFIX)
|
|
89
172
|
? value.slice(LEGACY_OPENAI_MULTI_PREFIX.length)
|
|
@@ -95,6 +178,28 @@ function rewriteLegacyOpenAiModelList(values: string[] | undefined): string[] |
|
|
|
95
178
|
return [...new Set(values.map(rewriteLegacyOpenAiSelectedId))];
|
|
96
179
|
}
|
|
97
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Rewrite legacy `openai-multi/<model>` keys in a modelCosts overlay so the
|
|
183
|
+
* prices still match after the migration resolves logs as provider `openai`
|
|
184
|
+
* with the bare model id. Keys without the legacy prefix pass through.
|
|
185
|
+
*/
|
|
186
|
+
function rewriteLegacyOpenAiCostKeys(costs: Record<string, ProviderCostOverlay> | undefined): Record<string, ProviderCostOverlay> {
|
|
187
|
+
// Null-prototype map so prototype-named model ids (e.g. "__proto__") are
|
|
188
|
+
// stored as own properties instead of invoking the inherited setter.
|
|
189
|
+
const rewritten = Object.create(null) as Record<string, ProviderCostOverlay>;
|
|
190
|
+
if (costs) {
|
|
191
|
+
for (const [key, value] of Object.entries(costs)) {
|
|
192
|
+
const canonicalKey = rewriteLegacyOpenAiSelectedId(key);
|
|
193
|
+
// A bare <model> key always wins over its openai-multi/<model> equivalent
|
|
194
|
+
// inside the same row, regardless of JSON property order.
|
|
195
|
+
if (key === canonicalKey || !Object.hasOwn(rewritten, canonicalKey)) {
|
|
196
|
+
rewritten[canonicalKey] = value;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return rewritten;
|
|
201
|
+
}
|
|
202
|
+
|
|
98
203
|
function mergeLegacyOpenAiProviderRows(
|
|
99
204
|
openai: OcxProviderConfig | undefined,
|
|
100
205
|
legacyMulti: OcxProviderConfig | undefined,
|
|
@@ -104,12 +209,22 @@ function mergeLegacyOpenAiProviderRows(
|
|
|
104
209
|
...(openai?.selectedModels ?? []),
|
|
105
210
|
...(legacyMulti?.selectedModels ?? []),
|
|
106
211
|
]);
|
|
212
|
+
// Both rows can carry disjoint overlays; merge them (canonical openai wins on
|
|
213
|
+
// key conflicts) so legacy Multi prices are not silently dropped. Keys are
|
|
214
|
+
// rewritten first so `openai-multi/<model>` entries still resolve after the
|
|
215
|
+
// provider is canonicalized to `openai`.
|
|
216
|
+
const modelCosts = {
|
|
217
|
+
...rewriteLegacyOpenAiCostKeys(legacyMulti?.modelCosts),
|
|
218
|
+
...rewriteLegacyOpenAiCostKeys(openai?.modelCosts),
|
|
219
|
+
};
|
|
220
|
+
const hasModelCosts = Object.keys(modelCosts).length > 0;
|
|
107
221
|
const formerRows = [openai, legacyMulti].filter((row): row is OcxProviderConfig => row !== undefined);
|
|
108
222
|
const disabled = formerRows.length > 0 && formerRows.every(row => row.disabled === true);
|
|
109
223
|
return {
|
|
110
224
|
...canonicalCodexForwardProvider(mode),
|
|
111
225
|
...(disabled ? { disabled: true } : {}),
|
|
112
226
|
...(selectedModels && selectedModels.length > 0 ? { selectedModels } : {}),
|
|
227
|
+
...(hasModelCosts ? { modelCosts } : {}),
|
|
113
228
|
};
|
|
114
229
|
}
|
|
115
230
|
|
|
@@ -62,6 +62,7 @@ export function applyOpenAiVirtualModel(
|
|
|
62
62
|
logCtx.resolvedModel = resolution.wireModelId;
|
|
63
63
|
route.modelId = resolution.wireModelId;
|
|
64
64
|
parsed.modelId = resolution.wireModelId;
|
|
65
|
+
parsed._openAiVirtualSelectedModelId = resolution.selectedModelId;
|
|
65
66
|
|
|
66
67
|
if (parsed._rawBody && typeof parsed._rawBody === "object" && !Array.isArray(parsed._rawBody)) {
|
|
67
68
|
const raw = parsed._rawBody as Record<string, unknown>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode Zen short-window rate-limit guidance (#1145 / OCX-56).
|
|
3
|
+
*
|
|
4
|
+
* OpenCode's keyed and keyless Zen chat endpoints share `https://opencode.ai/zen/v1`.
|
|
5
|
+
* Free-model traffic can hit a short-window burst ceiling around 15–20 RPM
|
|
6
|
+
* (community-measured). Zen often answers with opaque `429 Rate limit exceeded`
|
|
7
|
+
* bodies and may omit `Retry-After` / `X-RateLimit-*`; when those headers are
|
|
8
|
+
* present they still take precedence. Distinct from the keyless desktop
|
|
9
|
+
* ~200 requests / 5h quota documented on `opencode-free`.
|
|
10
|
+
*/
|
|
11
|
+
import { validateClientRetryAfterHeader } from "../lib/retry-after";
|
|
12
|
+
import { registryEntryForProviderDestination } from "./registry";
|
|
13
|
+
|
|
14
|
+
const OPENCODE_ZEN_PROVIDER_IDS = new Set(["opencode-zen", "opencode-free"]);
|
|
15
|
+
|
|
16
|
+
/** Observed free-model burst ceiling on Zen (not an official OpenCode figure). */
|
|
17
|
+
export const OPENCODE_ZEN_OBSERVED_RPM_HINT = "roughly 15-20 requests per minute";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Synthetic client backoff when Zen omits Retry-After after a rate-limit 429.
|
|
21
|
+
* Longer than the generic 2s default so Codex-shaped clients do not immediately
|
|
22
|
+
* re-hammer a ~15-20 RPM window.
|
|
23
|
+
*/
|
|
24
|
+
export const OPENCODE_ZEN_SYNTHETIC_RETRY_AFTER_SEC = 15;
|
|
25
|
+
|
|
26
|
+
const ENRICHMENT_MARKER = "15-20 requests per minute";
|
|
27
|
+
|
|
28
|
+
export function isOpenCodeZenRateLimitProvider(opts: {
|
|
29
|
+
providerName?: string;
|
|
30
|
+
baseUrl?: string;
|
|
31
|
+
adapter?: string;
|
|
32
|
+
}): boolean {
|
|
33
|
+
const name = opts.providerName?.trim();
|
|
34
|
+
if (name && OPENCODE_ZEN_PROVIDER_IDS.has(name)) return true;
|
|
35
|
+
const baseUrl = opts.baseUrl?.trim();
|
|
36
|
+
if (!baseUrl) return false;
|
|
37
|
+
const entry = registryEntryForProviderDestination({
|
|
38
|
+
baseUrl,
|
|
39
|
+
adapter: opts.adapter?.trim() || "openai-chat",
|
|
40
|
+
authMode: "key",
|
|
41
|
+
});
|
|
42
|
+
return entry !== undefined && OPENCODE_ZEN_PROVIDER_IDS.has(entry.id);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Same-key `retryOn429` only applies on key-authenticated HTTP paths — not
|
|
47
|
+
* keyless `opencode-free` traffic and not custom `runTurn` transports.
|
|
48
|
+
*/
|
|
49
|
+
export function supportsOpenCodeZenRetryOn429Guidance(opts: {
|
|
50
|
+
authMode?: string;
|
|
51
|
+
hasApiKey?: boolean;
|
|
52
|
+
supportsHttpSameKeyRetry?: boolean;
|
|
53
|
+
}): boolean {
|
|
54
|
+
if (opts.supportsHttpSameKeyRetry === false) return false;
|
|
55
|
+
if (opts.authMode !== undefined && opts.authMode !== "key") return false;
|
|
56
|
+
return opts.hasApiKey === true;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Append actionable Zen rate-limit context to a generic upstream 429 message and
|
|
61
|
+
* embed a parseable `try again in Ns` hint so {@link resolveClientRetryAfter}
|
|
62
|
+
* surfaces a useful Retry-After when the gateway sent none.
|
|
63
|
+
*/
|
|
64
|
+
export function enrichOpenCodeZenRateLimitMessage(
|
|
65
|
+
message: string,
|
|
66
|
+
opts: {
|
|
67
|
+
status: number;
|
|
68
|
+
providerName?: string;
|
|
69
|
+
baseUrl?: string;
|
|
70
|
+
adapter?: string;
|
|
71
|
+
authMode?: string;
|
|
72
|
+
hasApiKey?: boolean;
|
|
73
|
+
/** Upstream Retry-After header; when valid, skip the synthetic 15s text hint. */
|
|
74
|
+
upstreamRetryAfter?: string | null;
|
|
75
|
+
/** False for custom `runTurn` transports outside the HTTP retry loop. */
|
|
76
|
+
supportsHttpSameKeyRetry?: boolean;
|
|
77
|
+
now?: number;
|
|
78
|
+
},
|
|
79
|
+
): string {
|
|
80
|
+
if (opts.status !== 429) return message;
|
|
81
|
+
if (!isOpenCodeZenRateLimitProvider(opts)) return message;
|
|
82
|
+
if (!/rate\s*limit/i.test(message)) return message;
|
|
83
|
+
if (message.includes(ENRICHMENT_MARKER)) return message;
|
|
84
|
+
|
|
85
|
+
const upstreamRetry = validateClientRetryAfterHeader(
|
|
86
|
+
opts.upstreamRetryAfter,
|
|
87
|
+
opts.now ?? Date.now(),
|
|
88
|
+
);
|
|
89
|
+
const retryHint = upstreamRetry || /try again in \d/i.test(message)
|
|
90
|
+
? ""
|
|
91
|
+
: ` Try again in ${OPENCODE_ZEN_SYNTHETIC_RETRY_AFTER_SEC}s.`;
|
|
92
|
+
const paceHint = supportsOpenCodeZenRetryOn429Guidance(opts)
|
|
93
|
+
? " Slow the request pace, or set providers.opencode-zen.retryOn429 for same-key backoff."
|
|
94
|
+
: " Slow the request pace.";
|
|
95
|
+
return (
|
|
96
|
+
`${message}`
|
|
97
|
+
+ ` OpenCode Zen free-model traffic is often limited to ${OPENCODE_ZEN_OBSERVED_RPM_HINT}`
|
|
98
|
+
+ ` (observed; OpenCode does not publish this RPM, and may omit rate-limit headers).`
|
|
99
|
+
+ `${retryHint}`
|
|
100
|
+
+ paceHint
|
|
101
|
+
);
|
|
102
|
+
}
|
|
@@ -148,3 +148,32 @@ export function rewriteProviderReferences(config: OcxConfig, from: string, to: s
|
|
|
148
148
|
|
|
149
149
|
return { changed, collisions };
|
|
150
150
|
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Drop the custom-model rows that belonged to a provider being removed.
|
|
154
|
+
*
|
|
155
|
+
* The sibling of the rename pass above. `rewriteProviderReferences` already
|
|
156
|
+
* carries `customModels[].provider` across a rename, so the array tracks the
|
|
157
|
+
* provider lifecycle — but removal used to delete only `config.providers[name]`
|
|
158
|
+
* and leave the rows behind. Those orphans still reach `/api/models` and the
|
|
159
|
+
* generated Codex catalog, which key on the row rather than on provider
|
|
160
|
+
* existence, so they surface as models that resolve to nothing (#1273).
|
|
161
|
+
*
|
|
162
|
+
* Only the rows are touched: the `customModelCatalogMigration` marker records
|
|
163
|
+
* one-time ownership of pre-marker rows and must survive removal unchanged, or
|
|
164
|
+
* an older binary's view of that ownership silently changes.
|
|
165
|
+
*
|
|
166
|
+
* Returns the number of rows dropped so callers can report it.
|
|
167
|
+
*/
|
|
168
|
+
export function dropProviderCustomModels(config: OcxConfig, provider: string): number {
|
|
169
|
+
const existing = config.customModels;
|
|
170
|
+
if (!Array.isArray(existing) || existing.length === 0) return 0;
|
|
171
|
+
const kept = existing.filter(model => model.provider !== provider);
|
|
172
|
+
if (kept.length === existing.length) return 0;
|
|
173
|
+
// Match the add/remove routes: an emptied list is dropped rather than left as
|
|
174
|
+
// `[]`, so the `customModels` field is absent either way. Only that field —
|
|
175
|
+
// the `customModelCatalogMigration` marker is deliberately left in place.
|
|
176
|
+
if (kept.length > 0) config.customModels = kept;
|
|
177
|
+
else delete config.customModels;
|
|
178
|
+
return existing.length - kept.length;
|
|
179
|
+
}
|