@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
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MiniMax client launchers.
|
|
3
|
+
*
|
|
4
|
+
* `ocx mcode` uses the managed `custom_provider.opencodex` block written by the
|
|
5
|
+
* existing file-integration subsystem. `ocx mmx` is intentionally text-only:
|
|
6
|
+
* the official platform CLI's text commands speak Anthropic Messages, while its
|
|
7
|
+
* image/video/speech/music/search/quota endpoints are MiniMax-specific APIs that
|
|
8
|
+
* OpenCodex does not claim to implement.
|
|
9
|
+
*/
|
|
10
|
+
import { execFileSync, spawn, type ChildProcess } from "node:child_process";
|
|
11
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { ClientPathError, mcodeConfigPath, LOOPBACK_API_KEY_PLACEHOLDER } from "../clients/config-export";
|
|
15
|
+
import { loadConfig } from "../config";
|
|
16
|
+
import { clearableDeadline } from "../lib/abort";
|
|
17
|
+
import { withProcessRuntimeProvenance } from "../lib/bun-runtime";
|
|
18
|
+
import { selfLaunchArgv } from "../lib/self-launch-argv";
|
|
19
|
+
import { commandInvocation } from "../lib/win-exec";
|
|
20
|
+
import { isLoopbackHostname } from "../server/auth-cors";
|
|
21
|
+
import { findLiveProxy, probeHostname, type LiveProxy } from "../server/proxy-liveness";
|
|
22
|
+
import type { OcxConfig } from "../types";
|
|
23
|
+
import { opencodeProxyStartEnv } from "./opencode";
|
|
24
|
+
|
|
25
|
+
export interface MinimaxLaunchEnv {
|
|
26
|
+
[key: string]: string | undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface MmxTextBridge {
|
|
30
|
+
baseUrl: string;
|
|
31
|
+
port: number;
|
|
32
|
+
stop(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface MmxTextBridgeOptions {
|
|
36
|
+
/** Optional outer guard; production delegates timeout policy to `/v1/messages`. */
|
|
37
|
+
headerTimeoutMs?: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface MmxTerminationTarget {
|
|
41
|
+
pid?: number;
|
|
42
|
+
exitCode: number | null;
|
|
43
|
+
signalCode: NodeJS.Signals | null;
|
|
44
|
+
kill(signal?: NodeJS.Signals | number): boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface MmxTerminationDeps {
|
|
48
|
+
platform?: NodeJS.Platform;
|
|
49
|
+
killWindowsTree?: (pid: number) => void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface MmxSignalHost {
|
|
53
|
+
on(signal: "SIGINT" | "SIGTERM", listener: () => void): unknown;
|
|
54
|
+
off(signal: "SIGINT" | "SIGTERM", listener: () => void): unknown;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface MmxTerminationHandlersOptions {
|
|
58
|
+
getChild: () => MmxTerminationTarget | null;
|
|
59
|
+
cleanup: () => Promise<void>;
|
|
60
|
+
host?: MmxSignalHost;
|
|
61
|
+
now?: () => number;
|
|
62
|
+
terminationDeps?: MmxTerminationDeps;
|
|
63
|
+
onCleanupError?: (error: unknown) => void;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const MMX_TERMINATION_DUPLICATE_WINDOW_MS = 500;
|
|
67
|
+
|
|
68
|
+
const MMX_CHILD_OWNED_ENV_KEYS = new Set([
|
|
69
|
+
"MMX_CONFIG_DIR",
|
|
70
|
+
"MINIMAX_BASE_URL",
|
|
71
|
+
"MINIMAX_REGION",
|
|
72
|
+
"MINIMAX_API_KEY",
|
|
73
|
+
"HTTP_PROXY",
|
|
74
|
+
"HTTPS_PROXY",
|
|
75
|
+
"ALL_PROXY",
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
const MMX_GLOBAL_BOOLEAN_FLAGS = new Set([
|
|
79
|
+
"--quiet",
|
|
80
|
+
"--verbose",
|
|
81
|
+
"--no-color",
|
|
82
|
+
"--dry-run",
|
|
83
|
+
"--non-interactive",
|
|
84
|
+
"--yes",
|
|
85
|
+
"--async",
|
|
86
|
+
"--stream",
|
|
87
|
+
"--no-stream",
|
|
88
|
+
"--no-wait",
|
|
89
|
+
"--help",
|
|
90
|
+
"--version",
|
|
91
|
+
]);
|
|
92
|
+
|
|
93
|
+
/** Mirrors the official mmx command scanner's global-flag skipping behavior. */
|
|
94
|
+
export function mmxCommandPath(argv: readonly string[]): string[] {
|
|
95
|
+
const path: string[] = [];
|
|
96
|
+
for (let index = 0; index < argv.length;) {
|
|
97
|
+
const arg = argv[index]!;
|
|
98
|
+
if (arg === "--") break;
|
|
99
|
+
if (arg.startsWith("--")) {
|
|
100
|
+
const equals = arg.indexOf("=");
|
|
101
|
+
const name = equals >= 0 ? arg.slice(0, equals) : arg;
|
|
102
|
+
index += equals < 0 && !MMX_GLOBAL_BOOLEAN_FLAGS.has(name) ? 2 : 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (arg.startsWith("-")) {
|
|
106
|
+
index += 1;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
path.push(arg);
|
|
110
|
+
index += 1;
|
|
111
|
+
}
|
|
112
|
+
return path;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** Caller credentials and destinations may never override the proxy wrapper. */
|
|
116
|
+
export function mmxUnsafeOverride(argv: readonly string[]): string | null {
|
|
117
|
+
for (const arg of argv) {
|
|
118
|
+
if (arg === "--api-key" || arg.startsWith("--api-key=")) return "--api-key";
|
|
119
|
+
if (arg === "--base-url" || arg.startsWith("--base-url=")) return "--base-url";
|
|
120
|
+
if (arg === "--region" || arg.startsWith("--region=")) return "--region";
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function buildMmxEnv(
|
|
126
|
+
live: Pick<LiveProxy, "hostname" | "port">,
|
|
127
|
+
configDir: string,
|
|
128
|
+
base: MinimaxLaunchEnv = process.env,
|
|
129
|
+
): MinimaxLaunchEnv {
|
|
130
|
+
const env: MinimaxLaunchEnv = { ...base };
|
|
131
|
+
// The official MMX client installs one ProxyAgent whenever any proxy variable
|
|
132
|
+
// is present and does not apply NO_PROXY. Its OpenCodex destination is always
|
|
133
|
+
// loopback, so carrying these variables could send the request off-machine.
|
|
134
|
+
// Windows environment names are case-insensitive; strip every inherited
|
|
135
|
+
// spelling before installing the wrapper-owned values below.
|
|
136
|
+
for (const key of Object.keys(env)) {
|
|
137
|
+
if (MMX_CHILD_OWNED_ENV_KEYS.has(key.toUpperCase())) delete env[key];
|
|
138
|
+
}
|
|
139
|
+
env.MMX_CONFIG_DIR = configDir;
|
|
140
|
+
env.MINIMAX_BASE_URL = `http://${probeHostname(live.hostname)}:${live.port}`;
|
|
141
|
+
// Prevent a parent-shell region from triggering key detection against the
|
|
142
|
+
// official MiniMax hosts. The base URL above remains authoritative.
|
|
143
|
+
env.MINIMAX_REGION = "global";
|
|
144
|
+
return env;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* MMX hard-codes `/anthropic/v1/messages` below its configured base URL while
|
|
149
|
+
* OpenCodex already exposes the canonical Anthropic data plane at
|
|
150
|
+
* `/v1/messages`. Keep that client-specific path adaptation inside the checked
|
|
151
|
+
* launcher instead of widening the proxy server's authentication surface.
|
|
152
|
+
*/
|
|
153
|
+
export function startMmxTextBridge(
|
|
154
|
+
live: Pick<LiveProxy, "hostname" | "port">,
|
|
155
|
+
options: MmxTextBridgeOptions = {},
|
|
156
|
+
): MmxTextBridge {
|
|
157
|
+
const upstreamOrigin = `http://${probeHostname(live.hostname)}:${live.port}`;
|
|
158
|
+
const server = Bun.serve({
|
|
159
|
+
hostname: "127.0.0.1",
|
|
160
|
+
port: 0,
|
|
161
|
+
async fetch(req) {
|
|
162
|
+
const incoming = new URL(req.url);
|
|
163
|
+
const canonicalPath = incoming.pathname === "/anthropic/v1/messages"
|
|
164
|
+
? "/v1/messages"
|
|
165
|
+
: incoming.pathname === "/anthropic/v1/messages/count_tokens"
|
|
166
|
+
? "/v1/messages/count_tokens"
|
|
167
|
+
: null;
|
|
168
|
+
if (req.method !== "POST" || !canonicalPath) {
|
|
169
|
+
return Response.json({
|
|
170
|
+
type: "error",
|
|
171
|
+
error: { type: "not_found_error", message: "unsupported MMX bridge route" },
|
|
172
|
+
}, { status: 404 });
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const target = new URL(canonicalPath, `${upstreamOrigin}/`);
|
|
176
|
+
target.search = incoming.search;
|
|
177
|
+
const headers = new Headers(req.headers);
|
|
178
|
+
// The bridge is loopback-only and OpenCodex does not require a real key
|
|
179
|
+
// there. Pin the public placeholder even if a future MMX release loads a
|
|
180
|
+
// credential from somewhere outside the isolated config directory.
|
|
181
|
+
headers.delete("authorization");
|
|
182
|
+
headers.delete("x-opencodex-api-key");
|
|
183
|
+
headers.set("x-api-key", LOOPBACK_API_KEY_PLACEHOLDER);
|
|
184
|
+
headers.delete("host");
|
|
185
|
+
headers.delete("content-length");
|
|
186
|
+
// The canonical data plane owns its configured response-header, retry,
|
|
187
|
+
// and stream-stall budgets. An extra default here would cut off valid
|
|
188
|
+
// non-streaming or failover completions before their real response.
|
|
189
|
+
const headerDeadline = options.headerTimeoutMs === undefined
|
|
190
|
+
? null
|
|
191
|
+
: clearableDeadline(options.headerTimeoutMs, req.signal);
|
|
192
|
+
try {
|
|
193
|
+
const upstreamRequest = new Request(target, {
|
|
194
|
+
method: "POST",
|
|
195
|
+
headers,
|
|
196
|
+
body: req.body,
|
|
197
|
+
signal: headerDeadline?.signal ?? req.signal,
|
|
198
|
+
});
|
|
199
|
+
return await fetch(upstreamRequest, {
|
|
200
|
+
// Override HTTP(S)_PROXY with the loopback listener itself. Bun sends
|
|
201
|
+
// the HTTP proxy-form request directly to this exact origin, so the
|
|
202
|
+
// hop cannot leave the machine even when the parent has proxy vars.
|
|
203
|
+
proxy: { url: upstreamOrigin },
|
|
204
|
+
});
|
|
205
|
+
} catch {
|
|
206
|
+
return Response.json({
|
|
207
|
+
type: "error",
|
|
208
|
+
error: { type: "api_error", message: "OpenCodex proxy unavailable" },
|
|
209
|
+
}, { status: 502 });
|
|
210
|
+
} finally {
|
|
211
|
+
// Once response headers arrive, streaming body cancellation remains
|
|
212
|
+
// linked to the client while this response-header timer is disarmed.
|
|
213
|
+
headerDeadline?.clear();
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
const bridgePort = server.port;
|
|
218
|
+
if (bridgePort === undefined) {
|
|
219
|
+
void server.stop(true);
|
|
220
|
+
throw new Error("MMX text bridge did not receive a TCP port");
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
baseUrl: `http://127.0.0.1:${bridgePort}`,
|
|
224
|
+
port: bridgePort,
|
|
225
|
+
stop: () => server.stop(true),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function normalizedMcodeBaseUrl(value: string): string | null {
|
|
230
|
+
try {
|
|
231
|
+
const url = new URL(value);
|
|
232
|
+
if (
|
|
233
|
+
url.username
|
|
234
|
+
|| url.password
|
|
235
|
+
|| (url.pathname !== "" && url.pathname !== "/")
|
|
236
|
+
|| url.search
|
|
237
|
+
|| url.hash
|
|
238
|
+
) return null;
|
|
239
|
+
return url.origin;
|
|
240
|
+
} catch {
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** Read only the provider destination; never return or log the persisted key. */
|
|
246
|
+
export function mcodeOpenCodexBaseUrl(text: string): string | null {
|
|
247
|
+
try {
|
|
248
|
+
const parsed = Bun.YAML.parse(text) as {
|
|
249
|
+
custom_provider?: { opencodex?: { options?: { baseURL?: unknown } } };
|
|
250
|
+
};
|
|
251
|
+
const baseURL = parsed?.custom_provider?.opencodex?.options?.baseURL;
|
|
252
|
+
return typeof baseURL === "string" ? baseURL : null;
|
|
253
|
+
} catch {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** Reject stale runtime metadata that points a loopback-only launcher off-machine. */
|
|
259
|
+
export function usableMinimaxLiveProxy(live: LiveProxy | null): LiveProxy | null {
|
|
260
|
+
if (!live) return null;
|
|
261
|
+
return isLoopbackHostname(probeHostname(live.hostname)) ? live : null;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async function ensureProxy(config: OcxConfig): Promise<LiveProxy | null> {
|
|
265
|
+
const live = usableMinimaxLiveProxy(await findLiveProxy());
|
|
266
|
+
if (live) return live;
|
|
267
|
+
const pinPort = typeof config.port === "number" && config.port > 0 ? config.port : 10100;
|
|
268
|
+
const child = spawn(process.execPath, selfLaunchArgv(["start", "--port", String(pinPort)]), {
|
|
269
|
+
detached: true,
|
|
270
|
+
stdio: "ignore",
|
|
271
|
+
windowsHide: true,
|
|
272
|
+
// Reuse the established service-token lookup so a detached start works
|
|
273
|
+
// when admission lives in the hardened token file rather than this shell.
|
|
274
|
+
env: withProcessRuntimeProvenance(opencodeProxyStartEnv(process.env) as NodeJS.ProcessEnv),
|
|
275
|
+
});
|
|
276
|
+
child.on("error", () => { /* the bounded health poll reports failure */ });
|
|
277
|
+
child.unref();
|
|
278
|
+
const deadline = Date.now() + 8_000;
|
|
279
|
+
while (Date.now() < deadline) {
|
|
280
|
+
const started = usableMinimaxLiveProxy(await findLiveProxy());
|
|
281
|
+
if (started) return started;
|
|
282
|
+
await new Promise(resolve => setTimeout(resolve, 250));
|
|
283
|
+
}
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** Only a root-level, single-token info request may bypass proxy isolation. */
|
|
288
|
+
export function isStandaloneInformationalInvocation(
|
|
289
|
+
argv: readonly string[],
|
|
290
|
+
client: "mcode" | "mmx",
|
|
291
|
+
): boolean {
|
|
292
|
+
if (argv.length !== 1) return false;
|
|
293
|
+
const arg = argv[0];
|
|
294
|
+
if (arg === "--help" || arg === "-h" || arg === "--version") return true;
|
|
295
|
+
// MMX 1.0.19 implements -v for version and does not implement -V. Preserve
|
|
296
|
+
// MCode's established -V passthrough separately.
|
|
297
|
+
return client === "mmx" ? arg === "-v" : arg === "-v" || arg === "-V";
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** Forward wrapper termination only while the MMX child is still live. */
|
|
301
|
+
export function forwardMmxTerminationSignal(
|
|
302
|
+
child: MmxTerminationTarget,
|
|
303
|
+
signal: "SIGINT" | "SIGTERM",
|
|
304
|
+
deps: MmxTerminationDeps = {},
|
|
305
|
+
): boolean {
|
|
306
|
+
if (child.exitCode !== null || child.signalCode !== null) return false;
|
|
307
|
+
try {
|
|
308
|
+
if ((deps.platform ?? process.platform) === "win32") {
|
|
309
|
+
if (!Number.isInteger(child.pid) || child.pid === undefined || child.pid <= 0) return false;
|
|
310
|
+
const killWindowsTree = deps.killWindowsTree ?? (pid => {
|
|
311
|
+
const taskkill = `${process.env.SystemRoot ?? "C:\\Windows"}\\System32\\taskkill.exe`;
|
|
312
|
+
execFileSync(taskkill, ["/PID", String(pid), "/T", "/F"], {
|
|
313
|
+
stdio: "ignore",
|
|
314
|
+
windowsHide: true,
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
killWindowsTree(child.pid);
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
return child.kill(signal);
|
|
321
|
+
} catch {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** Install persistent, duplicate-aware wrapper signal handlers. */
|
|
327
|
+
export function installMmxTerminationHandlers(
|
|
328
|
+
options: MmxTerminationHandlersOptions,
|
|
329
|
+
): () => void {
|
|
330
|
+
const host = options.host ?? process;
|
|
331
|
+
const now = options.now ?? Date.now;
|
|
332
|
+
let lastTerminationSignalAt: number | null = null;
|
|
333
|
+
const onTerminationSignal = (signal: "SIGINT" | "SIGTERM") => {
|
|
334
|
+
const receivedAt = now();
|
|
335
|
+
// Ctrl-C reaches the foreground Bun process directly and is also
|
|
336
|
+
// forwarded by bin/ocx.mjs. Keep the listener installed and coalesce the
|
|
337
|
+
// near-simultaneous duplicate so async cleanup cannot be interrupted by
|
|
338
|
+
// the default signal action after a once-listener disappears.
|
|
339
|
+
if (
|
|
340
|
+
lastTerminationSignalAt !== null
|
|
341
|
+
&& receivedAt - lastTerminationSignalAt < MMX_TERMINATION_DUPLICATE_WINDOW_MS
|
|
342
|
+
) return;
|
|
343
|
+
lastTerminationSignalAt = receivedAt;
|
|
344
|
+
const child = options.getChild();
|
|
345
|
+
if (child) forwardMmxTerminationSignal(child, signal, options.terminationDeps);
|
|
346
|
+
try {
|
|
347
|
+
void options.cleanup().catch(error => { options.onCleanupError?.(error); });
|
|
348
|
+
} catch (error) {
|
|
349
|
+
options.onCleanupError?.(error);
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const onSigint = () => onTerminationSignal("SIGINT");
|
|
353
|
+
const onSigterm = () => onTerminationSignal("SIGTERM");
|
|
354
|
+
host.on("SIGINT", onSigint);
|
|
355
|
+
host.on("SIGTERM", onSigterm);
|
|
356
|
+
return () => {
|
|
357
|
+
host.off("SIGINT", onSigint);
|
|
358
|
+
host.off("SIGTERM", onSigterm);
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/** Keep signal handlers active until asynchronous bridge cleanup has settled. */
|
|
363
|
+
export async function finishMmxClientCleanup(
|
|
364
|
+
cleanup: () => Promise<void>,
|
|
365
|
+
removeTerminationHandlers: () => void,
|
|
366
|
+
): Promise<void> {
|
|
367
|
+
try {
|
|
368
|
+
await cleanup();
|
|
369
|
+
} finally {
|
|
370
|
+
removeTerminationHandlers();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function spawnClient(
|
|
375
|
+
command: "mcode" | "mmx",
|
|
376
|
+
args: readonly string[],
|
|
377
|
+
env: NodeJS.ProcessEnv,
|
|
378
|
+
installHint: string,
|
|
379
|
+
onSpawn?: (child: ChildProcess) => void,
|
|
380
|
+
): Promise<number> {
|
|
381
|
+
return new Promise(resolve => {
|
|
382
|
+
const inv = commandInvocation(command, [...args]);
|
|
383
|
+
const child = spawn(inv.file, inv.args, { stdio: "inherit", env, ...inv.options });
|
|
384
|
+
onSpawn?.(child);
|
|
385
|
+
child.on("error", (error: NodeJS.ErrnoException) => {
|
|
386
|
+
console.error(error.code === "ENOENT" ? installHint : `❌ Failed to launch ${command}: ${error.message}`);
|
|
387
|
+
resolve(1);
|
|
388
|
+
});
|
|
389
|
+
child.on("exit", (code, signal) => {
|
|
390
|
+
if (process.platform === "win32" && code === 9009 && !signal) console.error(installHint);
|
|
391
|
+
resolve(signal ? 1 : code ?? 0);
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const MCODE_INSTALL_HINT = "❌ `mcode` CLI not found. Install MiniMax Code first: https://github.com/MiniMax-AI/minimax-code";
|
|
397
|
+
const MMX_INSTALL_HINT = "❌ `mmx` CLI not found. Install it first: npm install -g mmx-cli";
|
|
398
|
+
|
|
399
|
+
export async function cmdMcode(args: string[]): Promise<number> {
|
|
400
|
+
if (isStandaloneInformationalInvocation(args, "mcode")) return spawnClient("mcode", args, process.env, MCODE_INSTALL_HINT);
|
|
401
|
+
const config = loadConfig();
|
|
402
|
+
if (!isLoopbackHostname(config.hostname)) {
|
|
403
|
+
console.error("❌ MiniMax Code integration is loopback-only; its config cannot carry OpenCodex's dedicated remote-admission header.");
|
|
404
|
+
return 2;
|
|
405
|
+
}
|
|
406
|
+
const live = await ensureProxy(config);
|
|
407
|
+
if (!live) {
|
|
408
|
+
console.error("❌ Proxy did not become healthy after starting.");
|
|
409
|
+
return 1;
|
|
410
|
+
}
|
|
411
|
+
let configuredBase: string | null = null;
|
|
412
|
+
try {
|
|
413
|
+
configuredBase = mcodeOpenCodexBaseUrl(readFileSync(mcodeConfigPath(process.env), "utf8"));
|
|
414
|
+
} catch (error) {
|
|
415
|
+
// Missing or unreadable is reported as not connected below. An unstable
|
|
416
|
+
// relative override needs its own message because re-enabling cannot fix it.
|
|
417
|
+
if (error instanceof ClientPathError) {
|
|
418
|
+
console.error(`❌ ${error.message}`);
|
|
419
|
+
return 2;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (!configuredBase) {
|
|
423
|
+
console.error("❌ MiniMax Code is not connected. Run: ocx integration client enable --client mcode");
|
|
424
|
+
return 2;
|
|
425
|
+
}
|
|
426
|
+
const expected = `http://${probeHostname(live.hostname)}:${live.port}`;
|
|
427
|
+
if (normalizedMcodeBaseUrl(configuredBase) !== normalizedMcodeBaseUrl(expected)) {
|
|
428
|
+
console.error("❌ MiniMax Code's OpenCodex provider points at a stale proxy address. Re-run: ocx integration client enable --client mcode");
|
|
429
|
+
return 2;
|
|
430
|
+
}
|
|
431
|
+
console.error(`✅ MiniMax Code wired to ${expected}; select custom_provider:opencodex/<model> in MCode.`);
|
|
432
|
+
return spawnClient("mcode", args, process.env, MCODE_INSTALL_HINT);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export async function cmdMmx(args: string[]): Promise<number> {
|
|
436
|
+
if (isStandaloneInformationalInvocation(args, "mmx")) return spawnClient("mmx", args, process.env, MMX_INSTALL_HINT);
|
|
437
|
+
const unsafe = mmxUnsafeOverride(args);
|
|
438
|
+
if (unsafe) {
|
|
439
|
+
console.error(`❌ ${unsafe} is not accepted by ocx mmx because it could bypass the proxy or expose a caller credential.`);
|
|
440
|
+
return 2;
|
|
441
|
+
}
|
|
442
|
+
const commandPath = mmxCommandPath(args);
|
|
443
|
+
if (commandPath[0] !== "text") {
|
|
444
|
+
console.error("❌ ocx mmx supports only `mmx text` commands. Use plain `mmx` for MiniMax image, video, speech, music, vision, search, quota, auth, config, file, and update APIs.");
|
|
445
|
+
return 2;
|
|
446
|
+
}
|
|
447
|
+
const config = loadConfig();
|
|
448
|
+
if (!isLoopbackHostname(config.hostname)) {
|
|
449
|
+
console.error("❌ ocx mmx is loopback-only; MMX has no field for OpenCodex's dedicated remote-admission header.");
|
|
450
|
+
return 2;
|
|
451
|
+
}
|
|
452
|
+
const live = await ensureProxy(config);
|
|
453
|
+
if (!live) {
|
|
454
|
+
console.error("❌ Proxy did not become healthy after starting.");
|
|
455
|
+
return 1;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const configDir = mkdtempSync(join(tmpdir(), "opencodex-mmx-"));
|
|
459
|
+
let bridge: MmxTextBridge | null = null;
|
|
460
|
+
let mmxChild: ChildProcess | null = null;
|
|
461
|
+
let cleanupPromise: Promise<void> | null = null;
|
|
462
|
+
let removeTerminationHandlers = () => {};
|
|
463
|
+
const cleanup = (): Promise<void> => {
|
|
464
|
+
cleanupPromise ??= (async () => {
|
|
465
|
+
const activeBridge = bridge;
|
|
466
|
+
bridge = null;
|
|
467
|
+
try {
|
|
468
|
+
if (activeBridge) await activeBridge.stop();
|
|
469
|
+
} finally {
|
|
470
|
+
rmSync(configDir, { recursive: true, force: true });
|
|
471
|
+
}
|
|
472
|
+
})();
|
|
473
|
+
return cleanupPromise;
|
|
474
|
+
};
|
|
475
|
+
try {
|
|
476
|
+
// Isolate MMX from ~/.mmx OAuth/API-key state. The only credential in this
|
|
477
|
+
// temporary file is a public loopback placeholder, and the directory is
|
|
478
|
+
// removed as soon as the child exits.
|
|
479
|
+
writeFileSync(join(configDir, "config.json"), `${JSON.stringify({
|
|
480
|
+
api_key: LOOPBACK_API_KEY_PLACEHOLDER,
|
|
481
|
+
region: "global",
|
|
482
|
+
}, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
483
|
+
bridge = startMmxTextBridge(live);
|
|
484
|
+
const env = buildMmxEnv({ hostname: "127.0.0.1", port: bridge.port }, configDir, process.env) as NodeJS.ProcessEnv;
|
|
485
|
+
console.error(`✅ MiniMax CLI text bridged to http://${probeHostname(live.hostname)}:${live.port}/v1/messages.`);
|
|
486
|
+
removeTerminationHandlers = installMmxTerminationHandlers({
|
|
487
|
+
getChild: () => mmxChild,
|
|
488
|
+
cleanup,
|
|
489
|
+
onCleanupError: error => {
|
|
490
|
+
console.error(`❌ Failed to clean up the MMX bridge after a termination signal: ${String(error)}`);
|
|
491
|
+
},
|
|
492
|
+
});
|
|
493
|
+
return await spawnClient("mmx", args, env, MMX_INSTALL_HINT, child => { mmxChild = child; });
|
|
494
|
+
} finally {
|
|
495
|
+
await finishMmxClientCleanup(cleanup, removeTerminationHandlers);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
@@ -16,11 +16,17 @@ import {
|
|
|
16
16
|
const USAGE = `Usage:
|
|
17
17
|
ocx models live [--provider <name>] [--json]
|
|
18
18
|
ocx models edit <custom-id> [--model-id <id>] [--display-name <name|->]
|
|
19
|
-
[--context-window <tokens|0>] [--modalities <text,image,audio|->]
|
|
19
|
+
[--context-window <tokens|0>] [--modalities <text,image,audio|->]
|
|
20
|
+
[--reasoning-efforts <none,minimal,low,medium,high,xhigh,max,ultra|->]
|
|
21
|
+
[--default-reasoning-effort <level|->] [--json]
|
|
20
22
|
ocx models <enable|disable> <provider/model|native-model> [--native] [--json]
|
|
21
23
|
ocx models provider <name> <on|off> [--json]
|
|
22
24
|
ocx models selected <provider> [--set <id,id...>|--clear] [--json]
|
|
23
|
-
ocx models
|
|
25
|
+
ocx models preset show [--provider <name>] [--json]
|
|
26
|
+
ocx models preset apply <provider> [--all] [--json]
|
|
27
|
+
ocx models new-policy [on|off] [--provider <name>] [--json]
|
|
28
|
+
ocx models new-arrivals [--json]
|
|
29
|
+
ocx models context <status|value <tokens> [--set-all]|provider <name> on [--value <tokens>]|provider <name> off|all <on|off>> [--json]
|
|
24
30
|
ocx models shadow <status|set> [model|-] [--enabled <on|off>] [--json]`;
|
|
25
31
|
|
|
26
32
|
type ModelRow = {
|
|
@@ -57,6 +63,8 @@ async function edit(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
|
57
63
|
const displayName = takeOption(args, "--display-name");
|
|
58
64
|
const contextRaw = takeOption(args, "--context-window");
|
|
59
65
|
const modalitiesRaw = takeOption(args, "--modalities");
|
|
66
|
+
const reasoningEffortsRaw = takeOption(args, "--reasoning-efforts");
|
|
67
|
+
const defaultEffortRaw = takeOption(args, "--default-reasoning-effort");
|
|
60
68
|
rejectArgs(args, USAGE);
|
|
61
69
|
if (modelId !== undefined) patch.modelId = modelId;
|
|
62
70
|
if (displayName !== undefined) patch.displayName = displayName === "-" ? "" : displayName;
|
|
@@ -66,6 +74,23 @@ async function edit(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
|
66
74
|
patch.contextWindow = value === 0 ? null : value;
|
|
67
75
|
}
|
|
68
76
|
if (modalitiesRaw !== undefined) patch.inputModalities = modalitiesRaw === "-" ? [] : csv(modalitiesRaw);
|
|
77
|
+
// "-" restores inheritance by clearing the stored ladder (null); "" stores an explicit
|
|
78
|
+
// empty ladder (the "no reasoning" override, same as the dashboard's uncheck-all).
|
|
79
|
+
// Embedded blank CSV members (`low,,high`, `,,`) are malformed and must be rejected, not
|
|
80
|
+
// silently normalized by csv().
|
|
81
|
+
if (reasoningEffortsRaw !== undefined) {
|
|
82
|
+
if (reasoningEffortsRaw === "-") {
|
|
83
|
+
patch.reasoningEfforts = null;
|
|
84
|
+
} else {
|
|
85
|
+
const trimmed = reasoningEffortsRaw.trim();
|
|
86
|
+
const values = trimmed === "" ? [] : trimmed.split(",").map(value => value.trim());
|
|
87
|
+
if (values.some(value => value === "")) {
|
|
88
|
+
throw new CliUsageError("--reasoning-efforts must be comma-separated values from none, minimal, low, medium, high, xhigh, max, ultra (\"\" for no reasoning, \"-\" to inherit)", USAGE);
|
|
89
|
+
}
|
|
90
|
+
patch.reasoningEfforts = values;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (defaultEffortRaw !== undefined) patch.defaultReasoningEffort = defaultEffortRaw === "-" ? null : defaultEffortRaw;
|
|
69
94
|
if (Object.keys(patch).length === 0) throw new CliUsageError("at least one edit option is required", USAGE);
|
|
70
95
|
const result = await runtimeRequest(`/api/custom-models/${encodeURIComponent(id)}`, {
|
|
71
96
|
method: "PUT",
|
|
@@ -141,6 +166,94 @@ async function selected(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
|
141
166
|
printData(result, wantsJson, [`${provider}: ${models.length ? models.join(", ") : "all models"}`]);
|
|
142
167
|
}
|
|
143
168
|
|
|
169
|
+
|
|
170
|
+
interface ModelPresetView {
|
|
171
|
+
mode: string;
|
|
172
|
+
appliedVersion?: number;
|
|
173
|
+
availableVersion: number;
|
|
174
|
+
presetIds: string[];
|
|
175
|
+
presetCount: number;
|
|
176
|
+
totalCount: number;
|
|
177
|
+
fallback?: string;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function presetLine(name: string, view: ModelPresetView): string {
|
|
181
|
+
const parts = [`${name}: mode=${view.mode}`];
|
|
182
|
+
if (view.appliedVersion !== undefined && view.appliedVersion !== view.availableVersion) {
|
|
183
|
+
parts.push(`applied v${view.appliedVersion}, available v${view.availableVersion}`);
|
|
184
|
+
} else {
|
|
185
|
+
parts.push(`preset v${view.availableVersion}`);
|
|
186
|
+
}
|
|
187
|
+
parts.push(`(${view.presetCount} of ${view.totalCount} models)`);
|
|
188
|
+
if (view.fallback) parts.push(`fallback=${view.fallback}`);
|
|
189
|
+
return parts.join(" ");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
async function preset(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
193
|
+
const args = [...argv];
|
|
194
|
+
const action = (args.shift() ?? "show").toLowerCase();
|
|
195
|
+
const wantsJson = takeFlag(args, "--json");
|
|
196
|
+
if (action === "show") {
|
|
197
|
+
const only = takeOption(args, "--provider")?.trim();
|
|
198
|
+
rejectArgs(args, USAGE);
|
|
199
|
+
const result = await runtimeRequest<{ providers?: Record<string, ModelPresetView> }>("/api/model-presets", {}, deps);
|
|
200
|
+
const providers = result.providers ?? {};
|
|
201
|
+
const entries = Object.entries(providers).filter(([name]) => !only || name === only);
|
|
202
|
+
const lines = entries.length > 0
|
|
203
|
+
? entries.map(([name, view]) => presetLine(name, view))
|
|
204
|
+
// A provider with no shipped preset is not an error: it simply has nothing to curate.
|
|
205
|
+
: [only ? `${only}: no model preset is shipped for this provider` : "no providers have a shipped model preset"];
|
|
206
|
+
printData(only ? providers[only] ?? {} : result, wantsJson, lines);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (action !== "apply") throw new CliUsageError(`unknown preset action '${action}'`, USAGE);
|
|
210
|
+
const provider = args.shift()?.trim();
|
|
211
|
+
const all = takeFlag(args, "--all");
|
|
212
|
+
if (!provider) throw new CliUsageError("provider is required", USAGE);
|
|
213
|
+
rejectArgs(args, USAGE);
|
|
214
|
+
const mode = all ? "all" : "preset";
|
|
215
|
+
const result = await runtimeRequest<{ selected?: string[]; fallback?: string; appliedVersion?: number }>(
|
|
216
|
+
"/api/model-presets",
|
|
217
|
+
{ method: "PUT", body: JSON.stringify({ provider, mode }) },
|
|
218
|
+
deps,
|
|
219
|
+
);
|
|
220
|
+
const selectedIds = result.selected ?? [];
|
|
221
|
+
const line = result.fallback === "preset-empty"
|
|
222
|
+
// Never silently narrow to nothing: empty means ALL, so a zero-match preset keeps what was
|
|
223
|
+
// there and says so.
|
|
224
|
+
? `${provider}: preset matched no models — selection unchanged (fallback to all)`
|
|
225
|
+
: all
|
|
226
|
+
? `${provider}: showing all models (allowlist cleared)`
|
|
227
|
+
: `${provider}: preset v${result.appliedVersion ?? "?"} applied — ${selectedIds.length} models selected`;
|
|
228
|
+
printData(result, wantsJson, [line]);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function newPolicy(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
232
|
+
const args = [...argv];
|
|
233
|
+
const state = args[0] && !args[0].startsWith("--") ? args.shift()!.toLowerCase() : undefined;
|
|
234
|
+
const provider = takeOption(args, "--provider")?.trim();
|
|
235
|
+
const wantsJson = takeFlag(args, "--json");
|
|
236
|
+
if (state !== undefined && state !== "on" && state !== "off") throw new CliUsageError("new policy must be on or off", USAGE);
|
|
237
|
+
rejectArgs(args, USAGE);
|
|
238
|
+
if (!state) {
|
|
239
|
+
const result = await runtimeRequest<{ policy: string; providers: Record<string, string> }>("/api/model-discovery", {}, deps);
|
|
240
|
+
const value = provider ? result.providers[provider] ?? "inherit" : result.policy;
|
|
241
|
+
printData(provider ? { provider, policy: value } : result, wantsJson, [`${provider ?? "global"}: ${value}`]);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
const result = await runtimeRequest<{ baselineBootstrapped?: boolean }>("/api/model-discovery", {
|
|
245
|
+
method: "PUT", body: JSON.stringify({ policy: state, provider: provider ?? null }),
|
|
246
|
+
}, deps);
|
|
247
|
+
printData(result, wantsJson, [`${provider ?? "global"}: ${state}${result.baselineBootstrapped ? " (current models recorded as known)" : ""}`]);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
async function newArrivals(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
251
|
+
const args = [...argv]; const wantsJson = takeFlag(args, "--json"); rejectArgs(args, USAGE);
|
|
252
|
+
const result = await runtimeRequest<{ recentArrivals: Record<string, Array<{ id: string; at: string; state: string }>> }>("/api/model-discovery", {}, deps);
|
|
253
|
+
const lines = Object.entries(result.recentArrivals).flatMap(([provider, rows]) => rows.map(row => `${provider}/${row.id} [${row.state}] ${row.at}`));
|
|
254
|
+
printData(result.recentArrivals, wantsJson, lines.length ? lines : ["no recent model arrivals"]);
|
|
255
|
+
}
|
|
256
|
+
|
|
144
257
|
async function context(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
145
258
|
const args = [...argv];
|
|
146
259
|
const action = (args.shift() ?? "status").toLowerCase();
|
|
@@ -158,11 +271,23 @@ async function context(argv: string[], deps: RuntimeApiDeps): Promise<void> {
|
|
|
158
271
|
const value = Number(raw.replace(/[_,]/g, ""));
|
|
159
272
|
if (!Number.isInteger(value) || value <= 0) throw new CliUsageError("context value must be a positive integer", USAGE);
|
|
160
273
|
body = { value };
|
|
274
|
+
// Explicit apply-to-all switch for headless use: re-points every routed provider to
|
|
275
|
+
// the new value, mirroring the dashboard's "apply to every routed provider" toggle.
|
|
276
|
+
// Without it the value only becomes the default for future toggles.
|
|
277
|
+
if (takeFlag(args, "--set-all")) body.setAll = true;
|
|
161
278
|
} else if (action === "provider") {
|
|
162
279
|
const provider = args.shift()?.trim();
|
|
163
280
|
const state = args.shift()?.toLowerCase();
|
|
164
281
|
if (!provider || (state !== "on" && state !== "off")) throw new CliUsageError("provider and on|off are required", USAGE);
|
|
165
282
|
body = { provider, enabled: state === "on" };
|
|
283
|
+
// Optional explicit cap value for this provider only (`ocx models context provider
|
|
284
|
+
// openai on --value 128000`). Mirrors the dashboard's per-provider cap picker; the
|
|
285
|
+
// value never leaks to other providers.
|
|
286
|
+
const value = takeIntegerOption(args, "--value", { min: 1 });
|
|
287
|
+
if (value !== undefined && state !== "on") {
|
|
288
|
+
throw new CliUsageError("--value can only be used with on", USAGE);
|
|
289
|
+
}
|
|
290
|
+
if (value !== undefined) body.value = value;
|
|
166
291
|
} else if (action === "all") {
|
|
167
292
|
const state = args.shift()?.toLowerCase();
|
|
168
293
|
if (state !== "on" && state !== "off") throw new CliUsageError("all requires on|off", USAGE);
|
|
@@ -203,6 +328,9 @@ export async function handleModelsRuntimeCommand(sub: string, argv: string[], de
|
|
|
203
328
|
else if (sub === "disable") action = () => visibility(false, argv, deps);
|
|
204
329
|
else if (sub === "provider") action = () => providerVisibility(argv, deps);
|
|
205
330
|
else if (sub === "selected") action = () => selected(argv, deps);
|
|
331
|
+
else if (sub === "preset") action = () => preset(argv, deps);
|
|
332
|
+
else if (sub === "new-policy") action = () => newPolicy(argv, deps);
|
|
333
|
+
else if (sub === "new-arrivals") action = () => newArrivals(argv, deps);
|
|
206
334
|
else if (sub === "context") action = () => context(argv, deps);
|
|
207
335
|
else if (sub === "shadow") action = () => shadow(argv, deps);
|
|
208
336
|
if (!action) return null;
|