@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
package/src/claude/desktop-3p.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
-
import { copyFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, unlinkSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { atomicWriteFile } from "../config";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
renderDesktopProfile,
|
|
11
11
|
type DesktopProfileModel,
|
|
12
12
|
} from "./desktop-profile";
|
|
13
|
-
import { nativeOpenAiContextWindow } from "../codex/catalog";
|
|
13
|
+
import { nativeOpenAiContextWindow, type NativeContextLimitsInput } from "../codex/catalog";
|
|
14
14
|
import { assertDesktop3pModelsValid } from "./desktop-3p-guard";
|
|
15
15
|
|
|
16
16
|
export interface Desktop3pModelEntry {
|
|
@@ -103,6 +103,45 @@ interface Desktop3pMetadata {
|
|
|
103
103
|
[key: string]: unknown;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
export type Desktop3pLibraryKind =
|
|
107
|
+
| "not_installed"
|
|
108
|
+
| "standard"
|
|
109
|
+
| "gateway_ours"
|
|
110
|
+
| "gateway_drifted"
|
|
111
|
+
| "foreign"
|
|
112
|
+
| "no_owned_state"
|
|
113
|
+
| "broken"
|
|
114
|
+
| "unsafe";
|
|
115
|
+
|
|
116
|
+
export interface Desktop3pLibraryInspection {
|
|
117
|
+
kind: Desktop3pLibraryKind;
|
|
118
|
+
libraryPath: string;
|
|
119
|
+
selectedProfilePath: string | null;
|
|
120
|
+
appliedId: string | null;
|
|
121
|
+
/** Paths of opencodex-owned rows that are not selected by Desktop. */
|
|
122
|
+
residualPaths: string[];
|
|
123
|
+
/** Bounded reason code; never includes metadata or profile contents. */
|
|
124
|
+
reason?: "metadata_unreadable" | "unsafe_applied_id" | "invalid_owned_profile";
|
|
125
|
+
fingerprint?: string;
|
|
126
|
+
/**
|
|
127
|
+
* Whether Desktop's applied selection is our owned entry, by ID match alone.
|
|
128
|
+
* `null` = undeterminable (no metadata, unreadable metadata, or no appliedId);
|
|
129
|
+
* a readable appliedId with no owned entry is a KNOWN false, not unknown.
|
|
130
|
+
* Deliberately independent of profile-file health: the status contract
|
|
131
|
+
* predates this inspector and callers render tri-state.
|
|
132
|
+
*/
|
|
133
|
+
ownedProfileActive: boolean | null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface Desktop3pRemovalResult {
|
|
137
|
+
ok: boolean;
|
|
138
|
+
changed: boolean;
|
|
139
|
+
kind: "removed" | "noop" | "cleanup_incomplete" | "unsafe" | "write_failed";
|
|
140
|
+
libraryPath: string;
|
|
141
|
+
residualPaths?: string[];
|
|
142
|
+
reason?: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
106
145
|
let desktop3pRegistry = new Map<string, string>();
|
|
107
146
|
let desktop3pAliasesByRoute = new Map<string, string>();
|
|
108
147
|
|
|
@@ -152,6 +191,7 @@ function collectDesktop3pModels(
|
|
|
152
191
|
nativeSlugs: string[],
|
|
153
192
|
routedModels: Array<Desktop3pRoutedModel>,
|
|
154
193
|
profile?: OcxClaudeDesktopProfile,
|
|
194
|
+
nativeContextCap?: NativeContextLimitsInput,
|
|
155
195
|
): { models: Desktop3pModelEntry[]; registry: Map<string, string> } {
|
|
156
196
|
const registry = new Map<string, string>();
|
|
157
197
|
const models: Desktop3pModelEntry[] = [];
|
|
@@ -160,7 +200,7 @@ function collectDesktop3pModels(
|
|
|
160
200
|
// Desktop DTO uses, so a native 1M/372k model resolves identically in the written
|
|
161
201
|
// config and on the dashboard.
|
|
162
202
|
...nativeSlugs.map(id => {
|
|
163
|
-
const contextWindow = nativeOpenAiContextWindow(id);
|
|
203
|
+
const contextWindow = nativeOpenAiContextWindow(id, nativeContextCap);
|
|
164
204
|
return { provider: "native", id, ...(contextWindow !== undefined ? { contextWindow } : {}) };
|
|
165
205
|
}),
|
|
166
206
|
...routedModels,
|
|
@@ -253,8 +293,9 @@ export function buildDesktop3pRegistry(
|
|
|
253
293
|
nativeSlugs: string[],
|
|
254
294
|
routedModels: Array<Desktop3pRoutedModel>,
|
|
255
295
|
profile?: OcxClaudeDesktopProfile,
|
|
296
|
+
nativeContextCap?: NativeContextLimitsInput,
|
|
256
297
|
): Map<string, string> {
|
|
257
|
-
const { registry } = collectDesktop3pModels(nativeSlugs, routedModels, profile);
|
|
298
|
+
const { registry } = collectDesktop3pModels(nativeSlugs, routedModels, profile, nativeContextCap);
|
|
258
299
|
desktop3pRegistry = registry;
|
|
259
300
|
return registry;
|
|
260
301
|
}
|
|
@@ -264,8 +305,9 @@ export function generateDesktop3pModels(
|
|
|
264
305
|
nativeSlugs: string[],
|
|
265
306
|
routedModels: Array<Desktop3pRoutedModel>,
|
|
266
307
|
profile?: OcxClaudeDesktopProfile,
|
|
308
|
+
nativeContextCap?: NativeContextLimitsInput,
|
|
267
309
|
): Desktop3pModelEntry[] {
|
|
268
|
-
const { models, registry } = collectDesktop3pModels(nativeSlugs, routedModels, profile);
|
|
310
|
+
const { models, registry } = collectDesktop3pModels(nativeSlugs, routedModels, profile, nativeContextCap);
|
|
269
311
|
desktop3pRegistry = registry;
|
|
270
312
|
return models;
|
|
271
313
|
}
|
|
@@ -295,6 +337,7 @@ export function generateDesktop3pConfig(
|
|
|
295
337
|
apiKey = "ocx",
|
|
296
338
|
mode: Desktop3pConfigMode = "static",
|
|
297
339
|
profile?: OcxClaudeDesktopProfile,
|
|
340
|
+
nativeContextCap?: NativeContextLimitsInput,
|
|
298
341
|
): object {
|
|
299
342
|
const base = {
|
|
300
343
|
inferenceProvider: "gateway",
|
|
@@ -304,14 +347,14 @@ export function generateDesktop3pConfig(
|
|
|
304
347
|
};
|
|
305
348
|
if (mode === "discovery") {
|
|
306
349
|
// Build/refresh the decode registry even though no static list is emitted.
|
|
307
|
-
buildDesktop3pRegistry(nativeSlugs, routedModels, profile);
|
|
350
|
+
buildDesktop3pRegistry(nativeSlugs, routedModels, profile, nativeContextCap);
|
|
308
351
|
return { ...base, modelDiscoveryEnabled: true };
|
|
309
352
|
}
|
|
310
353
|
return {
|
|
311
354
|
...base,
|
|
312
355
|
modelDiscoveryEnabled: mode === "hybrid",
|
|
313
356
|
inferenceModels: (() => {
|
|
314
|
-
const models = generateDesktop3pModels(nativeSlugs, routedModels, profile);
|
|
357
|
+
const models = generateDesktop3pModels(nativeSlugs, routedModels, profile, nativeContextCap);
|
|
315
358
|
// Fail loud at the write boundary rather than ship a config Desktop rejects:
|
|
316
359
|
// the output counterpart of the request-path guards.
|
|
317
360
|
assertDesktop3pModelsValid(models);
|
|
@@ -327,6 +370,195 @@ function parseMetadata(path: string): Desktop3pMetadata {
|
|
|
327
370
|
return { ...parsed, entries: parsed.entries };
|
|
328
371
|
}
|
|
329
372
|
|
|
373
|
+
const SAFE_DESKTOP_PROFILE_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
|
|
374
|
+
|
|
375
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
376
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function isOwnedDesktopEntry(entry: Desktop3pMetadataEntry | undefined): boolean {
|
|
380
|
+
return entry?.name === "opencodex" || entry?.name === "opencodex-standard";
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/** A gateway row is removable; the selected standard row must always remain. */
|
|
384
|
+
function isOwnedDesktopGatewayEntry(entry: Desktop3pMetadataEntry | undefined): boolean {
|
|
385
|
+
return entry?.name === "opencodex";
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function profilePath(libraryPath: string, id: string): string {
|
|
389
|
+
return join(libraryPath, `${id}.json`);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Read Desktop's selected config without changing its library.
|
|
394
|
+
*
|
|
395
|
+
* This is intentionally separate from the eager writer below: status probes must
|
|
396
|
+
* never manufacture a config-library directory on a machine without Desktop.
|
|
397
|
+
*/
|
|
398
|
+
export function inspectDesktop3pConfigLibrary(
|
|
399
|
+
options: Desktop3pConfigLibraryOptions & { appliedFingerprint?: string | null } = {},
|
|
400
|
+
): Desktop3pLibraryInspection {
|
|
401
|
+
const libraryPath = resolveDesktop3pConfigLibraryPath(options);
|
|
402
|
+
if (!existsSync(libraryPath)) {
|
|
403
|
+
return { kind: "not_installed", libraryPath, selectedProfilePath: null, appliedId: null, residualPaths: [], ownedProfileActive: null };
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const metadataPath = join(libraryPath, "_meta.json");
|
|
407
|
+
if (!existsSync(metadataPath)) {
|
|
408
|
+
return { kind: "no_owned_state", libraryPath, selectedProfilePath: null, appliedId: null, residualPaths: [], ownedProfileActive: null };
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
let metadata: Desktop3pMetadata;
|
|
412
|
+
try {
|
|
413
|
+
metadata = parseMetadata(metadataPath);
|
|
414
|
+
} catch {
|
|
415
|
+
return {
|
|
416
|
+
kind: "unsafe", libraryPath, selectedProfilePath: null, appliedId: null, residualPaths: [], reason: "metadata_unreadable", ownedProfileActive: null,
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
const appliedId = typeof metadata.appliedId === "string" ? metadata.appliedId : null;
|
|
420
|
+
if (appliedId === null) {
|
|
421
|
+
return { kind: "no_owned_state", libraryPath, selectedProfilePath: null, appliedId: null, residualPaths: [], ownedProfileActive: null };
|
|
422
|
+
}
|
|
423
|
+
const selected = metadata.entries.find(entry => entry?.id === appliedId);
|
|
424
|
+
// A readable appliedId with no owned entry is a KNOWN false, not unknown.
|
|
425
|
+
const ownedProfileActive = isOwnedDesktopEntry(selected);
|
|
426
|
+
if (!SAFE_DESKTOP_PROFILE_ID.test(appliedId)) {
|
|
427
|
+
return {
|
|
428
|
+
kind: "unsafe", libraryPath, selectedProfilePath: null, appliedId, residualPaths: [], reason: "unsafe_applied_id", ownedProfileActive,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
const selectedProfilePath = profilePath(libraryPath, appliedId);
|
|
433
|
+
const residualPaths = metadata.entries
|
|
434
|
+
.filter(entry => isOwnedDesktopGatewayEntry(entry) && entry.id !== appliedId && SAFE_DESKTOP_PROFILE_ID.test(entry.id))
|
|
435
|
+
.flatMap(entry => [profilePath(libraryPath, entry.id), `${profilePath(libraryPath, entry.id)}.bak`])
|
|
436
|
+
.filter(existsSync);
|
|
437
|
+
if (!existsSync(selectedProfilePath)) {
|
|
438
|
+
return { kind: "broken", libraryPath, selectedProfilePath, appliedId, residualPaths, ownedProfileActive };
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
let profile: Record<string, unknown>;
|
|
442
|
+
let fingerprint: string;
|
|
443
|
+
try {
|
|
444
|
+
const source = readFileSync(selectedProfilePath, "utf8");
|
|
445
|
+
const parsed = JSON.parse(source) as unknown;
|
|
446
|
+
if (!isRecord(parsed)) return { kind: "broken", libraryPath, selectedProfilePath, appliedId, residualPaths, ownedProfileActive };
|
|
447
|
+
profile = parsed;
|
|
448
|
+
fingerprint = createHash("sha256").update(source).digest("hex").slice(0, 16);
|
|
449
|
+
} catch {
|
|
450
|
+
return { kind: "broken", libraryPath, selectedProfilePath, appliedId, residualPaths, ownedProfileActive };
|
|
451
|
+
}
|
|
452
|
+
if (!isOwnedDesktopEntry(selected)) {
|
|
453
|
+
return { kind: "foreign", libraryPath, selectedProfilePath, appliedId, residualPaths, fingerprint, ownedProfileActive };
|
|
454
|
+
}
|
|
455
|
+
if (profile.inferenceProvider === undefined) {
|
|
456
|
+
return { kind: "standard", libraryPath, selectedProfilePath, appliedId, residualPaths, fingerprint, ownedProfileActive };
|
|
457
|
+
}
|
|
458
|
+
const validGateway = profile.inferenceProvider === "gateway"
|
|
459
|
+
&& profile.inferenceCredentialKind === "static"
|
|
460
|
+
&& typeof profile.inferenceGatewayBaseUrl === "string"
|
|
461
|
+
&& typeof profile.inferenceGatewayApiKey === "string";
|
|
462
|
+
if (!validGateway) {
|
|
463
|
+
return {
|
|
464
|
+
kind: "unsafe", libraryPath, selectedProfilePath, appliedId, residualPaths, fingerprint, reason: "invalid_owned_profile", ownedProfileActive,
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
return {
|
|
468
|
+
kind: options.appliedFingerprint && options.appliedFingerprint === fingerprint ? "gateway_ours" : "gateway_drifted",
|
|
469
|
+
libraryPath, selectedProfilePath, appliedId, residualPaths, fingerprint, ownedProfileActive,
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Select a credential-free standard profile before deleting an owned gateway.
|
|
475
|
+
* The old metadata row remains as a retry locator only until both its profile
|
|
476
|
+
* and backup are absent; successful cleanup removes it in the same operation.
|
|
477
|
+
*
|
|
478
|
+
* `gateway_drifted` is still an owned opencodex gateway (name + valid shape); the
|
|
479
|
+
* fingerprint only says on-disk bytes differ from the last saved marker. Refusing
|
|
480
|
+
* OFF for drift left users unable to disable after a lost `appliedFingerprint`
|
|
481
|
+
* (or any other benign mismatch), while the Integrations card still showed the
|
|
482
|
+
* leftover profile as applied/stale.
|
|
483
|
+
*/
|
|
484
|
+
export function removeDesktop3pStandardPivot(
|
|
485
|
+
options: Desktop3pConfigLibraryOptions & {
|
|
486
|
+
appliedFingerprint?: string | null;
|
|
487
|
+
unlink?: (path: string) => void;
|
|
488
|
+
} = {},
|
|
489
|
+
): Desktop3pRemovalResult {
|
|
490
|
+
const inspected = inspectDesktop3pConfigLibrary(options);
|
|
491
|
+
if (inspected.kind === "not_installed" || inspected.kind === "no_owned_state") {
|
|
492
|
+
return { ok: true, changed: false, kind: "noop", libraryPath: inspected.libraryPath };
|
|
493
|
+
}
|
|
494
|
+
if (inspected.kind === "broken" || inspected.kind === "unsafe") {
|
|
495
|
+
return { ok: false, changed: false, kind: "unsafe", libraryPath: inspected.libraryPath, reason: inspected.reason };
|
|
496
|
+
}
|
|
497
|
+
if (!inspected.appliedId || !SAFE_DESKTOP_PROFILE_ID.test(inspected.appliedId)) {
|
|
498
|
+
return { ok: false, changed: false, kind: "unsafe", libraryPath: inspected.libraryPath, reason: "unsafe_applied_id" };
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
const metadataPath = join(inspected.libraryPath, "_meta.json");
|
|
502
|
+
try {
|
|
503
|
+
const metadata = parseMetadata(metadataPath);
|
|
504
|
+
const selectedId = inspected.appliedId;
|
|
505
|
+
// When Desktop is actively using our gateway (current or drifted), pivot only
|
|
506
|
+
// that selected row first. Any second owned row is residue for a later
|
|
507
|
+
// standard-mode retry; this preserves the selected-row preference after an
|
|
508
|
+
// interrupted cleanup.
|
|
509
|
+
const selectedOwnedGatewayActive =
|
|
510
|
+
inspected.kind === "gateway_ours" || inspected.kind === "gateway_drifted";
|
|
511
|
+
const targetIds = selectedOwnedGatewayActive
|
|
512
|
+
? [selectedId]
|
|
513
|
+
: metadata.entries
|
|
514
|
+
.filter(isOwnedDesktopGatewayEntry)
|
|
515
|
+
.map(entry => entry.id)
|
|
516
|
+
.filter(id => SAFE_DESKTOP_PROFILE_ID.test(id));
|
|
517
|
+
if (targetIds.length === 0) return { ok: true, changed: false, kind: "noop", libraryPath: inspected.libraryPath };
|
|
518
|
+
|
|
519
|
+
let metadataAfterPivot = metadata;
|
|
520
|
+
if (selectedOwnedGatewayActive) {
|
|
521
|
+
const standardId = randomUUID();
|
|
522
|
+
const standardPath = profilePath(inspected.libraryPath, standardId);
|
|
523
|
+
atomicWriteFile(standardPath, "{}\n");
|
|
524
|
+
const standardEntry: Desktop3pMetadataEntry = { id: standardId, name: "opencodex-standard" };
|
|
525
|
+
metadataAfterPivot = { ...metadata, appliedId: standardId, entries: [...metadata.entries, standardEntry] };
|
|
526
|
+
atomicWriteFile(metadataPath, JSON.stringify(metadataAfterPivot, null, 2) + "\n");
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const residualPaths: string[] = [];
|
|
530
|
+
for (const id of targetIds) {
|
|
531
|
+
for (const candidate of [profilePath(inspected.libraryPath, id), `${profilePath(inspected.libraryPath, id)}.bak`]) {
|
|
532
|
+
try {
|
|
533
|
+
if (existsSync(candidate)) (options.unlink ?? unlinkSync)(candidate);
|
|
534
|
+
} catch {
|
|
535
|
+
// Only the path is allowed to leave this credential-bearing cleanup boundary.
|
|
536
|
+
}
|
|
537
|
+
if (existsSync(candidate)) residualPaths.push(candidate);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
const ownedResiduePaths = metadataAfterPivot.entries
|
|
541
|
+
.filter(entry => isOwnedDesktopGatewayEntry(entry) && !targetIds.includes(entry.id) && SAFE_DESKTOP_PROFILE_ID.test(entry.id))
|
|
542
|
+
.flatMap(entry => [profilePath(inspected.libraryPath, entry.id), `${profilePath(inspected.libraryPath, entry.id)}.bak`])
|
|
543
|
+
.filter(existsSync);
|
|
544
|
+
if (residualPaths.length > 0 || ownedResiduePaths.length > 0) {
|
|
545
|
+
return {
|
|
546
|
+
ok: false, changed: true, kind: "cleanup_incomplete", libraryPath: inspected.libraryPath,
|
|
547
|
+
residualPaths: [...new Set([...residualPaths, ...ownedResiduePaths])],
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
// Do not leave a metadata row pointing at a deleted profile. For a foreign
|
|
551
|
+
// selection this only removes proven opencodex residues; appliedId is kept.
|
|
552
|
+
atomicWriteFile(
|
|
553
|
+
metadataPath,
|
|
554
|
+
JSON.stringify({ ...metadataAfterPivot, entries: metadataAfterPivot.entries.filter(entry => !targetIds.includes(entry.id)) }, null, 2) + "\n",
|
|
555
|
+
);
|
|
556
|
+
return { ok: true, changed: true, kind: "removed", libraryPath: inspected.libraryPath };
|
|
557
|
+
} catch {
|
|
558
|
+
return { ok: false, changed: false, kind: "write_failed", libraryPath: inspected.libraryPath };
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
330
562
|
/** Write and apply the opencodex config in Claude Desktop 3P's config library. */
|
|
331
563
|
export function writeDesktop3pConfig(
|
|
332
564
|
port: number,
|
|
@@ -335,6 +567,7 @@ export function writeDesktop3pConfig(
|
|
|
335
567
|
apiKey?: string,
|
|
336
568
|
mode: Desktop3pConfigMode = "static",
|
|
337
569
|
profile?: OcxClaudeDesktopProfile,
|
|
570
|
+
nativeContextCap?: NativeContextLimitsInput,
|
|
338
571
|
): { written: boolean; path: string; reason?: string; fingerprint?: string } {
|
|
339
572
|
const libraryPath = resolveDesktop3pConfigLibraryPath();
|
|
340
573
|
const metadataPath = join(libraryPath, "_meta.json");
|
|
@@ -343,7 +576,8 @@ export function writeDesktop3pConfig(
|
|
|
343
576
|
try {
|
|
344
577
|
mkdirSync(libraryPath, { recursive: true, mode: 0o700 });
|
|
345
578
|
const metadata = parseMetadata(metadataPath);
|
|
346
|
-
const
|
|
579
|
+
const selected = metadata.entries.find(entry => entry?.id === metadata.appliedId && isOwnedDesktopGatewayEntry(entry));
|
|
580
|
+
const existing = selected ?? metadata.entries.find(entry => isOwnedDesktopGatewayEntry(entry) && typeof entry.id === "string");
|
|
347
581
|
const id = existing?.id ?? randomUUID();
|
|
348
582
|
configPath = join(libraryPath, `${id}.json`);
|
|
349
583
|
const entry: Desktop3pMetadataEntry = existing ? { ...existing, id, name: "opencodex" } : { id, name: "opencodex" };
|
|
@@ -351,7 +585,7 @@ export function writeDesktop3pConfig(
|
|
|
351
585
|
? metadata.entries.map(current => current === existing ? entry : current)
|
|
352
586
|
: [...metadata.entries, entry];
|
|
353
587
|
|
|
354
|
-
const configJson = JSON.stringify(generateDesktop3pConfig(port, nativeSlugs, routedModels, apiKey, mode, profile), null, 2) + "\n";
|
|
588
|
+
const configJson = JSON.stringify(generateDesktop3pConfig(port, nativeSlugs, routedModels, apiKey, mode, profile, nativeContextCap), null, 2) + "\n";
|
|
355
589
|
const fingerprint = createHash("sha256").update(configJson).digest("hex").slice(0, 16);
|
|
356
590
|
const { backupPath } = atomicReplaceDesktopConfig(configPath, configJson);
|
|
357
591
|
try {
|
|
@@ -13,12 +13,21 @@
|
|
|
13
13
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
14
14
|
import { homedir } from "node:os";
|
|
15
15
|
import { join } from "node:path";
|
|
16
|
+
import { loadServiceTokenFromFile, serviceApiTokenFilePath } from "../lib/service-secrets";
|
|
17
|
+
import type { OcxConfig } from "../types";
|
|
16
18
|
|
|
17
19
|
export interface GatewayModelRow {
|
|
18
20
|
id: string;
|
|
19
21
|
display_name?: string;
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
export interface GatewayModelCacheRefreshOptions {
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
configDir?: string;
|
|
27
|
+
admissionConfig?: Pick<OcxConfig, "apiKeys">;
|
|
28
|
+
env?: NodeJS.ProcessEnv;
|
|
29
|
+
}
|
|
30
|
+
|
|
22
31
|
/** Claude Code config dir (CLAUDE_CONFIG_DIR override honored, like the CLI). */
|
|
23
32
|
export function claudeConfigDir(): string {
|
|
24
33
|
const custom = process.env.CLAUDE_CONFIG_DIR;
|
|
@@ -45,14 +54,42 @@ export function writeGatewayModelCache(baseUrl: string, models: readonly Gateway
|
|
|
45
54
|
}
|
|
46
55
|
}
|
|
47
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Hardened service-token file, the same precedence `ocx opencode` uses. A service
|
|
59
|
+
* install writes the admission token to disk rather than the interactive environment,
|
|
60
|
+
* so an interactive `ocx claude` with neither env token nor configured key would
|
|
61
|
+
* otherwise still get a 401 and keep a stale picker list.
|
|
62
|
+
*/
|
|
63
|
+
function serviceFileToken(env: NodeJS.ProcessEnv): string | null {
|
|
64
|
+
const lookup = env.OCX_API_TOKEN_FILE?.trim()
|
|
65
|
+
? env
|
|
66
|
+
: { ...env, OCX_API_TOKEN_FILE: serviceApiTokenFilePath() };
|
|
67
|
+
return loadServiceTokenFromFile(lookup as Record<string, string | undefined>);
|
|
68
|
+
}
|
|
69
|
+
|
|
48
70
|
/** Fetch the anthropic-flavor /v1/models from the local proxy and write the cache. */
|
|
49
|
-
export async function refreshGatewayModelCacheFromProxy(
|
|
71
|
+
export async function refreshGatewayModelCacheFromProxy(
|
|
72
|
+
port: number,
|
|
73
|
+
options: GatewayModelCacheRefreshOptions = {},
|
|
74
|
+
): Promise<string | null> {
|
|
50
75
|
try {
|
|
76
|
+
const headers = new Headers({ "anthropic-version": "2023-06-01" });
|
|
77
|
+
// A wildcard/non-loopback listener requires data-plane admission even for a
|
|
78
|
+
// request sent to its local 127.0.0.1 address. Reuse the same dedicated
|
|
79
|
+
// credential domain as /v1/models admission; never place it in Authorization,
|
|
80
|
+
// which can belong to an upstream provider on other data-plane surfaces.
|
|
81
|
+
const envToken = (options.env ?? process.env).OPENCODEX_API_AUTH_TOKEN?.trim();
|
|
82
|
+
const configuredToken = options.admissionConfig?.apiKeys
|
|
83
|
+
?.find(entry => entry.key.trim().length > 0)
|
|
84
|
+
?.key.trim();
|
|
85
|
+
const admissionToken = envToken || serviceFileToken(options.env ?? process.env) || configuredToken;
|
|
86
|
+
if (admissionToken) headers.set("x-opencodex-api-key", admissionToken);
|
|
87
|
+
|
|
51
88
|
// ?ids=cli pins the readable claude-ocx id family deterministically (audit 051
|
|
52
89
|
// #5): the cache prewrite must not depend on UA sniffing.
|
|
53
90
|
const res = await fetch(`http://127.0.0.1:${port}/v1/models?limit=1000&ids=cli`, {
|
|
54
|
-
headers
|
|
55
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
91
|
+
headers,
|
|
92
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? 3_000),
|
|
56
93
|
});
|
|
57
94
|
if (!res.ok) return null;
|
|
58
95
|
const body = await res.json() as { data?: unknown };
|
|
@@ -63,7 +100,7 @@ export async function refreshGatewayModelCacheFromProxy(port: number, timeoutMs
|
|
|
63
100
|
id: m.id as string,
|
|
64
101
|
display_name: typeof m.display_name === "string" ? m.display_name : undefined,
|
|
65
102
|
}));
|
|
66
|
-
return writeGatewayModelCache(`http://127.0.0.1:${port}`, models, configDir);
|
|
103
|
+
return writeGatewayModelCache(`http://127.0.0.1:${port}`, models, options.configDir);
|
|
67
104
|
} catch {
|
|
68
105
|
return null;
|
|
69
106
|
}
|
package/src/claude/inbound.ts
CHANGED
|
@@ -10,9 +10,11 @@
|
|
|
10
10
|
* - top_k is accepted and silently dropped (no Responses equivalent, CCR parity).
|
|
11
11
|
*/
|
|
12
12
|
import type { OcxClaudeCodeConfig } from "../types";
|
|
13
|
+
import { isAnthropicOutputSchema } from "../adapters/anthropic-output-schema";
|
|
13
14
|
import { resolveAlias } from "./alias";
|
|
14
15
|
import { stripOneMillionMarker } from "./context-windows";
|
|
15
16
|
import { resolveDesktop3pAlias } from "./desktop-3p";
|
|
17
|
+
import { isClaudeWebSearchToolName } from "./outbound";
|
|
16
18
|
import { createHash } from "node:crypto";
|
|
17
19
|
|
|
18
20
|
export class AnthropicRequestError extends Error {}
|
|
@@ -23,7 +25,37 @@ function isRec(v: unknown): v is Rec {
|
|
|
23
25
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
function isClaudeClassifierModel(model: string): boolean {
|
|
29
|
+
const stripped = model.replace(/-\d{8}$/, "");
|
|
30
|
+
return /^claude-opus-[45]/.test(stripped);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Explicitly configured classifier route for Claude Code Auto Mode safety checks (#1697).
|
|
35
|
+
*
|
|
36
|
+
* Only OPERATOR-DECLARED targets are used: `classifierModel`, then the ordered
|
|
37
|
+
* `classifierFallbacks`. Both are qualified `provider/model` strings the operator chose, so
|
|
38
|
+
* routing them crosses no boundary the operator did not ask for.
|
|
39
|
+
*
|
|
40
|
+
* Deliberately NOT here: inferring a provider from `claudeCode.model`. That value is the
|
|
41
|
+
* injected/default config slot, not the provider the live session actually selected, so it goes
|
|
42
|
+
* stale the moment the user changes the model picker -- and acting on it would silently move a
|
|
43
|
+
* classifier turn onto a provider with its own privacy and billing consequences. Live session
|
|
44
|
+
* affinity needs the request/session state this function does not have; it is tracked as
|
|
45
|
+
* follow-up work rather than approximated from static config.
|
|
46
|
+
*/
|
|
47
|
+
function configuredClassifierRoute(cc?: OcxClaudeCodeConfig): string | undefined {
|
|
48
|
+
const explicit = typeof cc?.classifierModel === "string" ? cc.classifierModel.trim() : "";
|
|
49
|
+
if (explicit.length > 0) return explicit;
|
|
50
|
+
if (Array.isArray(cc?.classifierFallbacks)) {
|
|
51
|
+
for (const candidate of cc.classifierFallbacks) {
|
|
52
|
+
if (typeof candidate === "string" && candidate.trim().length > 0) return candidate.trim();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Alias first, then modelMap: exact id, then date-suffix-stripped (`-\d{8}$`), then classifier affinity/config, else passthrough. */
|
|
27
59
|
export function resolveInboundModel(model: string, cc?: OcxClaudeCodeConfig): string {
|
|
28
60
|
// Defensive: Desktop/CLI strip the [1m] context-variant marker client-side, but a
|
|
29
61
|
// leaking build must not break alias decode (devlog 138 — the 1M signal is the
|
|
@@ -45,6 +77,14 @@ export function resolveInboundModel(model: string, cc?: OcxClaudeCodeConfig): st
|
|
|
45
77
|
const stripped = model.replace(/-\d{8}$/, "");
|
|
46
78
|
const dateless = map[stripped];
|
|
47
79
|
if (typeof dateless === "string" && dateless.length > 0) return dateless;
|
|
80
|
+
|
|
81
|
+
// Claude Code Auto Mode classifier routing (#1697). Bare classifier checks such as
|
|
82
|
+
// `claude-opus-5` carry no provider, so without this they fall through to defaultProvider --
|
|
83
|
+
// which may not speak Anthropic at all. Only an operator-declared target is used.
|
|
84
|
+
if (isClaudeClassifierModel(model)) {
|
|
85
|
+
const configured = configuredClassifierRoute(cc);
|
|
86
|
+
if (configured) return configured;
|
|
87
|
+
}
|
|
48
88
|
return model;
|
|
49
89
|
}
|
|
50
90
|
|
|
@@ -68,6 +108,17 @@ export function effortFromOutputConfig(outputConfig: unknown): string | undefine
|
|
|
68
108
|
return typeof effort === "string" && OUTPUT_CONFIG_EFFORTS.has(effort) ? effort : undefined;
|
|
69
109
|
}
|
|
70
110
|
|
|
111
|
+
function formatFromOutputConfig(outputConfig: unknown): Rec | undefined {
|
|
112
|
+
if (!isRec(outputConfig) || !isRec(outputConfig.format)) return undefined;
|
|
113
|
+
const format = outputConfig.format;
|
|
114
|
+
if (
|
|
115
|
+
format.type !== "json_schema"
|
|
116
|
+
|| !isRec(format.schema)
|
|
117
|
+
|| !isAnthropicOutputSchema(format.schema)
|
|
118
|
+
) return undefined;
|
|
119
|
+
return { type: "json_schema", name: "response", schema: format.schema };
|
|
120
|
+
}
|
|
121
|
+
|
|
71
122
|
function systemToInstructions(system: unknown): string | undefined {
|
|
72
123
|
if (typeof system === "string") return system.length > 0 ? system : undefined;
|
|
73
124
|
if (Array.isArray(system)) {
|
|
@@ -106,6 +157,10 @@ function toolResultOutput(block: Rec): string | Rec[] {
|
|
|
106
157
|
} else if (item.type === "image") {
|
|
107
158
|
const img = imageBlockToInputImage(item);
|
|
108
159
|
if (img) out.push(img);
|
|
160
|
+
} else if (item.type === "document") {
|
|
161
|
+
// Same marker as the user-message document case below: the model should see the
|
|
162
|
+
// attachment happened instead of an empty tool output.
|
|
163
|
+
out.push({ type: "input_text", text: `[document${typeof item.title === "string" ? `: ${item.title}` : ""}]` });
|
|
109
164
|
}
|
|
110
165
|
}
|
|
111
166
|
if (isError) out.unshift({ type: "input_text", text: "[tool error]" });
|
|
@@ -371,7 +426,12 @@ function toolChoiceToResponses(choice: unknown, body: Rec): void {
|
|
|
371
426
|
if (typeof choice.name !== "string" || choice.name.length === 0) {
|
|
372
427
|
throw new AnthropicRequestError("tool_choice.tool requires a name");
|
|
373
428
|
}
|
|
374
|
-
|
|
429
|
+
// Anthropic represents hosted WebSearch as a named tool choice, while
|
|
430
|
+
// Responses requires the choice type to match the hosted declaration.
|
|
431
|
+
// Preserve forced-tool intent rather than weakening it to `auto`.
|
|
432
|
+
body.tool_choice = isClaudeWebSearchToolName(choice.name)
|
|
433
|
+
? { type: "web_search" }
|
|
434
|
+
: { type: "function", name: choice.name };
|
|
375
435
|
break;
|
|
376
436
|
default: break;
|
|
377
437
|
}
|
|
@@ -457,6 +517,8 @@ export function anthropicToResponsesTranslation(raw: unknown, cc?: OcxClaudeCode
|
|
|
457
517
|
if (Array.isArray(raw.stop_sequences) && raw.stop_sequences.length > 0) {
|
|
458
518
|
body.stop = raw.stop_sequences.filter((s): s is string => typeof s === "string");
|
|
459
519
|
}
|
|
520
|
+
const outputConfigFormat = formatFromOutputConfig(raw.output_config);
|
|
521
|
+
if (outputConfigFormat) body.text = { format: outputConfigFormat };
|
|
460
522
|
let cacheKeySource: ClaudeCacheKeySource = null;
|
|
461
523
|
if (isRec(raw.metadata) && typeof raw.metadata.user_id === "string") {
|
|
462
524
|
body.user = raw.metadata.user_id;
|
|
@@ -494,7 +556,14 @@ export function anthropicToResponsesTranslation(raw: unknown, cc?: OcxClaudeCode
|
|
|
494
556
|
const thinking = raw.thinking;
|
|
495
557
|
const outputConfigEffort = effortFromOutputConfig(raw.output_config);
|
|
496
558
|
const thinkingDisabled = isRec(thinking) && thinking.type === "disabled";
|
|
497
|
-
if (
|
|
559
|
+
if (thinkingDisabled) {
|
|
560
|
+
// An explicit "disabled" is an instruction, not an absence. Dropping it made this
|
|
561
|
+
// indistinguishable from a request that never mentioned thinking — and for models that
|
|
562
|
+
// think by default, omission means thinking is ON, sharing the caller's max_tokens (#545).
|
|
563
|
+
// `none` is the effort disable sentinel. It is not a valid OpenAI summary
|
|
564
|
+
// value, so do not attach the similarly named internal catalog sentinel.
|
|
565
|
+
body.reasoning = { effort: "none" };
|
|
566
|
+
} else if (isRec(thinking) || outputConfigEffort !== undefined) {
|
|
498
567
|
const reasoning: Rec = { summary: "auto" };
|
|
499
568
|
if (outputConfigEffort !== undefined) {
|
|
500
569
|
// Adaptive wire: /effort arrives as output_config.effort (devlog 080).
|
package/src/claude/model-info.ts
CHANGED
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
* - created_at is a fixed constant; max_input_tokens is authoritative-or-null;
|
|
16
16
|
* max_tokens is always null (no authoritative output limit exists proxy-side).
|
|
17
17
|
*/
|
|
18
|
-
import { catalogModelEfforts, nativeEffortClamp, nativeOpenAiContextWindow, type CatalogModel } from "../codex/catalog";
|
|
18
|
+
import { catalogModelEfforts, nativeEffortClamp, nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, type CatalogModel, type NativeContextLimitsInput } from "../codex/catalog";
|
|
19
19
|
import { claudeCodeAlias, claudeCodeNativeAlias } from "./alias";
|
|
20
20
|
import { desktop3pAlias } from "./desktop-3p";
|
|
21
|
-
import { AUTO_CONTEXT_OFF,
|
|
21
|
+
import { AUTO_CONTEXT_OFF, type AutoContextMode } from "./context-windows";
|
|
22
22
|
|
|
23
23
|
const MODEL_INFO_CREATED_AT = "2026-01-01T00:00:00Z";
|
|
24
24
|
const ANTHROPIC_EFFORT_RUNGS = new Set(["low", "medium", "high", "xhigh", "max"]);
|
|
@@ -108,32 +108,47 @@ export function buildAnthropicModelInfos(
|
|
|
108
108
|
auto: AutoContextMode = AUTO_CONTEXT_OFF,
|
|
109
109
|
idStyle: AnthropicIdStyle = "desktop3p",
|
|
110
110
|
aliasForRoute: (provider: string, modelId: string) => string = desktop3pAlias,
|
|
111
|
+
nativeContextCap?: NativeContextLimitsInput,
|
|
111
112
|
): AnthropicModelInfo[] {
|
|
112
113
|
const out: AnthropicModelInfo[] = [];
|
|
113
114
|
const seen = new Set<string>();
|
|
114
115
|
// [1m] picker variant (devlog 260712 B1): Claude Code accounts exactly 1M for ids
|
|
115
116
|
// carrying the marker (2.1.207 binary: /\[1m\]/i → 1e6, compaction preserved), so
|
|
116
|
-
// models with an authoritative >=1M window get a second selectable row
|
|
117
|
-
// auto-context
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
const push1mVariant = (base: AnthropicModelInfo, contextWindow: number | undefined,
|
|
121
|
-
|
|
117
|
+
// ONLY models with an authoritative >=1M window get a second selectable row —
|
|
118
|
+
// the auto-context widening that let a 372K route carry the marker (and be
|
|
119
|
+
// over-filled) is the #854 defect and does not come back. Guards (audit R1#11):
|
|
120
|
+
// same dedupe set, never double-suffix.
|
|
121
|
+
const push1mVariant = (base: AnthropicModelInfo, contextWindow: number | undefined, maxInputTokens?: number) => {
|
|
122
|
+
// The [1m] marker makes Claude Code account 1e6 tokens for the row, so it
|
|
123
|
+
// may only name models whose AUTHORITATIVE effective window is >= 1M —
|
|
124
|
+
// never the auto-context widening, which would mark a 372K route and have
|
|
125
|
+
// Claude Code over-fill it (the #854 defect).
|
|
126
|
+
if (contextWindow === undefined || contextWindow < ONE_MILLION) return;
|
|
122
127
|
if (base.id.includes("[1m]")) return;
|
|
123
128
|
const id = `${base.id}[1m]`;
|
|
124
129
|
if (seen.has(id)) return;
|
|
125
130
|
seen.add(id);
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
131
|
+
// The marker fixes Claude Code's accounting at 1e6, but a model may accept less input
|
|
132
|
+
// than that — a routed GPT-5.6 row runs a 1,050,000 window while refusing past 922,000
|
|
133
|
+
// (measured — see devlog/_plan/260817_native_gpt56_1m_context/001_measurement_evidence.md).
|
|
134
|
+
// Advertising the flat 1e6 there would invite mid-session context_length_exceeded, so the
|
|
135
|
+
// variant reports whichever of the two is smaller.
|
|
136
|
+
const advertised = typeof maxInputTokens === "number" && maxInputTokens > 0
|
|
137
|
+
? Math.min(ONE_MILLION, maxInputTokens)
|
|
138
|
+
: ONE_MILLION;
|
|
139
|
+
out.push({ ...base, id, display_name: `${base.display_name} · 1M`, max_input_tokens: advertised });
|
|
129
140
|
};
|
|
130
141
|
for (const slug of nativeSlugs) {
|
|
131
142
|
const id = idStyle === "readable" ? claudeCodeNativeAlias(slug) : aliasForRoute("native", slug);
|
|
132
143
|
if (seen.has(id)) continue;
|
|
133
144
|
seen.add(id);
|
|
134
|
-
const
|
|
145
|
+
const nativeWindow = nativeOpenAiContextWindow(slug, nativeContextCap);
|
|
146
|
+
const nativeMaxInput = nativeOpenAiMaxInputTokens(slug, nativeContextCap);
|
|
147
|
+
// max_input_tokens is an INPUT limit, so it follows the measured input ceiling rather
|
|
148
|
+
// than the total window whenever the model publishes one.
|
|
149
|
+
const info = modelInfo(id, `${slug} (native)`, nativeEffectiveLadder(slug), true, nativeMaxInput ?? nativeWindow);
|
|
135
150
|
out.push(info);
|
|
136
|
-
push1mVariant(info,
|
|
151
|
+
push1mVariant(info, nativeWindow, nativeMaxInput);
|
|
137
152
|
}
|
|
138
153
|
for (const m of routedModels) {
|
|
139
154
|
const id = idStyle === "readable" ? claudeCodeAlias(m.provider, m.id) : aliasForRoute(m.provider, m.id);
|
|
@@ -141,11 +156,19 @@ export function buildAnthropicModelInfos(
|
|
|
141
156
|
seen.add(id);
|
|
142
157
|
const ladder = Array.isArray(m.reasoningEfforts) ? m.reasoningEfforts : [];
|
|
143
158
|
const imageInput = Array.isArray(m.inputModalities) ? m.inputModalities.includes("image") : false;
|
|
144
|
-
|
|
159
|
+
// max_input_tokens is an input limit, so a row that publishes a lower input ceiling than
|
|
160
|
+
// its window (native GPT-5.6 forwarded through a provider: 922k under 1.05M) reports the
|
|
161
|
+
// ceiling. Rows without one keep reporting the window, as before.
|
|
162
|
+
const routedMaxInput = typeof m.maxInputTokens === "number" && m.maxInputTokens > 0
|
|
163
|
+
? (typeof m.contextWindow === "number" && m.contextWindow > 0
|
|
164
|
+
? Math.min(m.maxInputTokens, m.contextWindow)
|
|
165
|
+
: m.maxInputTokens)
|
|
166
|
+
: undefined;
|
|
167
|
+
const info = modelInfo(id, `${m.id} (${m.provider})`, ladder, imageInput, routedMaxInput ?? m.contextWindow);
|
|
145
168
|
out.push(info);
|
|
146
169
|
// Anthropic passthrough guard (audit 021 #3): never auto-widen canonical claude
|
|
147
170
|
// routes — only a genuine >=1M window earns the variant row there.
|
|
148
|
-
push1mVariant(info, m.contextWindow,
|
|
171
|
+
push1mVariant(info, m.contextWindow, routedMaxInput);
|
|
149
172
|
}
|
|
150
173
|
return out;
|
|
151
174
|
}
|