@iislee/opencodex 2.11.0 → 2.35.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 +117 -22
- package/bin/ocx.mjs +245 -88
- package/bin/package-main.mjs +1 -1
- package/gui/dist/assets/index-Be1sDpWw.css +1 -0
- package/gui/dist/assets/index-D4OKgUV4.js +114 -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 +21 -10
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +475 -62
- package/src/adapters/base.ts +82 -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 +637 -0
- package/src/adapters/cursor/call-id.ts +44 -0
- package/src/adapters/cursor/catalog.ts +541 -0
- package/src/adapters/cursor/checkpoint-store.ts +308 -0
- package/src/adapters/cursor/cursor-errors.ts +144 -6
- package/src/adapters/cursor/discovery.ts +122 -14
- package/src/adapters/cursor/effort-map.ts +106 -4
- package/src/adapters/cursor/envelope-echo.ts +290 -0
- 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 +180 -59
- package/src/adapters/cursor/live-transport.ts +623 -170
- package/src/adapters/cursor/message-mapper.ts +4 -1
- package/src/adapters/cursor/native-exec-common.ts +23 -2
- package/src/adapters/cursor/native-exec-desktop.ts +23 -0
- 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 +5 -3
- package/src/adapters/cursor/native-exec.ts +121 -14
- package/src/adapters/cursor/protobuf-events.ts +829 -11
- package/src/adapters/cursor/protobuf-request.ts +447 -75
- package/src/adapters/cursor/request-builder.ts +271 -35
- package/src/adapters/cursor/tool-definitions.ts +252 -12
- package/src/adapters/cursor/tool-result-normalize.ts +115 -0
- package/src/adapters/cursor/transport.ts +22 -0
- package/src/adapters/cursor/types.ts +48 -1
- package/src/adapters/cursor.ts +336 -39
- package/src/adapters/exec-tool-result-normalize.ts +99 -0
- package/src/adapters/google-antigravity-replay.ts +713 -41
- package/src/adapters/google-antigravity-wire.ts +48 -10
- package/src/adapters/google-errors.ts +44 -12
- 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 +742 -86
- package/src/adapters/identity.ts +39 -6
- package/src/adapters/image.ts +1 -1
- package/src/adapters/kiro-constants.ts +27 -0
- 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 +65 -17
- package/src/adapters/kiro.ts +270 -73
- package/src/adapters/mimo-free.ts +17 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1377 -344
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +1164 -64
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/run-turn-queue.ts +36 -1
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +105 -21
- package/src/adapters/xai-tool-schema.ts +436 -0
- package/src/adapters/xai-web-search.ts +186 -0
- package/src/bridge.ts +512 -92
- package/src/chat/inbound.ts +57 -20
- package/src/chat/outbound.ts +97 -33
- package/src/claude/agents-inject.ts +40 -10
- package/src/claude/context-windows.ts +37 -14
- 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 +88 -21
- package/src/cli/access.ts +46 -3
- package/src/cli/account-api.ts +150 -19
- package/src/cli/account-auth.ts +33 -6
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +648 -28
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +97 -19
- package/src/cli/agent.ts +53 -2
- package/src/cli/alias.ts +66 -0
- package/src/cli/capabilities-command.ts +94 -0
- package/src/cli/capabilities.ts +496 -0
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +60 -15
- package/src/cli/claude.ts +129 -35
- 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 +821 -0
- package/src/cli/doctor.ts +440 -56
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +46 -20
- package/src/cli/help.ts +34 -274
- package/src/cli/index.ts +417 -528
- package/src/cli/init.ts +5 -17
- package/src/cli/inspect.ts +230 -0
- 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 +130 -2
- package/src/cli/models.ts +118 -16
- package/src/cli/observe.ts +123 -11
- package/src/cli/opencode.ts +4 -2
- package/src/cli/provider-runtime.ts +34 -3
- package/src/cli/provider.ts +25 -3
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +476 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +57 -10
- package/src/cli/star-prompt.ts +71 -15
- package/src/cli/status.ts +51 -4
- package/src/cli/storage.ts +234 -0
- package/src/cli/system-command.ts +16 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +153 -6
- package/src/cli/usage-report.ts +184 -0
- package/src/cli/v2.ts +137 -18
- package/src/cli/version-skew.ts +46 -0
- package/src/cli.ts +1 -1
- package/src/clients/config-export.ts +1442 -23
- package/src/clients/effective-status.ts +30 -2
- package/src/clients/probes/cline.ts +81 -0
- package/src/codex/account-label.ts +35 -1
- package/src/codex/account-lifecycle.ts +130 -13
- package/src/codex/account-namespaces.ts +49 -3
- package/src/codex/account-pause.ts +2 -1
- package/src/codex/account-priority.ts +84 -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 +570 -107
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +893 -246
- package/src/codex/auth-collision.ts +5 -3
- package/src/codex/auth-context.ts +348 -32
- package/src/codex/autostart-health.ts +24 -1
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +86 -10
- package/src/codex/catalog/bundled.ts +331 -33
- package/src/codex/catalog/effort.ts +138 -32
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +555 -45
- package/src/codex/catalog/native-models.ts +75 -0
- package/src/codex/catalog/parsing.ts +269 -30
- package/src/codex/catalog/provider-fetch.ts +1626 -144
- package/src/codex/catalog/sync.ts +1576 -187
- 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 +386 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +676 -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/desktop-app-restart.ts +355 -0
- package/src/codex/features.ts +636 -39
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +436 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-manifest.ts +112 -0
- package/src/codex/history-migration-guardian.ts +30 -24
- package/src/codex/history-provider.ts +1016 -235
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +223 -0
- package/src/codex/inject-coordination.ts +373 -0
- package/src/codex/inject.ts +1114 -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 +81 -0
- package/src/codex/journal.ts +66 -4
- package/src/codex/log-guard/inspect.ts +524 -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 +360 -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 +622 -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 +675 -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 +1313 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/prompt-text-probe.ts +238 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +264 -21
- package/src/codex/refresh.ts +11 -2
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +514 -94
- package/src/codex/runtime.ts +159 -38
- package/src/codex/shim.ts +1065 -31
- package/src/codex/subagent-model-fallback.ts +437 -43
- package/src/codex/sync.ts +191 -2
- package/src/codex/transition-state.ts +720 -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 +47 -0
- package/src/combos/index.ts +4 -0
- package/src/combos/request.ts +32 -0
- package/src/combos/types.ts +91 -9
- package/src/compatibility/index.ts +26 -0
- package/src/compatibility/manifest.ts +253 -0
- package/src/compatibility/openai-responses.ts +121 -0
- package/src/config/atomic-write.ts +219 -0
- package/src/config/paths.ts +40 -0
- package/src/config/process-state.ts +309 -0
- package/src/config/provider-name.ts +24 -0
- package/src/config/provider-validation.ts +177 -0
- package/src/config/rebase-provenance.ts +68 -0
- package/src/config.ts +1713 -709
- package/src/generated/compatibility-version.json +3324 -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 +157 -33
- package/src/images/plan.ts +24 -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-policy.ts +160 -0
- package/src/integrations/ownership.ts +155 -0
- package/src/integrations/registry.ts +166 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +433 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +715 -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/admin-secrets.ts +24 -0
- package/src/lib/app-owned-memory-stores.ts +22 -0
- package/src/lib/bounded-body.ts +167 -11
- 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 +26 -2
- package/src/lib/destination-policy.ts +65 -1
- package/src/lib/errors.ts +80 -5
- 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/package-tree-integrity.ts +101 -0
- package/src/lib/pinned-http.ts +145 -26
- package/src/lib/process-control.ts +6 -2
- 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/service-secrets.ts +15 -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 +253 -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 +30 -4
- package/src/oauth/chatgpt.ts +12 -1
- package/src/oauth/cline.ts +203 -0
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +46 -5
- package/src/oauth/generic-account-failover.ts +231 -0
- package/src/oauth/google-antigravity.ts +35 -3
- package/src/oauth/health.ts +20 -12
- package/src/oauth/index.ts +462 -71
- package/src/oauth/key-providers.ts +25 -0
- package/src/oauth/kimi.ts +25 -3
- package/src/oauth/kiro.ts +95 -6
- package/src/oauth/local-token-detect.ts +13 -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/open-browser-choice.ts +26 -0
- package/src/oauth/store.ts +133 -26
- package/src/oauth/token-guardian.ts +9 -3
- package/src/oauth/types.ts +15 -0
- 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/auto-compact-budget.ts +65 -0
- package/src/providers/base-url-choices.ts +10 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +176 -0
- package/src/providers/context-cap.ts +26 -8
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/default-aliases.ts +65 -0
- package/src/providers/derive.ts +281 -6
- package/src/providers/fastwire.ts +507 -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 +35 -2
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +115 -22
- package/src/providers/model-presets.ts +119 -0
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/new-model-policy.ts +146 -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 +30 -0
- package/src/providers/quota.ts +1379 -40
- package/src/providers/registry.ts +1545 -112
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +94 -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 +32 -4
- package/src/reasoning-effort.ts +68 -3
- package/src/responses/apply-patch-envelope.ts +63 -0
- package/src/responses/code-mode-helper-compat.ts +50 -0
- package/src/responses/compaction.ts +26 -1
- package/src/responses/custom-tool-compat.ts +384 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +435 -0
- package/src/responses/parser.ts +225 -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 +504 -0
- package/src/responses/schema.ts +12 -2
- package/src/responses/spill-store.ts +75 -10
- package/src/responses/state.ts +659 -31
- package/src/responses/thought-signature-replay.ts +364 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/responses/turn-termination.ts +107 -0
- package/src/router.ts +405 -31
- package/src/routing/analytics.ts +379 -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 +155 -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 +289 -48
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +154 -72
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +445 -0
- package/src/server/claude-messages.ts +160 -44
- 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 +1021 -190
- package/src/server/lifecycle.ts +336 -14
- 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 +433 -116
- package/src/server/management/api-key-usage.ts +31 -5
- package/src/server/management/body.ts +6 -0
- package/src/server/management/codex-prompt-routes.ts +570 -0
- package/src/server/management/combo-routes.ts +64 -25
- package/src/server/management/config-routes.ts +511 -51
- package/src/server/management/context.ts +89 -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 +127 -52
- package/src/server/management/model-routes.ts +461 -133
- package/src/server/management/model-rows.ts +167 -0
- package/src/server/management/native-integration-routes.ts +770 -0
- package/src/server/management/oauth-account-routes.ts +90 -8
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +836 -159
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/route-registry.ts +332 -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 +289 -33
- 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 +126 -23
- package/src/server/management-auth.ts +220 -5
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/port-reclaim.ts +1 -1
- package/src/server/ports.ts +41 -1
- package/src/server/proxy-liveness.ts +161 -10
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +221 -54
- package/src/server/relay.ts +479 -87
- package/src/server/request-decompress.ts +113 -6
- package/src/server/request-log-conversation.ts +51 -0
- package/src/server/request-log.ts +298 -31
- 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/codex-auth-error.ts +55 -0
- package/src/server/responses/collaboration.ts +239 -36
- package/src/server/responses/combo-stream-preflight.ts +178 -0
- package/src/server/responses/compact.ts +444 -72
- package/src/server/responses/core.ts +3579 -436
- package/src/server/responses/empty-completion-guard.ts +333 -0
- package/src/server/responses/encrypted-payload.ts +62 -39
- package/src/server/responses/fetch-helpers.ts +89 -99
- package/src/server/responses/input-admission.ts +187 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/passthrough-error.ts +33 -9
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +343 -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 +381 -0
- package/src/server/responses-custom-tool-repair.ts +363 -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 +363 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +376 -0
- package/src/server/responses.ts +18 -2
- package/src/server/search.ts +78 -13
- package/src/server/sse-frame-buffer.ts +319 -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 +53 -40
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +1153 -94
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/storage/cleanup.ts +2 -2
- package/src/storage/policy-job.ts +14 -4
- package/src/storage/policy.ts +88 -23
- 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 +911 -0
- package/src/types/provider.ts +614 -0
- package/src/types/request.ts +397 -0
- package/src/types/tools.ts +236 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +107 -1237
- package/src/update/index.ts +37 -23
- package/src/update/job.ts +445 -68
- 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 +266 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/expected-prices.ts +287 -16
- package/src/usage/log.ts +666 -50
- package/src/usage/summary.ts +388 -17
- 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 +27 -16
- 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 +119 -0
- package/src/web-search/executor.ts +21 -6
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +150 -15
- package/src/web-search/loop.ts +284 -54
- 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/cli/models.ts
CHANGED
|
@@ -5,15 +5,77 @@ import { randomUUID } from "node:crypto";
|
|
|
5
5
|
import { createInterface } from "node:readline/promises";
|
|
6
6
|
import { syncModelsToCodex } from "../codex/sync";
|
|
7
7
|
import { hasOwnProvider, isValidProviderName, loadConfig, saveConfig } from "../config";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
canonicalizeReasoningEfforts,
|
|
10
|
+
configuredReasoningEfforts,
|
|
11
|
+
isDeclaredReasoningEffort,
|
|
12
|
+
modelRecordValue,
|
|
13
|
+
} from "../reasoning-effort";
|
|
14
|
+
import { encodedModelIdCollides, resolveSlugSelection, routedSlug } from "../providers/slug-codec";
|
|
15
|
+
import { knownModelIdsForProvider } from "../router";
|
|
9
16
|
import { findLiveProxy } from "../server/proxy-liveness";
|
|
10
|
-
import type
|
|
17
|
+
import { modelInList, type OcxConfig, type OcxCustomModel } from "../types";
|
|
11
18
|
|
|
12
|
-
const ADD_USAGE = "Usage: ocx models add <provider> <modelId> [--display-name <name>] [--context-window <tokens>] [--modalities text,image,audio]";
|
|
19
|
+
const ADD_USAGE = "Usage: ocx models add <provider> <modelId> [--display-name <name>] [--context-window <tokens>] [--modalities text,image,audio] [--reasoning-efforts <none,minimal,low,medium,high,xhigh,max,ultra>] [--default-reasoning-effort <level>]";
|
|
13
20
|
const REMOVE_USAGE = "Usage: ocx models remove <customId|provider/modelId> [--yes]";
|
|
14
21
|
const LIST_CUSTOM_USAGE = "Usage: ocx models list-custom [--json]";
|
|
15
22
|
const ALLOWED_MODALITIES = new Set(["text", "image", "audio"]);
|
|
16
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Parse and validate the reasoning flags shared by `ocx models add` (offline path).
|
|
26
|
+
* "-" means "inherit" and omits the field entirely; "" means an explicit empty ladder
|
|
27
|
+
* ("no reasoning" override, the same state the dashboard stores for the toggle-off
|
|
28
|
+
* checkbox set). Malformed CSV like `low,,high` or `,,` is rejected instead of being
|
|
29
|
+
* silently normalized. Values are canonicalized into Codex ladder order so the stored
|
|
30
|
+
* config matches what the API stores.
|
|
31
|
+
*/
|
|
32
|
+
export function parseReasoningArgs(
|
|
33
|
+
reasoningEffortsValue: string | undefined,
|
|
34
|
+
defaultEffortValue: string | undefined,
|
|
35
|
+
): { reasoningEfforts?: string[]; defaultReasoningEffort?: string; error?: string } {
|
|
36
|
+
if (reasoningEffortsValue === undefined && defaultEffortValue === undefined) return {};
|
|
37
|
+
let reasoningEfforts: string[] | undefined;
|
|
38
|
+
if (reasoningEffortsValue !== undefined) {
|
|
39
|
+
const trimmed = reasoningEffortsValue.trim();
|
|
40
|
+
if (trimmed === "-") {
|
|
41
|
+
reasoningEfforts = undefined;
|
|
42
|
+
} else if (trimmed === "") {
|
|
43
|
+
// Explicit no-reasoning override, exactly like the API's [] / the dashboard's
|
|
44
|
+
// uncheck-all state.
|
|
45
|
+
reasoningEfforts = [];
|
|
46
|
+
} else {
|
|
47
|
+
const parts = trimmed.split(",").map(value => value.trim());
|
|
48
|
+
if (parts.some(part => part === "")) {
|
|
49
|
+
return { error: "--reasoning-efforts must be comma-separated values from none, minimal, low, medium, high, xhigh, max, ultra (\"\" for no reasoning, \"-\" to inherit)" };
|
|
50
|
+
}
|
|
51
|
+
const invalid = parts.filter(value => !isDeclaredReasoningEffort(value));
|
|
52
|
+
if (invalid.length > 0) {
|
|
53
|
+
return { error: `unsupported reasoning effort: ${invalid.join(", ")} (allowed: none, minimal, low, medium, high, xhigh, max, ultra)` };
|
|
54
|
+
}
|
|
55
|
+
reasoningEfforts = canonicalizeReasoningEfforts(parts);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
let defaultReasoningEffort: string | undefined;
|
|
59
|
+
if (defaultEffortValue !== undefined) {
|
|
60
|
+
const trimmed = defaultEffortValue.trim();
|
|
61
|
+
if (trimmed === "-") {
|
|
62
|
+
defaultReasoningEffort = undefined;
|
|
63
|
+
} else {
|
|
64
|
+
if (!isDeclaredReasoningEffort(trimmed)) {
|
|
65
|
+
return { error: `unsupported reasoning effort: ${trimmed} (allowed: none, minimal, low, medium, high, xhigh, max, ultra)` };
|
|
66
|
+
}
|
|
67
|
+
if (!reasoningEfforts || reasoningEfforts.length === 0) {
|
|
68
|
+
return { error: "--default-reasoning-effort requires --reasoning-efforts" };
|
|
69
|
+
}
|
|
70
|
+
if (!reasoningEfforts.includes(trimmed)) {
|
|
71
|
+
return { error: `--default-reasoning-effort "${trimmed}" is not in the declared reasoning efforts` };
|
|
72
|
+
}
|
|
73
|
+
defaultReasoningEffort = trimmed;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return { reasoningEfforts, defaultReasoningEffort };
|
|
77
|
+
}
|
|
78
|
+
|
|
17
79
|
interface ModelEntry {
|
|
18
80
|
provider: string;
|
|
19
81
|
model: string;
|
|
@@ -34,22 +96,34 @@ function collectModels(config: OcxConfig, providerFilter?: string): ModelEntry[]
|
|
|
34
96
|
const seen = new Set<string>();
|
|
35
97
|
const contextWindows = prov.modelContextWindows ?? {};
|
|
36
98
|
const inputModalities = prov.modelInputModalities ?? {};
|
|
37
|
-
const reasoningEfforts = prov.modelReasoningEfforts ?? {};
|
|
38
99
|
const globalContext = prov.contextWindow ?? null;
|
|
39
100
|
|
|
40
101
|
const addModel = (model: string, isDefault: boolean) => {
|
|
41
102
|
if (seen.has(model)) return;
|
|
42
103
|
seen.add(model);
|
|
43
104
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
105
|
+
// Resolve exactly as the runtime does, or this command reports capabilities the
|
|
106
|
+
// proxy will not honour: `isModelTextOnly` matches noVisionModels with modelInList
|
|
107
|
+
// and reads modelInputModalities with modelRecordValue, so a `gpt-oss` entry covers
|
|
108
|
+
// `gpt-oss:120b`. A bare lookup reported that model as unclassified on every field.
|
|
109
|
+
// noVisionModels is checked first because `isModelTextOnly` returns true on that
|
|
110
|
+
// match before it ever reads modelInputModalities: a `gpt-oss` noVision entry beats
|
|
111
|
+
// an exact `gpt-oss:120b` entry that lists "image", and the proxy rejects the image.
|
|
112
|
+
const noVision = modelInList(prov.noVisionModels, model);
|
|
113
|
+
const modalities = noVision ? ["text"] : (modelRecordValue(inputModalities, model) ?? null);
|
|
114
|
+
// Same reason, for the ladder: `configuredReasoningEfforts` is what the catalog
|
|
115
|
+
// (`provider-fetch`) and the effort cap (`effort-policy`) resolve through, and it
|
|
116
|
+
// does three things this expression did not — it returns [] for a noReasoningModels
|
|
117
|
+
// match, drops levels Codex does not declare, and re-adds tiers the wire map proves
|
|
118
|
+
// the model emits. Restating two of its five lines here reported a ladder the proxy
|
|
119
|
+
// strips, and unsanitized junk as a supported level.
|
|
120
|
+
const efforts = configuredReasoningEfforts(prov, model) ?? null;
|
|
47
121
|
|
|
48
122
|
entries.push({
|
|
49
123
|
provider: provName,
|
|
50
124
|
model,
|
|
51
125
|
isDefault,
|
|
52
|
-
contextWindow: contextWindows
|
|
126
|
+
contextWindow: modelRecordValue(contextWindows, model) ?? globalContext,
|
|
53
127
|
inputModalities: modalities,
|
|
54
128
|
reasoningEfforts: efforts,
|
|
55
129
|
});
|
|
@@ -102,9 +176,13 @@ function rejectUnexpectedArgs(args: string[], usage: string): void {
|
|
|
102
176
|
async function syncCustomModelsIfLive(): Promise<void> {
|
|
103
177
|
const live = await findLiveProxy();
|
|
104
178
|
if (!live) return;
|
|
105
|
-
await syncModelsToCodex(live.port).catch(error => {
|
|
179
|
+
const synced = await syncModelsToCodex(live.port).catch(error => {
|
|
106
180
|
console.error(`Warning: custom model saved, but catalog sync failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
181
|
+
return null;
|
|
107
182
|
});
|
|
183
|
+
if (synced?.status === "skipped") {
|
|
184
|
+
console.log("Custom model saved; Codex integration is OFF, so its catalog was not changed.");
|
|
185
|
+
}
|
|
108
186
|
}
|
|
109
187
|
|
|
110
188
|
async function handleCustomAdd(args: string[]): Promise<void> {
|
|
@@ -114,11 +192,12 @@ async function handleCustomAdd(args: string[]): Promise<void> {
|
|
|
114
192
|
const displayNameValue = consumeFlagValue(rest, "--display-name");
|
|
115
193
|
const contextWindowValue = consumeFlagValue(rest, "--context-window");
|
|
116
194
|
const modalitiesValue = consumeFlagValue(rest, "--modalities");
|
|
195
|
+
const reasoningEffortsValue = consumeFlagValue(rest, "--reasoning-efforts");
|
|
196
|
+
const defaultEffortValue = consumeFlagValue(rest, "--default-reasoning-effort");
|
|
117
197
|
rejectUnexpectedArgs(rest, ADD_USAGE);
|
|
118
198
|
|
|
119
199
|
if (!provider || !modelId) fail("provider and modelId are required", ADD_USAGE);
|
|
120
200
|
if (!isValidProviderName(provider)) fail(`invalid provider name "${provider}"`);
|
|
121
|
-
if (modelId.includes("/")) fail("modelId must not contain /");
|
|
122
201
|
|
|
123
202
|
const config = loadConfig();
|
|
124
203
|
if (!hasOwnProvider(config.providers, provider)) {
|
|
@@ -146,11 +225,18 @@ async function handleCustomAdd(args: string[]): Promise<void> {
|
|
|
146
225
|
inputModalities = [...new Set(inputModalities)];
|
|
147
226
|
}
|
|
148
227
|
|
|
228
|
+
const parsed = parseReasoningArgs(reasoningEffortsValue, defaultEffortValue);
|
|
229
|
+
if (parsed.error) fail(parsed.error);
|
|
230
|
+
|
|
149
231
|
const existing = config.customModels ?? [];
|
|
150
232
|
const slug = routedSlug(provider, modelId);
|
|
151
233
|
if (existing.some(model => routedSlug(model.provider, model.modelId) === slug)) {
|
|
152
234
|
fail(`custom model "${slug}" already exists`);
|
|
153
235
|
}
|
|
236
|
+
const known = knownModelIdsForProvider(provider, config.providers[provider], config);
|
|
237
|
+
if (encodedModelIdCollides(modelId, known)) {
|
|
238
|
+
fail(`custom model "${slug}" is ambiguous; it encodes to an existing model id`);
|
|
239
|
+
}
|
|
154
240
|
|
|
155
241
|
const entry: OcxCustomModel = {
|
|
156
242
|
id: randomUUID(),
|
|
@@ -159,6 +245,8 @@ async function handleCustomAdd(args: string[]): Promise<void> {
|
|
|
159
245
|
...(displayName ? { displayName } : {}),
|
|
160
246
|
...(contextWindow ? { contextWindow } : {}),
|
|
161
247
|
...(inputModalities ? { inputModalities } : {}),
|
|
248
|
+
...(parsed.reasoningEfforts ? { reasoningEfforts: parsed.reasoningEfforts } : {}),
|
|
249
|
+
...(parsed.defaultReasoningEffort ? { defaultReasoningEffort: parsed.defaultReasoningEffort } : {}),
|
|
162
250
|
addedAt: new Date().toISOString(),
|
|
163
251
|
};
|
|
164
252
|
config.customModels = [...existing, entry];
|
|
@@ -189,10 +277,22 @@ async function handleCustomRemove(args: string[]): Promise<void> {
|
|
|
189
277
|
|
|
190
278
|
const config = loadConfig();
|
|
191
279
|
const existing = config.customModels ?? [];
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
280
|
+
// Slug matching goes through the shared resolver so this command sees the same collision
|
|
281
|
+
// class catalog filtering and persisted sync see (#2491). `slugEquals` compares the raw and
|
|
282
|
+
// encoded spellings of ONE id, so a selector written in the native slash form matched only
|
|
283
|
+
// that row while the dash form matched both — the two relations disagreed on the same
|
|
284
|
+
// config. Removal stays exact-or-refuse: an ambiguous selector still aborts below, which is
|
|
285
|
+
// the right default for a destructive command.
|
|
286
|
+
const matchingIndexes = existing.flatMap((model, index) => {
|
|
287
|
+
if (!target.includes("/")) return model.id === target ? [index] : [];
|
|
288
|
+
const resolved = resolveSlugSelection(model.provider, target, [model.modelId]);
|
|
289
|
+
return resolved.matched.length > 0 ? [index] : [];
|
|
290
|
+
});
|
|
291
|
+
if (matchingIndexes.length === 0) fail(`custom model "${target}" not found`);
|
|
292
|
+
if (matchingIndexes.length > 1) {
|
|
293
|
+
fail(`custom model selector "${target}" is ambiguous; use the custom model id`);
|
|
294
|
+
}
|
|
295
|
+
const index = matchingIndexes[0]!;
|
|
196
296
|
|
|
197
297
|
const model = existing[index];
|
|
198
298
|
if (!confirmed && !(await confirmCustomRemoval(model))) {
|
|
@@ -214,12 +314,14 @@ function customModelCells(model: OcxCustomModel): string[] {
|
|
|
214
314
|
model.displayName ?? "-",
|
|
215
315
|
model.contextWindow ? `${Math.round(model.contextWindow / 1000)}k` : "-",
|
|
216
316
|
model.inputModalities?.join(",") ?? "-",
|
|
317
|
+
model.reasoningEfforts?.join(",") ?? "-",
|
|
318
|
+
model.defaultReasoningEffort ?? "-",
|
|
217
319
|
];
|
|
218
320
|
}
|
|
219
321
|
|
|
220
322
|
function printCustomModelGroup(provider: string, models: OcxCustomModel[]): void {
|
|
221
323
|
const rows = models.map(customModelCells);
|
|
222
|
-
const headers = ["ID", "MODEL", "DISPLAY NAME", "CONTEXT", "MODALITIES"];
|
|
324
|
+
const headers = ["ID", "MODEL", "DISPLAY NAME", "CONTEXT", "MODALITIES", "EFFORTS", "DEFAULT EFFORT"];
|
|
223
325
|
const widths = headers.map((header, column) => Math.max(header.length, ...rows.map(row => row[column].length)));
|
|
224
326
|
const line = (cells: string[]) => cells.map((cell, column) => cell.padEnd(widths[column])).join(" ");
|
|
225
327
|
console.log(`${provider}:`);
|
|
@@ -326,7 +428,7 @@ export async function handleModels(args: string[]): Promise<void> {
|
|
|
326
428
|
handleCustomList(rest);
|
|
327
429
|
return;
|
|
328
430
|
}
|
|
329
|
-
if (["live", "edit", "enable", "disable", "provider", "selected", "context", "shadow"].includes(subcommand ?? "")) {
|
|
431
|
+
if (["live", "edit", "enable", "disable", "provider", "selected", "preset", "context", "shadow"].includes(subcommand ?? "")) {
|
|
330
432
|
const { handleModelsRuntimeCommand } = await import("./models-runtime");
|
|
331
433
|
const code = await handleModelsRuntimeCommand(subcommand!, rest);
|
|
332
434
|
if (code !== null) process.exitCode = code;
|
package/src/cli/observe.ts
CHANGED
|
@@ -10,12 +10,18 @@ import {
|
|
|
10
10
|
takeOption,
|
|
11
11
|
type RuntimeApiDeps,
|
|
12
12
|
} from "./runtime-api";
|
|
13
|
+
import { formatUsageReport } from "./usage-report";
|
|
14
|
+
import { USAGE_RANGES, USAGE_SURFACES } from "../usage/summary";
|
|
13
15
|
|
|
14
16
|
const USAGE = `Usage:
|
|
15
17
|
ocx observe logs [--provider <name>] [--model <id>] [--status <code>]
|
|
16
|
-
[--limit <n>] [--follow] [--json|--jsonl]
|
|
17
|
-
ocx
|
|
18
|
-
ocx
|
|
18
|
+
[--conversation <id>] [--limit <n>] [--follow] [--json|--jsonl]
|
|
19
|
+
ocx logs explain <request-id> [--json]
|
|
20
|
+
ocx logs rebuild-index
|
|
21
|
+
ocx logs index-status
|
|
22
|
+
ocx observe usage [--range <today|1d|7d|30d|all>] [--surface <all|codex|claude|grok>]
|
|
23
|
+
[--provider <name>] [--model <id>] [--json]
|
|
24
|
+
ocx observe storage [codex-logs [status|protect|unprotect|repair|compact] [--mode <compat|quiet>]] [--json]
|
|
19
25
|
ocx observe memory [--json]
|
|
20
26
|
ocx observe debug [--json]
|
|
21
27
|
ocx observe claude-inbound [--limit <n>] [--json]
|
|
@@ -44,7 +50,12 @@ function formatLog(row: LogEntry): string {
|
|
|
44
50
|
const route = [row.provider, row.model].filter(Boolean).join("/");
|
|
45
51
|
const status = row.status ?? row.statusCode ?? "?";
|
|
46
52
|
const duration = row.durationMs !== undefined ? `${String(row.durationMs)}ms` : "";
|
|
47
|
-
|
|
53
|
+
// The conversation id is shown because a conversation FILTER whose output never names the
|
|
54
|
+
// conversation is hard to trust: an empty result and a wrong-id result look identical (#2704).
|
|
55
|
+
const conversation = typeof row.conversationId === "string" && row.conversationId.length > 0
|
|
56
|
+
? `conv=${row.conversationId}`
|
|
57
|
+
: "";
|
|
58
|
+
return [time, String(status), route, duration, conversation].filter(Boolean).join(" ");
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
async function logs(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
@@ -55,13 +66,16 @@ async function logs(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
|
55
66
|
const provider = takeOption(args, "--provider");
|
|
56
67
|
const model = takeOption(args, "--model");
|
|
57
68
|
const status = takeOption(args, "--status");
|
|
69
|
+
// Both spellings, because the server accepts both (`request-log.ts:1032`) and an operator
|
|
70
|
+
// should not have to remember which one this surface wanted.
|
|
71
|
+
const conversationId = takeOption(args, "--conversation") ?? takeOption(args, "--conversationId");
|
|
58
72
|
const limit = takeIntegerOption(args, "--limit", { min: 1 }) ?? 200;
|
|
59
73
|
rejectArgs(args, USAGE);
|
|
60
74
|
if (wantsJson && wantsJsonl) throw new CliUsageError("--json and --jsonl cannot be combined", USAGE);
|
|
61
75
|
if (follow && wantsJson) throw new CliUsageError("--follow uses --jsonl, not --json", USAGE);
|
|
62
76
|
let seen = new Set<string>();
|
|
63
77
|
do {
|
|
64
|
-
const data = await runtimeRequest(`/api/logs${query({ provider, model, status, limit })}`, {}, deps);
|
|
78
|
+
const data = await runtimeRequest(`/api/logs${query({ provider, model, status, conversationId, limit })}`, {}, deps);
|
|
65
79
|
const rows = logRows(data);
|
|
66
80
|
if (!follow && wantsJson) printData(data, true);
|
|
67
81
|
else {
|
|
@@ -79,16 +93,72 @@ async function logs(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
|
79
93
|
} while (true);
|
|
80
94
|
}
|
|
81
95
|
|
|
96
|
+
async function explain(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
97
|
+
const args = [...argv];
|
|
98
|
+
const requestId = args.shift();
|
|
99
|
+
const wantsJson = takeFlag(args, "--json");
|
|
100
|
+
if (!requestId) throw new CliUsageError("request id is required", USAGE);
|
|
101
|
+
rejectArgs(args, USAGE);
|
|
102
|
+
const encoded = encodeURIComponent(requestId);
|
|
103
|
+
const result = await runtimeRequest(`/api/request-history/${encoded}/route-decision`, {}, deps);
|
|
104
|
+
printData(result, wantsJson, wantsJson ? undefined : [JSON.stringify(result, null, 2)]);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function rebuildIndex(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
108
|
+
const args = [...argv];
|
|
109
|
+
const wantsJson = takeFlag(args, "--json");
|
|
110
|
+
rejectArgs(args, USAGE);
|
|
111
|
+
const { rebuildRequestHistoryIndex } = await import("../routing/history/indexer");
|
|
112
|
+
const meta = await rebuildRequestHistoryIndex();
|
|
113
|
+
if (wantsJson) printData(meta, true);
|
|
114
|
+
else {
|
|
115
|
+
console.log(`Request-history index rebuilt (${meta.dbPath})`);
|
|
116
|
+
console.log(` schema version: ${meta.schemaVersion}`);
|
|
117
|
+
console.log(` indexed rows: ${meta.indexedRows}`);
|
|
118
|
+
console.log(` source size: ${meta.sourceSize} bytes`);
|
|
119
|
+
console.log(` last error: ${meta.lastError ?? "none"}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async function indexStatus(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
124
|
+
const args = [...argv];
|
|
125
|
+
const wantsJson = takeFlag(args, "--json");
|
|
126
|
+
rejectArgs(args, USAGE);
|
|
127
|
+
const { requestHistoryIndexStatus } = await import("../routing/history/indexer");
|
|
128
|
+
const meta = await requestHistoryIndexStatus();
|
|
129
|
+
if (wantsJson) printData(meta, true);
|
|
130
|
+
else {
|
|
131
|
+
console.log(`Request-history index (${meta.dbPath})`);
|
|
132
|
+
console.log(` schema version: ${meta.schemaVersion}`);
|
|
133
|
+
console.log(` indexed rows: ${meta.indexedRows}`);
|
|
134
|
+
console.log(` source size: ${meta.sourceSize} bytes`);
|
|
135
|
+
console.log(` indexed offset: ${meta.indexedOffset} bytes`);
|
|
136
|
+
console.log(` last error: ${meta.lastError ?? "none"}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
82
140
|
async function usage(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
83
141
|
const args = [...argv];
|
|
84
142
|
const wantsJson = takeFlag(args, "--json");
|
|
85
143
|
const range = takeOption(args, "--range") ?? "30d";
|
|
86
144
|
const surface = takeOption(args, "--surface") ?? "all";
|
|
87
|
-
|
|
88
|
-
|
|
145
|
+
const provider = takeOption(args, "--provider");
|
|
146
|
+
const model = takeOption(args, "--model");
|
|
147
|
+
// `1d` is accepted here as well as server-side so the CLI does not reject an
|
|
148
|
+
// alias the API would have understood.
|
|
149
|
+
const ranges = [...USAGE_RANGES, "1d"];
|
|
150
|
+
if (!ranges.includes(range)) throw new CliUsageError(`--range must be one of ${USAGE_RANGES.join(", ")} (1d aliases today)`, USAGE);
|
|
151
|
+
if (!USAGE_SURFACES.includes(surface as (typeof USAGE_SURFACES)[number])) {
|
|
152
|
+
throw new CliUsageError(`--surface must be one of ${USAGE_SURFACES.join(", ")}`, USAGE);
|
|
153
|
+
}
|
|
89
154
|
rejectArgs(args, USAGE);
|
|
90
|
-
const result = await runtimeRequest(`/api/usage${query({ range, surface })}`, {}, deps);
|
|
91
|
-
|
|
155
|
+
const result = await runtimeRequest(`/api/usage${query({ range, surface, provider, model })}`, {}, deps);
|
|
156
|
+
// Built only when it will be printed: JavaScript evaluates arguments before
|
|
157
|
+
// the call, so passing formatUsageReport(...) inline would run the human
|
|
158
|
+
// renderer during --json and let its assumptions affect a path that is meant
|
|
159
|
+
// to bypass it entirely.
|
|
160
|
+
if (wantsJson) printData(result, true);
|
|
161
|
+
else printData(result, false, formatUsageReport(result as Parameters<typeof formatUsageReport>[0]));
|
|
92
162
|
}
|
|
93
163
|
|
|
94
164
|
async function simple(path: string, argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
@@ -100,12 +170,54 @@ async function simple(path: string, argv: string[], deps: RuntimeApiDeps): Promi
|
|
|
100
170
|
printData(result, wantsJson, summaryLines(result));
|
|
101
171
|
}
|
|
102
172
|
|
|
173
|
+
async function storage(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
174
|
+
if (argv[0] !== "codex-logs") {
|
|
175
|
+
await simple("/api/storage", argv, deps);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const args = argv.slice(1);
|
|
180
|
+
const action = args[0] && !args[0].startsWith("-") ? args.shift()! : "status";
|
|
181
|
+
const wantsJson = takeFlag(args, "--json");
|
|
182
|
+
const mode = takeOption(args, "--mode");
|
|
183
|
+
rejectArgs(args, USAGE);
|
|
184
|
+
|
|
185
|
+
let result: unknown;
|
|
186
|
+
if (action === "status") {
|
|
187
|
+
if (mode !== undefined) throw new CliUsageError("--mode is only valid with codex-logs protect", USAGE);
|
|
188
|
+
result = await runtimeRequest("/api/storage/codex-logs", {}, deps);
|
|
189
|
+
} else if (action === "protect") {
|
|
190
|
+
const requestedMode = mode ?? "compat";
|
|
191
|
+
if (requestedMode !== "compat" && requestedMode !== "quiet") {
|
|
192
|
+
throw new CliUsageError("--mode must be compat or quiet", USAGE);
|
|
193
|
+
}
|
|
194
|
+
result = await runtimeRequest("/api/storage/codex-logs/protect", {
|
|
195
|
+
method: "POST",
|
|
196
|
+
headers: { "content-type": "application/json" },
|
|
197
|
+
body: JSON.stringify({ mode: requestedMode }),
|
|
198
|
+
}, deps);
|
|
199
|
+
} else if (action === "unprotect" || action === "repair" || action === "compact") {
|
|
200
|
+
if (mode !== undefined) throw new CliUsageError("--mode is only valid with codex-logs protect", USAGE);
|
|
201
|
+
result = await runtimeRequest(`/api/storage/codex-logs/${action}`, { method: "POST" }, deps);
|
|
202
|
+
} else {
|
|
203
|
+
throw new CliUsageError(`unknown codex-logs action ${action}`, USAGE);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
printData(result, wantsJson, summaryLines(result));
|
|
207
|
+
}
|
|
208
|
+
|
|
103
209
|
export async function handleObserveCommand(argv: string[], deps: RuntimeApiDeps = {}): Promise<number> {
|
|
104
210
|
return runCliAction(async () => {
|
|
105
211
|
const [sub = "logs", ...rest] = argv;
|
|
106
|
-
if (sub === "logs")
|
|
212
|
+
if (sub === "logs") {
|
|
213
|
+
const action = rest[0];
|
|
214
|
+
if (action === "explain") await explain(rest.slice(1), deps);
|
|
215
|
+
else if (action === "rebuild-index") await rebuildIndex(rest.slice(1), deps);
|
|
216
|
+
else if (action === "index-status") await indexStatus(rest.slice(1), deps);
|
|
217
|
+
else await logs(rest, deps);
|
|
218
|
+
}
|
|
107
219
|
else if (sub === "usage") await usage(rest, deps);
|
|
108
|
-
else if (sub === "storage") await
|
|
220
|
+
else if (sub === "storage") await storage(rest, deps);
|
|
109
221
|
else if (sub === "memory") await simple("/api/system/memory", rest, deps);
|
|
110
222
|
else if (sub === "debug") await simple("/api/debug", rest, deps);
|
|
111
223
|
else if (sub === "claude-inbound") await simple("/api/claude/inbound-debug", rest, deps);
|
package/src/cli/opencode.ts
CHANGED
|
@@ -40,6 +40,8 @@ import { loadServiceTokenFromFile, serviceApiTokenFilePath } from "../lib/servic
|
|
|
40
40
|
import { providerCodexAccountMode } from "../providers/registry";
|
|
41
41
|
import { findLiveProxy, probeHostname, type LiveProxy } from "../server/proxy-liveness";
|
|
42
42
|
import type { OcxConfig } from "../types";
|
|
43
|
+
import { withProcessRuntimeProvenance } from "../lib/bun-runtime";
|
|
44
|
+
import { selfLaunchArgv } from "../lib/self-launch-argv";
|
|
43
45
|
|
|
44
46
|
/**
|
|
45
47
|
* The provider-block serializer, its constants, and the config-path helpers now live in
|
|
@@ -493,11 +495,11 @@ async function ensureProxyForOpencode(config: OcxConfig): Promise<LiveProxy | nu
|
|
|
493
495
|
if (live) return live;
|
|
494
496
|
const cfgPort = config.port;
|
|
495
497
|
const pinPort = typeof cfgPort === "number" && cfgPort > 0 ? cfgPort : 10100;
|
|
496
|
-
const child = spawn(process.execPath, [
|
|
498
|
+
const child = spawn(process.execPath, selfLaunchArgv(["start", "--port", String(pinPort)]), {
|
|
497
499
|
detached: true,
|
|
498
500
|
stdio: "ignore",
|
|
499
501
|
windowsHide: true,
|
|
500
|
-
env: opencodeProxyStartEnv(process.env) as NodeJS.ProcessEnv,
|
|
502
|
+
env: withProcessRuntimeProvenance(opencodeProxyStartEnv(process.env) as NodeJS.ProcessEnv),
|
|
501
503
|
});
|
|
502
504
|
// Without a listener an 'error' (bad argv[1], EMFILE, AV denial) throws synchronously
|
|
503
505
|
// and kills this process; the health poll below already reports the failure properly.
|
|
@@ -11,12 +11,20 @@ import {
|
|
|
11
11
|
takeOption,
|
|
12
12
|
type RuntimeApiDeps,
|
|
13
13
|
} from "./runtime-api";
|
|
14
|
+
import { providerQuotaLine } from "./account-extended";
|
|
15
|
+
import type { ProviderQuotaReportDto } from "./account-api";
|
|
16
|
+
|
|
17
|
+
interface ProviderQuotasDto {
|
|
18
|
+
generatedAt?: number;
|
|
19
|
+
reports?: ProviderQuotaReportDto[];
|
|
20
|
+
}
|
|
14
21
|
|
|
15
22
|
const USAGE = `Usage:
|
|
16
23
|
ocx provider edit <name> [--adapter <id>] [--base-url <url>] [--default-model <id|->]
|
|
17
24
|
[--auth-mode <key|forward|oauth|local|->] [--note <text|->]
|
|
18
25
|
[--api-key-transport <x-api-key|bearer|->]
|
|
19
|
-
[--
|
|
26
|
+
[--headers <json>] [--enabled <on|off>] [--live-models <on|off>]
|
|
27
|
+
[--allow-private-network <on|off>] [--json]
|
|
20
28
|
ocx provider test <name> [--json]
|
|
21
29
|
ocx provider quota [--refresh] [--json]
|
|
22
30
|
ocx provider presets [--json]
|
|
@@ -39,6 +47,7 @@ async function edit(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
|
39
47
|
const authMode = cleared(takeOption(args, "--auth-mode"));
|
|
40
48
|
const note = cleared(takeOption(args, "--note"));
|
|
41
49
|
const apiKeyTransport = cleared(takeOption(args, "--api-key-transport"));
|
|
50
|
+
const headers = takeOption(args, "--headers");
|
|
42
51
|
const enabled = takeBooleanOption(args, "--enabled");
|
|
43
52
|
const liveModels = takeBooleanOption(args, "--live-models");
|
|
44
53
|
const allowPrivateNetwork = takeBooleanOption(args, "--allow-private-network");
|
|
@@ -49,6 +58,21 @@ async function edit(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
|
49
58
|
if (authMode !== undefined) patch.authMode = authMode;
|
|
50
59
|
if (note !== undefined) patch.note = note;
|
|
51
60
|
if (apiKeyTransport !== undefined) patch.apiKeyTransport = apiKeyTransport;
|
|
61
|
+
if (headers !== undefined) {
|
|
62
|
+
if (headers === "-") {
|
|
63
|
+
patch.headers = null;
|
|
64
|
+
} else {
|
|
65
|
+
let parsed: unknown;
|
|
66
|
+
try { parsed = JSON.parse(headers); } catch { throw new CliUsageError("--headers must be valid JSON"); }
|
|
67
|
+
if (parsed === null) {
|
|
68
|
+
patch.headers = null;
|
|
69
|
+
} else if (typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
70
|
+
throw new CliUsageError("--headers must be a JSON object like {\"X-Custom\":\"value\"}");
|
|
71
|
+
} else {
|
|
72
|
+
patch.headers = parsed;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
52
76
|
if (enabled !== undefined) patch.disabled = !enabled;
|
|
53
77
|
if (liveModels !== undefined) patch.liveModels = liveModels;
|
|
54
78
|
if (allowPrivateNetwork !== undefined) patch.allowPrivateNetwork = allowPrivateNetwork;
|
|
@@ -90,8 +114,15 @@ async function quota(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
|
90
114
|
const wantsJson = takeFlag(args, "--json");
|
|
91
115
|
const refresh = takeFlag(args, "--refresh");
|
|
92
116
|
rejectArgs(args, USAGE);
|
|
93
|
-
const result = await runtimeRequest(`/api/provider-quotas${refresh ? "?refresh=1" : ""}`, {}, deps);
|
|
94
|
-
|
|
117
|
+
const result = await runtimeRequest<ProviderQuotasDto>(`/api/provider-quotas${refresh ? "?refresh=1" : ""}`, {}, deps);
|
|
118
|
+
// `summaryLines` is a depth-1 flattener: it renders a non-scalar array as "N item(s)", which
|
|
119
|
+
// collapsed the whole report to a count and made the command useless for its stated purpose
|
|
120
|
+
// (#2565). Render one line per report with the same formatter `ocx account refresh` uses.
|
|
121
|
+
const reports = Array.isArray(result?.reports) ? result.reports : [];
|
|
122
|
+
const lines = reports.length > 0
|
|
123
|
+
? reports.map(report => providerQuotaLine(report.provider, report))
|
|
124
|
+
: ["no quota reports available"];
|
|
125
|
+
printData(result, wantsJson, lines);
|
|
95
126
|
}
|
|
96
127
|
|
|
97
128
|
async function presets(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
package/src/cli/provider.ts
CHANGED
|
@@ -8,10 +8,12 @@
|
|
|
8
8
|
* show <name> Show provider config details (secrets masked)
|
|
9
9
|
* set-default <name> Change the default provider
|
|
10
10
|
*/
|
|
11
|
-
import {
|
|
11
|
+
import { hasOwnProvider, isValidProviderName, loadConfig, sanitizeModelCostsForDisplay, saveConfig } from "../config";
|
|
12
|
+
import { apiKeyTransportConfigError } from "../config/provider-validation";
|
|
12
13
|
import { hasHelpFlag } from "./help";
|
|
13
14
|
import { getProviderRegistryEntry, PROVIDER_REGISTRY } from "../providers/registry";
|
|
14
15
|
import { providerConfigSeed } from "../providers/derive";
|
|
16
|
+
import { dropProviderCustomModels } from "../providers/provider-id-rewrite";
|
|
15
17
|
import type { OcxProviderConfig } from "../types";
|
|
16
18
|
import { findLiveProxy } from "../server/proxy-liveness";
|
|
17
19
|
import { syncModelsToCodex } from "../codex/sync";
|
|
@@ -209,7 +211,14 @@ async function handleAdd(args: string[]): Promise<void> {
|
|
|
209
211
|
provConfig.apiKeyTransport = apiKeyTransport;
|
|
210
212
|
}
|
|
211
213
|
|
|
214
|
+
const existingProvider = config.providers[name];
|
|
212
215
|
config.providers[name] = provConfig;
|
|
216
|
+
// A --force overwrite rotates the key/endpoint but must not drop a
|
|
217
|
+
// user-configured price overlay (same rule as the /api/providers path and
|
|
218
|
+
// the login paths); there is no explicit clear/replace flag yet.
|
|
219
|
+
if (existingProvider?.modelCosts !== undefined && provConfig.modelCosts === undefined) {
|
|
220
|
+
provConfig.modelCosts = existingProvider.modelCosts;
|
|
221
|
+
}
|
|
213
222
|
if (allowPrivateNetwork) provConfig.allowPrivateNetwork = true;
|
|
214
223
|
if (setDefault) config.defaultProvider = name;
|
|
215
224
|
|
|
@@ -229,12 +238,18 @@ async function handleAdd(args: string[]): Promise<void> {
|
|
|
229
238
|
return;
|
|
230
239
|
}
|
|
231
240
|
|
|
241
|
+
let codexSyncSkipped = false;
|
|
232
242
|
if (wantsSync) {
|
|
233
243
|
const live = await findLiveProxy();
|
|
234
244
|
if (live) {
|
|
235
|
-
await syncModelsToCodex(live.port).catch(e => {
|
|
245
|
+
const synced = await syncModelsToCodex(live.port).catch(e => {
|
|
236
246
|
console.error(`Warning: sync failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
247
|
+
return null;
|
|
237
248
|
});
|
|
249
|
+
if (synced?.status === "skipped") {
|
|
250
|
+
codexSyncSkipped = true;
|
|
251
|
+
console.log("Provider saved; Codex integration is OFF, so Codex sync was skipped.");
|
|
252
|
+
}
|
|
238
253
|
}
|
|
239
254
|
}
|
|
240
255
|
|
|
@@ -249,7 +264,7 @@ async function handleAdd(args: string[]): Promise<void> {
|
|
|
249
264
|
console.log(` Set API key with: ocx provider add ${name} --api-key <key> --force`);
|
|
250
265
|
console.log(` Or set env var: ${envKey}`);
|
|
251
266
|
}
|
|
252
|
-
if (wantsSync) {
|
|
267
|
+
if (wantsSync && !codexSyncSkipped) {
|
|
253
268
|
console.log(` Models synced to Codex.`);
|
|
254
269
|
} else {
|
|
255
270
|
console.log(` Apply to Codex: ocx sync`);
|
|
@@ -296,6 +311,7 @@ function handleRemove(args: string[]): void {
|
|
|
296
311
|
}
|
|
297
312
|
|
|
298
313
|
delete config.providers[name];
|
|
314
|
+
const droppedCustomModels = dropProviderCustomModels(config, name);
|
|
299
315
|
validateAndSave(config);
|
|
300
316
|
|
|
301
317
|
|
|
@@ -306,11 +322,16 @@ function handleRemove(args: string[]): void {
|
|
|
306
322
|
remainingProviders: Object.keys(config.providers),
|
|
307
323
|
defaultProvider: config.defaultProvider,
|
|
308
324
|
needsSync: true,
|
|
325
|
+
...(droppedCustomModels > 0 ? { droppedCustomModels } : {}),
|
|
309
326
|
}, null, 2));
|
|
310
327
|
return;
|
|
311
328
|
}
|
|
312
329
|
|
|
313
330
|
console.log(`✅ Provider "${name}" removed.`);
|
|
331
|
+
if (droppedCustomModels > 0) {
|
|
332
|
+
const plural = droppedCustomModels === 1 ? "model" : "models";
|
|
333
|
+
console.log(` Also removed ${droppedCustomModels} custom ${plural} that belonged to it.`);
|
|
334
|
+
}
|
|
314
335
|
}
|
|
315
336
|
|
|
316
337
|
// ---------------------------------------------------------------------------
|
|
@@ -336,6 +357,7 @@ function handleShow(args: string[]): void {
|
|
|
336
357
|
const prov = config.providers[name];
|
|
337
358
|
const display = {
|
|
338
359
|
...prov,
|
|
360
|
+
...(prov.modelCosts !== undefined ? { modelCosts: sanitizeModelCostsForDisplay(prov.modelCosts) } : {}),
|
|
339
361
|
...(prov.apiKey ? { apiKey: maskSecret(prov.apiKey) } : {}),
|
|
340
362
|
...(prov.apiKeyPool ? { apiKeyPool: prov.apiKeyPool.map(e => ({ ...e, key: maskSecret(e.key) })) } : {}),
|
|
341
363
|
};
|