@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
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime registry for user-configured provider cost overlays
|
|
3
|
+
* (`providers.<name>.modelCosts` in config.json — per-model prices in ocx's
|
|
4
|
+
* flat `modelXxx` convention, mirroring opencode's per-model pricing).
|
|
5
|
+
*
|
|
6
|
+
* The usage cost estimator stays pure: it receives overlays as parameters and
|
|
7
|
+
* defaults to this registry, which is refreshed at the config chokepoints
|
|
8
|
+
* (loadConfig and every persist path). A refresh that actually changes the
|
|
9
|
+
* rows replaces the active array with a NEW identity and bumps a version
|
|
10
|
+
* counter, so the estimator's memo and the /api/usage summary cache skip stale
|
|
11
|
+
* rows without cross-module invalidation. Refreshes with byte-identical rows
|
|
12
|
+
* are no-ops: config is reloaded at many chokepoints and an unchanged reload
|
|
13
|
+
* must not churn the version (see refreshUserCostOverlays). The configured
|
|
14
|
+
* provider-name set is part of the change identity: adding or removing a
|
|
15
|
+
* provider changes which names may collapse to a label base in the resolver,
|
|
16
|
+
* so it bumps the version even when no overlay row changed.
|
|
17
|
+
*
|
|
18
|
+
* Display-time estimation only — these rows never affect billing.
|
|
19
|
+
*/
|
|
20
|
+
import type { OcxConfig, OcxProviderConfig, ProviderCostOverlay } from "../types";
|
|
21
|
+
import { MAX_COST4_RATE, type ExpectedPriceOverlay } from "./expected-prices";
|
|
22
|
+
import { redactSecretString } from "../lib/redact";
|
|
23
|
+
|
|
24
|
+
const EMPTY: readonly ExpectedPriceOverlay[] = [];
|
|
25
|
+
|
|
26
|
+
let active: readonly ExpectedPriceOverlay[] = EMPTY;
|
|
27
|
+
let activeSignature = "";
|
|
28
|
+
let activeConfigured = new Set<string>();
|
|
29
|
+
let version = 0;
|
|
30
|
+
let preservedDiskOnlyProviders: Record<string, OcxProviderConfig> | null = null;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Preservation owner metadata rides through the shallow config projections in
|
|
34
|
+
* config.ts via an enumerable SYMBOL key. JSON.stringify ignores symbol keys,
|
|
35
|
+
* so the tag is process-local only and can never reach config.json or a DTO.
|
|
36
|
+
*/
|
|
37
|
+
const PRESERVATION_OWNER_STATE = Symbol("opencodex.user-cost-overlay-preservation-owner");
|
|
38
|
+
const PERSISTED_PROVIDER_DELETIONS = Symbol("opencodex.persisted-provider-deletions");
|
|
39
|
+
|
|
40
|
+
type PreservationOwnerState = {
|
|
41
|
+
refs: number;
|
|
42
|
+
config: OcxConfig;
|
|
43
|
+
ownedProviders: Set<string>;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
type PreservationTaggedConfig = OcxConfig & {
|
|
47
|
+
[PRESERVATION_OWNER_STATE]?: PreservationOwnerState;
|
|
48
|
+
[PERSISTED_PROVIDER_DELETIONS]?: readonly string[];
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const preservationOwnerStates = new Set<PreservationOwnerState>();
|
|
52
|
+
|
|
53
|
+
function providerNames(config: OcxConfig): Set<string> {
|
|
54
|
+
return new Set(Object.keys(config.providers ?? {}));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Register one active live-config owner. Multiple server leases may share one config object. */
|
|
58
|
+
export function registerPreservedProviderOwner(config: OcxConfig): void {
|
|
59
|
+
const tagged = config as PreservationTaggedConfig;
|
|
60
|
+
const existing = tagged[PRESERVATION_OWNER_STATE];
|
|
61
|
+
if (existing && preservationOwnerStates.has(existing)) {
|
|
62
|
+
existing.refs += 1;
|
|
63
|
+
existing.ownedProviders = providerNames(config);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const state: PreservationOwnerState = {
|
|
67
|
+
refs: 1,
|
|
68
|
+
config,
|
|
69
|
+
ownedProviders: providerNames(config),
|
|
70
|
+
};
|
|
71
|
+
// Enumerable is deliberate: projectCustomModelCatalogMigration and the live
|
|
72
|
+
// binding guard use object spread, which must carry this process-local tag to
|
|
73
|
+
// the serialization view. Symbol keys are still omitted by JSON.stringify.
|
|
74
|
+
Object.defineProperty(tagged, PRESERVATION_OWNER_STATE, {
|
|
75
|
+
value: state,
|
|
76
|
+
enumerable: true,
|
|
77
|
+
configurable: true,
|
|
78
|
+
});
|
|
79
|
+
preservationOwnerStates.add(state);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Refresh a registered owner's provider snapshot from a successful disk read.
|
|
84
|
+
*
|
|
85
|
+
* A provider still present on disk remains owned even if the live object
|
|
86
|
+
* temporarily omits it: management DELETE has an async-import gap between
|
|
87
|
+
* mutating the live config and committing the write, and a reconciler tick in
|
|
88
|
+
* that gap must not erase the deletion authority. Conversely, providers that
|
|
89
|
+
* disappeared from disk are no longer considered owned, and newly present
|
|
90
|
+
* providers are adopted only when this live config actually has the row.
|
|
91
|
+
*/
|
|
92
|
+
export function refreshPreservedProviderOwner(config: OcxConfig, disk: OcxConfig): void {
|
|
93
|
+
const state = (config as PreservationTaggedConfig)[PRESERVATION_OWNER_STATE];
|
|
94
|
+
if (!state || !preservationOwnerStates.has(state)) return;
|
|
95
|
+
const diskNames = providerNames(disk);
|
|
96
|
+
for (const name of [...state.ownedProviders]) {
|
|
97
|
+
if (!diskNames.has(name)) state.ownedProviders.delete(name);
|
|
98
|
+
}
|
|
99
|
+
for (const name of Object.keys(config.providers ?? {})) {
|
|
100
|
+
if (diskNames.has(name)) state.ownedProviders.add(name);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Release one active live-config owner lease. */
|
|
105
|
+
export function unregisterPreservedProviderOwner(config: OcxConfig): void {
|
|
106
|
+
const tagged = config as PreservationTaggedConfig;
|
|
107
|
+
const state = tagged[PRESERVATION_OWNER_STATE];
|
|
108
|
+
if (!state || !preservationOwnerStates.has(state)) return;
|
|
109
|
+
state.refs -= 1;
|
|
110
|
+
if (state.refs > 0) return;
|
|
111
|
+
preservationOwnerStates.delete(state);
|
|
112
|
+
if (tagged[PRESERVATION_OWNER_STATE] === state) {
|
|
113
|
+
delete tagged[PRESERVATION_OWNER_STATE];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Remember provider rows that exist on disk but are intentionally absent from
|
|
119
|
+
* the live routing config (added by an external editor after the proxy booted).
|
|
120
|
+
* They are merged back at the config serialization boundary so an unrelated
|
|
121
|
+
* in-process save cannot erase the external provider and its overlay.
|
|
122
|
+
*/
|
|
123
|
+
export function setPreservedDiskOnlyProviders(
|
|
124
|
+
providers: Record<string, OcxProviderConfig> | null,
|
|
125
|
+
): void {
|
|
126
|
+
preservedDiskOnlyProviders = providers;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Commit an explicit provider deletion only after the persisted serialization
|
|
131
|
+
* view has been accepted by the config write path. This clears the stale
|
|
132
|
+
* preservation row and removes the provider from every active live projection,
|
|
133
|
+
* so a second owner cannot resurrect it on a later unrelated save.
|
|
134
|
+
*/
|
|
135
|
+
function commitPersistedProviderDeletions(config: OcxConfig): void {
|
|
136
|
+
const tagged = config as PreservationTaggedConfig;
|
|
137
|
+
const deletions = tagged[PERSISTED_PROVIDER_DELETIONS];
|
|
138
|
+
if (!deletions || deletions.length === 0) return;
|
|
139
|
+
|
|
140
|
+
const deleted = new Set(deletions);
|
|
141
|
+
if (preservedDiskOnlyProviders) {
|
|
142
|
+
const next = { ...preservedDiskOnlyProviders };
|
|
143
|
+
for (const name of deleted) delete next[name];
|
|
144
|
+
preservedDiskOnlyProviders = Object.keys(next).length > 0 ? next : null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
for (const state of preservationOwnerStates) {
|
|
148
|
+
for (const name of deleted) {
|
|
149
|
+
state.ownedProviders.delete(name);
|
|
150
|
+
if (state.config.providers) delete state.config.providers[name];
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
delete tagged[PERSISTED_PROVIDER_DELETIONS];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* A serialization view of `config` that keeps externally added providers on
|
|
158
|
+
* disk without adding them to live routing state. Live providers win when a
|
|
159
|
+
* name exists in both maps.
|
|
160
|
+
*
|
|
161
|
+
* A registered owner also carries the provider names it previously owned. If
|
|
162
|
+
* that owner now omits one of those providers, the omission is an intentional
|
|
163
|
+
* in-process deletion rather than an old projection that never knew the row.
|
|
164
|
+
* Suppress only those names from preservation for this write. The suppression
|
|
165
|
+
* is committed globally only after refreshUserCostOverlays receives the
|
|
166
|
+
* successfully persisted view, so a failed atomic write cannot destroy the
|
|
167
|
+
* preservation safety net.
|
|
168
|
+
*/
|
|
169
|
+
export function withPreservedDiskOnlyProviders(config: OcxConfig): OcxConfig {
|
|
170
|
+
const tagged = config as PreservationTaggedConfig;
|
|
171
|
+
const owner = tagged[PRESERVATION_OWNER_STATE];
|
|
172
|
+
const deletedProviders = owner && preservationOwnerStates.has(owner)
|
|
173
|
+
? [...owner.ownedProviders].filter(name => !Object.hasOwn(config.providers ?? {}, name))
|
|
174
|
+
: [];
|
|
175
|
+
const deletedSet = new Set(deletedProviders);
|
|
176
|
+
|
|
177
|
+
let preserved: Record<string, OcxProviderConfig> | null = null;
|
|
178
|
+
if (preservedDiskOnlyProviders) {
|
|
179
|
+
const filtered = Object.entries(preservedDiskOnlyProviders)
|
|
180
|
+
.filter(([name]) => !deletedSet.has(name));
|
|
181
|
+
if (filtered.length > 0) preserved = Object.fromEntries(filtered);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
let persisted: OcxConfig;
|
|
185
|
+
if (preserved && Object.keys(preserved).length > 0) {
|
|
186
|
+
persisted = {
|
|
187
|
+
...config,
|
|
188
|
+
providers: {
|
|
189
|
+
...preserved,
|
|
190
|
+
...config.providers,
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
} else if (deletedProviders.length > 0) {
|
|
194
|
+
// Return a distinct object so the persisted-deletion marker remains scoped
|
|
195
|
+
// to this serialization attempt rather than the long-lived live config.
|
|
196
|
+
persisted = { ...config };
|
|
197
|
+
} else {
|
|
198
|
+
return config;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (deletedProviders.length > 0) {
|
|
202
|
+
Object.defineProperty(persisted as PreservationTaggedConfig, PERSISTED_PROVIDER_DELETIONS, {
|
|
203
|
+
value: deletedProviders,
|
|
204
|
+
enumerable: false,
|
|
205
|
+
configurable: true,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return persisted;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Test-only reset for the preserved disk-only provider registry. */
|
|
212
|
+
export function resetPreservedDiskOnlyProvidersForTests(): void {
|
|
213
|
+
preservedDiskOnlyProviders = null;
|
|
214
|
+
preservationOwnerStates.clear();
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Exact four fields accepted for a user-configured cost tuple. */
|
|
218
|
+
export const COST4_RATE_KEYS = ["input", "output", "cacheRead", "cacheWrite"] as const;
|
|
219
|
+
|
|
220
|
+
/** Shared per-rate predicate used by config validation, display sanitization, and runtime lifting. */
|
|
221
|
+
export function isValidCost4Rate(rate: unknown): rate is number {
|
|
222
|
+
return typeof rate === "number"
|
|
223
|
+
&& Number.isFinite(rate)
|
|
224
|
+
&& rate >= 0
|
|
225
|
+
&& rate <= MAX_COST4_RATE;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** True when `value` is a complete cost entry: all four rates are non-negative finite numbers. */
|
|
229
|
+
function validCost4(value: unknown): value is ProviderCostOverlay {
|
|
230
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
231
|
+
const entry = value as Record<string, unknown>;
|
|
232
|
+
return COST4_RATE_KEYS.every(key => isValidCost4Rate(entry[key]));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Rebuild the active user-overlay rows from the current config. Malformed rows
|
|
237
|
+
* are skipped (config validation reports them separately); a provider with no
|
|
238
|
+
* overlay contributes nothing.
|
|
239
|
+
*/
|
|
240
|
+
export function refreshUserCostOverlays(config: OcxConfig): void {
|
|
241
|
+
// Only persisted serialization views carry PERSISTED_PROVIDER_DELETIONS.
|
|
242
|
+
// Committing here means changed writes update owner state only after the
|
|
243
|
+
// atomic write succeeds, while byte-identical successful saves also converge.
|
|
244
|
+
commitPersistedProviderDeletions(config);
|
|
245
|
+
|
|
246
|
+
const rows: ExpectedPriceOverlay[] = [];
|
|
247
|
+
const providers = config.providers;
|
|
248
|
+
if (providers) {
|
|
249
|
+
for (const [providerName, provider] of Object.entries(providers)) {
|
|
250
|
+
const costs = provider?.modelCosts;
|
|
251
|
+
if (!costs || typeof costs !== "object" || Array.isArray(costs)) continue;
|
|
252
|
+
for (const [modelId, cost4] of Object.entries(costs)) {
|
|
253
|
+
if (!modelId.trim() || !validCost4(cost4)) continue;
|
|
254
|
+
rows.push({
|
|
255
|
+
provider: providerName,
|
|
256
|
+
modelId,
|
|
257
|
+
// Copy ONLY the four validated rate fields: a hand-edited row may
|
|
258
|
+
// carry extra properties (e.g. a misplaced apiKey) that must never
|
|
259
|
+
// reach display estimates or /api/logs through the registry.
|
|
260
|
+
cost4: {
|
|
261
|
+
input: cost4.input,
|
|
262
|
+
output: cost4.output,
|
|
263
|
+
cacheRead: cost4.cacheRead,
|
|
264
|
+
cacheWrite: cost4.cacheWrite,
|
|
265
|
+
},
|
|
266
|
+
// Display provenance only: redact token-shaped provider/model ids so
|
|
267
|
+
// the source string can never echo a pasted key. Matching still uses
|
|
268
|
+
// the raw fields, and the change-detection signature below MUST keep
|
|
269
|
+
// them raw — distinct ids would otherwise collapse to "[REDACTED]"
|
|
270
|
+
// and skip the version bump.
|
|
271
|
+
source: `config:providers.${redactSecretString(providerName)}.modelCosts[${redactSecretString(modelId)}]`,
|
|
272
|
+
verifiedAt: "user-configured",
|
|
273
|
+
status: "verified",
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// Config is re-loaded at many chokepoints (server start, migrations, persist
|
|
279
|
+
// paths). Bumping the version on every load — even when nothing changed —
|
|
280
|
+
// would invalidate the /api/usage summary cache on unrelated reloads and
|
|
281
|
+
// churn the cost memo. Only a real overlay change bumps the version, so the
|
|
282
|
+
// cache survives reloads of an unchanged config.
|
|
283
|
+
// The signature MUST compare the raw matching fields: two different
|
|
284
|
+
// secret-shaped ids would both redact to "[REDACTED]" and falsely look
|
|
285
|
+
// unchanged, skipping the version bump and serving stale estimates. The
|
|
286
|
+
// signature is process-local state and is never serialized to a response;
|
|
287
|
+
// only the display `source` above is redacted.
|
|
288
|
+
// The configured provider-name set is part of the identity too: adding or
|
|
289
|
+
// removing a provider (even one without an overlay) changes which names are
|
|
290
|
+
// allowed to collapse to a label base, so the resolver memo and the
|
|
291
|
+
// /api/usage summary cache must be invalidated on that change as well.
|
|
292
|
+
const configuredNames = Object.keys(providers ?? {}).sort();
|
|
293
|
+
const signature = `${JSON.stringify(configuredNames)}\u0000${JSON.stringify(rows)}`;
|
|
294
|
+
if (signature === activeSignature) return;
|
|
295
|
+
activeSignature = signature;
|
|
296
|
+
active = rows;
|
|
297
|
+
activeConfigured = new Set(configuredNames);
|
|
298
|
+
version++;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/** Active user-configured overlay rows (stable identity until the next refresh). */
|
|
302
|
+
export function activeUserCostOverlays(): readonly ExpectedPriceOverlay[] {
|
|
303
|
+
return active;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** Monotonic version bumped on every refresh; used by the estimator memo key. */
|
|
307
|
+
export function userCostOverlayVersion(): number {
|
|
308
|
+
return version;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/** Configured provider names from the last refresh (pricing-namespace identity). */
|
|
312
|
+
export function activeConfiguredProviders(): ReadonlySet<string> {
|
|
313
|
+
return activeConfigured;
|
|
314
|
+
}
|
|
@@ -3,7 +3,7 @@ import { CLAUDE_CODE_HEADERS, claudeCodeSessionId } from "../adapters/client-fin
|
|
|
3
3
|
import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
|
|
4
4
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
5
5
|
import { fetchWithResetRetry } from "../lib/upstream-retry";
|
|
6
|
-
import { getValidAccessToken } from "../oauth";
|
|
6
|
+
import { getValidAccessToken, publicOAuthAuthenticationErrorMessage } from "../oauth";
|
|
7
7
|
import { ANTHROPIC_OAUTH_BETA, CLAUDE_CODE_SYSTEM_INSTRUCTION } from "../oauth/anthropic";
|
|
8
8
|
import type { DescribeOutcome, VisionSettings } from "./describe";
|
|
9
9
|
|
|
@@ -67,8 +67,8 @@ export async function parseAnthropicVisionSSE(res: Response): Promise<DescribeOu
|
|
|
67
67
|
const delta = isRecord(data.delta) ? data.delta : {};
|
|
68
68
|
if (delta.type === "text_delta" && typeof delta.text === "string") text += delta.text;
|
|
69
69
|
} else if (data.type === "error") {
|
|
70
|
-
|
|
71
|
-
terminalError =
|
|
70
|
+
// Provider-authored stream errors can contain credentials, paths, or response bodies.
|
|
71
|
+
terminalError = "anthropic vision sidecar stream error";
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
74
|
|
|
@@ -116,7 +116,7 @@ export async function describeImageAnthropic(
|
|
|
116
116
|
try {
|
|
117
117
|
token = await getValidAccessToken(providerName);
|
|
118
118
|
} catch (error) {
|
|
119
|
-
return { text: "", error: `anthropic vision sidecar auth failed: ${
|
|
119
|
+
return { text: "", error: `anthropic vision sidecar auth failed: ${publicOAuthAuthenticationErrorMessage(error)}` };
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
const headers: Record<string, string> = {
|
|
@@ -166,7 +166,11 @@ export async function describeImageAnthropic(
|
|
|
166
166
|
if (!res.ok) {
|
|
167
167
|
const responseText = await res.text().catch(() => "");
|
|
168
168
|
console.warn(`[vision] anthropic sidecar HTTP ${res.status} (${Date.now() - startedAt}ms)`);
|
|
169
|
-
|
|
169
|
+
if (res.status === 401) {
|
|
170
|
+
return { text: "", error: `anthropic vision sidecar auth failed: ${publicOAuthAuthenticationErrorMessage(new Error(responseText))}` };
|
|
171
|
+
}
|
|
172
|
+
// Upstream bodies are untrusted and may contain credentials, paths, or provider diagnostics.
|
|
173
|
+
return { text: "", error: `anthropic vision sidecar HTTP ${res.status}` };
|
|
170
174
|
}
|
|
171
175
|
const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
|
|
172
176
|
try {
|
|
@@ -177,7 +181,7 @@ export async function describeImageAnthropic(
|
|
|
177
181
|
} catch (error) {
|
|
178
182
|
const kind = error instanceof Error && error.name === "TimeoutError" ? "timeout" : "connect_error";
|
|
179
183
|
console.warn(`[vision] anthropic sidecar ${kind} (${Date.now() - startedAt}ms)`);
|
|
180
|
-
return { text: "", error:
|
|
184
|
+
return { text: "", error: `anthropic vision sidecar ${kind}` };
|
|
181
185
|
} finally {
|
|
182
186
|
sidecarExit();
|
|
183
187
|
linkedSignal.cleanup();
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which backends may DESCRIBE images for the vision sidecar, and which
|
|
3
|
+
* candidate rows each can describe through (#2188 vision rules; roadmap 170
|
|
4
|
+
* REVISED: the "routed" backend).
|
|
5
|
+
*
|
|
6
|
+
* A SIBLING of WEB_SEARCH_BACKENDS, not a shared table: vision has no
|
|
7
|
+
* per-model probe (rule 2 is "− provably text-only", enforced by
|
|
8
|
+
* modelAcceptsImageInput, not here), carries per-side baseline models, and
|
|
9
|
+
* excludes non-LLM backends like exa.
|
|
10
|
+
*
|
|
11
|
+
* Three backends, not one per provider: "openai" and "anthropic" carry auth
|
|
12
|
+
* semantics loopback routing cannot replicate (forwarded ChatGPT headers,
|
|
13
|
+
* OAuth beta fences) and their defaults must not drift. Every OTHER
|
|
14
|
+
* picker-visible provider row reaches the describer through "routed" — a
|
|
15
|
+
* loopback self-fetch of the proxy's own /v1/chat/completions, where the
|
|
16
|
+
* router and adapters already speak each provider's wire. That is what makes
|
|
17
|
+
* this table closed under provider growth: a new provider needs no new
|
|
18
|
+
* describe executor.
|
|
19
|
+
*/
|
|
20
|
+
import type { OcxConfig } from "../types";
|
|
21
|
+
import type { SidecarAuthState } from "../sidecar/auth";
|
|
22
|
+
import { listOpenAiForwardSidecarCandidates } from "../providers/openai-sidecar";
|
|
23
|
+
import type { VisionCandidateModel, VisionSidecarBackend } from "./eligibility";
|
|
24
|
+
|
|
25
|
+
export interface VisionBackendDescriptor {
|
|
26
|
+
backend: VisionSidecarBackend;
|
|
27
|
+
/** Liveness signal for this backend. */
|
|
28
|
+
isActive(auth: SidecarAuthState, config: OcxConfig): boolean;
|
|
29
|
+
/** Which candidate rows this backend's describe executor can actually run. */
|
|
30
|
+
candidateMatch(candidate: VisionCandidateModel, auth: SidecarAuthState): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Default entry for this side: cheap, image-capable, present in every
|
|
33
|
+
* deployment. Only the two universal sides carry one — "routed" has no
|
|
34
|
+
* universal model to name.
|
|
35
|
+
*/
|
|
36
|
+
baseline?: string;
|
|
37
|
+
/** Stable option ordering (baselines first within a side). */
|
|
38
|
+
rank: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const VISION_BACKENDS: readonly VisionBackendDescriptor[] = [
|
|
42
|
+
{
|
|
43
|
+
backend: "openai",
|
|
44
|
+
// The OpenAI describer needs a CANONICAL ChatGPT forward provider, not
|
|
45
|
+
// merely a provider keyed "openai" — same predicate the runtime sidecar
|
|
46
|
+
// resolver uses. Deliberately NOT auth.isCodexAuth: tightening to a live
|
|
47
|
+
// credential here would change which options a fresh install sees, and
|
|
48
|
+
// the options list is a suggestion surface, not the write gate.
|
|
49
|
+
isActive: (_auth, config) => listOpenAiForwardSidecarCandidates(config).length > 0,
|
|
50
|
+
candidateMatch: candidate => candidate.native === true || candidate.provider === "openai",
|
|
51
|
+
baseline: "gpt-5.6-luna",
|
|
52
|
+
rank: 0,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
backend: "anthropic",
|
|
56
|
+
isActive: auth => auth.isAnthropicAuth,
|
|
57
|
+
// The runtime dispatches through exactly ONE Anthropic provider — the
|
|
58
|
+
// resolved OAuth row. Same-adapter keyed rows are unreachable (see
|
|
59
|
+
// visionBackendForCandidate's original stance).
|
|
60
|
+
candidateMatch: (candidate, auth) => candidate.provider === auth.anthropicProviderName,
|
|
61
|
+
baseline: "claude-haiku-4-5",
|
|
62
|
+
rank: 1,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
backend: "routed",
|
|
66
|
+
// Always offered: options only materialize when a matching picker row
|
|
67
|
+
// exists, and the row's own provider config is the liveness signal — the
|
|
68
|
+
// loopback request fails closed through ordinary routing errors.
|
|
69
|
+
isActive: () => true,
|
|
70
|
+
// Any row the other two executors do NOT own. Auth-slot rows are
|
|
71
|
+
// entitlements of the openai/anthropic sides and never route here.
|
|
72
|
+
candidateMatch: (candidate, auth) =>
|
|
73
|
+
candidate.native !== true
|
|
74
|
+
&& candidate.provider !== "openai"
|
|
75
|
+
&& candidate.provider !== auth.anthropicProviderName,
|
|
76
|
+
rank: 2,
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
export function visionBackendDescriptor(backend: VisionSidecarBackend): VisionBackendDescriptor {
|
|
81
|
+
const descriptor = VISION_BACKENDS.find(entry => entry.backend === backend);
|
|
82
|
+
if (!descriptor) throw new Error(`unknown vision backend "${backend}"`);
|
|
83
|
+
return descriptor;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The active backend set for option generation. Falls back to the two
|
|
88
|
+
* UNIVERSAL sides when neither is active (fresh install: picker stays
|
|
89
|
+
* populated, permissive-unknown rule); "routed" is active by construction.
|
|
90
|
+
*/
|
|
91
|
+
export function activeVisionBackends(auth: SidecarAuthState, config: OcxConfig): VisionSidecarBackend[] {
|
|
92
|
+
const active = VISION_BACKENDS.filter(entry => entry.isActive(auth, config)).map(entry => entry.backend);
|
|
93
|
+
return active.includes("openai") || active.includes("anthropic")
|
|
94
|
+
? active
|
|
95
|
+
: ["openai", "anthropic", ...active.filter(backend => backend === "routed")];
|
|
96
|
+
}
|
|
97
|
+
|
package/src/vision/describe.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { OcxProviderConfig } from "../types";
|
|
2
|
+
import type { VisionReasoningEffort } from "../reasoning-effort";
|
|
2
3
|
import { FORWARD_HEADERS } from "../adapters/openai-responses";
|
|
3
4
|
import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
|
|
4
5
|
import { redactSecretString } from "../lib/redact";
|
|
@@ -9,6 +10,7 @@ import type { SidecarOutcomeRecorder } from "../web-search/executor";
|
|
|
9
10
|
|
|
10
11
|
export interface VisionSettings {
|
|
11
12
|
model: string;
|
|
13
|
+
reasoning: VisionReasoningEffort;
|
|
12
14
|
timeoutMs: number;
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -77,9 +79,9 @@ export async function describeImage(
|
|
|
77
79
|
"verbatim, and note UI/layout, colors, branding/logos, charts, and notable details. Focus on " +
|
|
78
80
|
"what's relevant to the user's request. Output only the description.",
|
|
79
81
|
input: [{ type: "message", role: "user", content }],
|
|
80
|
-
reasoning: { effort:
|
|
81
|
-
// The ChatGPT (codex) backend rejects `max_output_tokens` ("Unsupported parameter"); the
|
|
82
|
-
//
|
|
82
|
+
reasoning: { effort: settings.reasoning },
|
|
83
|
+
// The ChatGPT (codex) backend rejects `max_output_tokens` ("Unsupported parameter"); the shared
|
|
84
|
+
// SSE parser bounds raw response bytes before DESC_MAX_CHARS applies its display clamp.
|
|
83
85
|
store: false,
|
|
84
86
|
stream: true,
|
|
85
87
|
};
|
|
@@ -93,6 +95,10 @@ export async function describeImage(
|
|
|
93
95
|
headers,
|
|
94
96
|
body: JSON.stringify(body),
|
|
95
97
|
signal: linkedSignal.signal,
|
|
98
|
+
// Credential-bearing: do not follow a cross-origin 3xx. Bun strips `Authorization`
|
|
99
|
+
// across origins but forwards nonstandard headers such as `chatgpt-account-id`,
|
|
100
|
+
// `session_id`, and `x-codex-turn-metadata` to the redirect target.
|
|
101
|
+
redirect: "manual",
|
|
96
102
|
}),
|
|
97
103
|
{ abortSignal: linkedSignal.signal, label: "vision-sidecar" },
|
|
98
104
|
);
|