@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/doctor.ts
CHANGED
|
@@ -10,18 +10,41 @@
|
|
|
10
10
|
import { accessSync, constants, existsSync, readFileSync } from "node:fs";
|
|
11
11
|
import { homedir } from "node:os";
|
|
12
12
|
import { dirname, join } from "node:path";
|
|
13
|
-
import { getConfigDir, getConfigPath, readConfigDiagnostics,
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
13
|
+
import { getConfigDir, getConfigPath, readConfigDiagnostics, resolveEnvValue } from "../config";
|
|
14
|
+
import { readPid } from "../config/process-state";
|
|
15
|
+
import { findLiveProxy, type LiveProxy } from "../server/proxy-liveness";
|
|
16
|
+
import { BUN_RUNTIME_SOURCES } from "../lib/bun-runtime";
|
|
17
|
+
import type { BunRuntimeSource } from "../lib/bun-runtime";
|
|
16
18
|
import { maskAccountId } from "../lib/privacy";
|
|
19
|
+
import { tokenCollidesWithAdmin } from "../lib/admin-secrets";
|
|
20
|
+
import { readInstalledServiceToken } from "../lib/service-secrets";
|
|
17
21
|
import { PROXY_ENV_KEYS, proxyEnvPresent } from "../lib/proxy-env";
|
|
18
|
-
import {
|
|
22
|
+
import { LOCAL_MANAGEMENT_READ_PATHS } from "../lib/local-management-capability";
|
|
19
23
|
import { readCodexTokens } from "../codex/auth-collision";
|
|
24
|
+
import { withNativeMainSharedClaim } from "../codex/native-main-claim";
|
|
25
|
+
import { probeNativeProfileRecoveryState, resolveNativeProfileContext } from "../codex/native-profile-store";
|
|
26
|
+
import { NativeProfileError } from "../codex/native-profile-types";
|
|
20
27
|
import { collectOrcaCodexHomeDiagnostic, resolveCodexHomeDir as resolveCodexHomeDirImpl, isWslRuntime, listWslWindowsCodexHomes, wslAutomountRoot, type CodexHomeDeps } from "../codex/home";
|
|
28
|
+
import { scanCodexAgentRolesWithTomlModelFallback } from "../codex/subagent-model-fallback";
|
|
21
29
|
import { findCodexOnPath, isWindowsInteropDir } from "../codex/shim";
|
|
22
30
|
import { countPendingOpencodexHistory } from "../codex/history-provider";
|
|
31
|
+
import {
|
|
32
|
+
inspectCodexCoordinator,
|
|
33
|
+
recoverZeroByteCodexCoordinator,
|
|
34
|
+
type CodexCoordinatorDiagnostic,
|
|
35
|
+
} from "../codex/coordinator-doctor";
|
|
36
|
+
import {
|
|
37
|
+
inspectAbandonedResponseStateTemps,
|
|
38
|
+
reclaimAbandonedResponseStateTemps,
|
|
39
|
+
type ResponseStateTempRecoveryResult,
|
|
40
|
+
} from "../responses/state";
|
|
41
|
+
import {
|
|
42
|
+
CodexUserIdentityRefusal,
|
|
43
|
+
probeCodexCoordinatorNamespace,
|
|
44
|
+
resolveEffectiveUserIdentity,
|
|
45
|
+
} from "../codex/user-identity";
|
|
23
46
|
import { collectProjectCodexConfigWarnings, formatProjectCodexConfigWarningsForDoctor } from "../codex/project-config-warnings";
|
|
24
|
-
import { collectStartupHealth, startupHealthSummary } from "../codex/autostart-health";
|
|
47
|
+
import { collectStartupHealth, formatStartupRoutingDetail, startupHealthSummary } from "../codex/autostart-health";
|
|
25
48
|
import {
|
|
26
49
|
displayCodexRuntimePath,
|
|
27
50
|
loadLastEffortClamp,
|
|
@@ -31,9 +54,41 @@ import {
|
|
|
31
54
|
} from "../codex/runtime";
|
|
32
55
|
import { CODEX_REAUTH_ACTION, collectOAuthHealthEntriesForCli, MASKED_ACCOUNT_FALLBACK, type OAuthHealthEntry } from "../oauth/health";
|
|
33
56
|
import { getAuthRefreshIntentLockPath, getAuthStorePath } from "../oauth/store";
|
|
57
|
+
import {
|
|
58
|
+
fetchBoundLocalManagementRead,
|
|
59
|
+
type LocalManagementReadDeps,
|
|
60
|
+
} from "../server/local-management-read-client";
|
|
34
61
|
export { resolveCodexHomeDir } from "../codex/home";
|
|
35
62
|
|
|
36
|
-
|
|
63
|
+
/**
|
|
64
|
+
* `FAIL` exists for a condition that makes the surface unusable rather than degraded.
|
|
65
|
+
* A review of the #2696 work pointed out that reporting a fully fenced management plane
|
|
66
|
+
* — every `/api/*` returning 503 — at the same level as a directory-permission note
|
|
67
|
+
* misleads the reader about severity.
|
|
68
|
+
*
|
|
69
|
+
* Doctor's own exit code still belongs to the uniform contract in wp3b (devlog 025);
|
|
70
|
+
* this type only fixes what the operator is told.
|
|
71
|
+
*/
|
|
72
|
+
export type OAuthDoctorCheck = { level: "OK" | "WARN" | "FAIL"; message: string };
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Whether any FAIL-level condition was seen during this `runDoctor` pass.
|
|
76
|
+
*
|
|
77
|
+
* Module-scoped and reset at the top of `runDoctor` rather than threaded through, because
|
|
78
|
+
* `runDoctor` reports by direct `console.log` across a dozen sections and has no checks
|
|
79
|
+
* collection to inspect. Reset matters for the test suite, which calls `runDoctor` several
|
|
80
|
+
* times in one process; a sticky flag would make the second call fail because the first did.
|
|
81
|
+
*/
|
|
82
|
+
let doctorSawFailure = false;
|
|
83
|
+
|
|
84
|
+
function recordDoctorFailure(): void {
|
|
85
|
+
doctorSawFailure = true;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** True when the last `runDoctor` pass saw a FAIL-level condition. */
|
|
89
|
+
export function doctorFailed(): boolean {
|
|
90
|
+
return doctorSawFailure;
|
|
91
|
+
}
|
|
37
92
|
|
|
38
93
|
function pathIsWritable(path: string): boolean {
|
|
39
94
|
try {
|
|
@@ -112,6 +167,50 @@ function describeDoctorHealth(entry: OAuthHealthEntry): string {
|
|
|
112
167
|
}
|
|
113
168
|
}
|
|
114
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Detect the management/data-plane credential collision behind #2696.
|
|
172
|
+
*
|
|
173
|
+
* The service exports the service token file as `OPENCODEX_API_AUTH_TOKEN` before
|
|
174
|
+
* starting the proxy. When that value is the admin token, the server treats the
|
|
175
|
+
* management credential as a data-plane admission secret and fences the ENTIRE
|
|
176
|
+
* management plane closed at boot: every `/api/*` returns 503, including on a loopback
|
|
177
|
+
* install that never needed a data-plane secret.
|
|
178
|
+
*
|
|
179
|
+
* `assertNotAdminToken` in src/service.ts now refuses to create this state, but an
|
|
180
|
+
* install made before that guard existed is already broken on disk, and the symptom
|
|
181
|
+
* (every management command failing) points nowhere. This is the check that names it.
|
|
182
|
+
*
|
|
183
|
+
* Observe-only, like the rest of doctor: it compares shapes and never prints, logs, or
|
|
184
|
+
* returns a credential value.
|
|
185
|
+
*/
|
|
186
|
+
export function dataPlaneCredentialCollisionCheck(
|
|
187
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
188
|
+
installedServiceToken: string | null = readInstalledServiceToken(),
|
|
189
|
+
): OAuthDoctorCheck {
|
|
190
|
+
const dataPlane = env.OPENCODEX_API_AUTH_TOKEN?.trim() || installedServiceToken?.trim() || "";
|
|
191
|
+
if (!dataPlane) {
|
|
192
|
+
return { level: "OK", message: "No data-plane token is set, so it cannot collide with the management token." };
|
|
193
|
+
}
|
|
194
|
+
// Same comparison as assertNotAdminToken: minted prefix or configuredAdminToken
|
|
195
|
+
// (env or admin-api-token file). The file token is the one the service wrapper
|
|
196
|
+
// actually exports; inspecting only the doctor process env reported OK on every
|
|
197
|
+
// already-broken install (#2696).
|
|
198
|
+
if (!tokenCollidesWithAdmin(dataPlane, env)) {
|
|
199
|
+
return { level: "OK", message: "Data-plane and management credentials are distinct." };
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
// Not a degradation: while this holds, every /api/* returns 503 and no ocx
|
|
203
|
+
// management command can work at all.
|
|
204
|
+
level: "FAIL",
|
|
205
|
+
message:
|
|
206
|
+
"The data-plane secret (OPENCODEX_API_AUTH_TOKEN or the service token file) holds the "
|
|
207
|
+
+ "management (admin) token, so the proxy fences the whole management API closed and "
|
|
208
|
+
+ "every ocx management command fails with 503. "
|
|
209
|
+
+ "Action: unset OPENCODEX_API_AUTH_TOKEN, replace the service token file with a distinct "
|
|
210
|
+
+ "data-plane key, then re-run `ocx service install` and restart the proxy",
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
115
214
|
/**
|
|
116
215
|
* OAuth reliability checks for `ocx doctor`. Observe-only: never mutates
|
|
117
216
|
* credentials, locks, or networking. Every WARN includes a recovery Action.
|
|
@@ -122,6 +221,8 @@ export async function collectOAuthDoctorChecks(
|
|
|
122
221
|
): Promise<OAuthDoctorCheck[]> {
|
|
123
222
|
const checks: OAuthDoctorCheck[] = [];
|
|
124
223
|
|
|
224
|
+
checks.push(dataPlaneCredentialCollisionCheck());
|
|
225
|
+
|
|
125
226
|
if (isOAuthCredentialStorageWritable()) {
|
|
126
227
|
checks.push({ level: "OK", message: "OAuth credential storage directory is writable for atomic auth.json updates." });
|
|
127
228
|
} else {
|
|
@@ -479,36 +580,75 @@ export type WhamProbeResult = {
|
|
|
479
580
|
authenticated: boolean;
|
|
480
581
|
};
|
|
481
582
|
|
|
583
|
+
type NativeMainDoctorClaim = <T>(operation: () => Promise<T>) => Promise<T>;
|
|
584
|
+
|
|
585
|
+
export interface WhamProbeDeps {
|
|
586
|
+
withNativeMainClaim?: NativeMainDoctorClaim;
|
|
587
|
+
probeNativeMainRecoveryState?: typeof probeNativeProfileRecoveryState;
|
|
588
|
+
}
|
|
589
|
+
|
|
482
590
|
/**
|
|
483
591
|
* Replicate the runtime WHAM fetch shape (same URL, 8s timeout, main-token
|
|
484
592
|
* headers when present) so the probe fails exactly where the real path fails.
|
|
485
593
|
* `fetchImpl` is injectable for testing.
|
|
486
594
|
*/
|
|
487
|
-
export async function probeWham(
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
headers.Authorization = `Bearer ${tokens.access_token}`;
|
|
492
|
-
headers["ChatGPT-Account-Id"] = tokens.account_id;
|
|
493
|
-
}
|
|
595
|
+
export async function probeWham(
|
|
596
|
+
fetchImpl: typeof fetch = fetch,
|
|
597
|
+
deps: WhamProbeDeps = {},
|
|
598
|
+
): Promise<WhamProbeResult> {
|
|
494
599
|
const start = performance.now();
|
|
600
|
+
let authenticated = false;
|
|
495
601
|
try {
|
|
496
|
-
const
|
|
497
|
-
const
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
602
|
+
const context = resolveNativeProfileContext();
|
|
603
|
+
const withClaim = deps.withNativeMainClaim
|
|
604
|
+
?? (<T>(operation: () => Promise<T>) => withNativeMainSharedClaim(context, operation));
|
|
605
|
+
return await withClaim(async () => {
|
|
606
|
+
const recoveryState = (deps.probeNativeMainRecoveryState ?? probeNativeProfileRecoveryState)(context);
|
|
607
|
+
if (recoveryState !== "none") {
|
|
608
|
+
return {
|
|
609
|
+
ok: false,
|
|
610
|
+
status: null,
|
|
611
|
+
durationMs: Math.round(performance.now() - start),
|
|
612
|
+
classification: `native_main_recovery_${recoveryState}`,
|
|
613
|
+
authenticated: false,
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
const tokens = readCodexTokens();
|
|
617
|
+
const headers: Record<string, string> = {};
|
|
618
|
+
if (tokens) {
|
|
619
|
+
headers.Authorization = `Bearer ${tokens.access_token}`;
|
|
620
|
+
headers["ChatGPT-Account-Id"] = tokens.account_id;
|
|
621
|
+
}
|
|
622
|
+
authenticated = !!tokens;
|
|
623
|
+
const resp = await fetchImpl(WHAM_USAGE_URL, { headers, signal: AbortSignal.timeout(PROBE_TIMEOUT_MS) });
|
|
624
|
+
const durationMs = Math.round(performance.now() - start);
|
|
625
|
+
return {
|
|
626
|
+
ok: resp.ok,
|
|
627
|
+
status: resp.status,
|
|
628
|
+
durationMs,
|
|
629
|
+
classification: resp.ok ? "ok" : `http_${resp.status}`,
|
|
630
|
+
authenticated,
|
|
631
|
+
};
|
|
632
|
+
});
|
|
505
633
|
} catch (err) {
|
|
506
634
|
const durationMs = Math.round(performance.now() - start);
|
|
635
|
+
if (
|
|
636
|
+
err instanceof NativeProfileError
|
|
637
|
+
&& (err.code === "NATIVE_MAIN_CLAIM_BUSY" || err.code === "NATIVE_MAIN_CLAIM_UNAVAILABLE")
|
|
638
|
+
) {
|
|
639
|
+
return {
|
|
640
|
+
ok: false,
|
|
641
|
+
status: null,
|
|
642
|
+
durationMs,
|
|
643
|
+
classification: err.code.toLowerCase(),
|
|
644
|
+
authenticated: false,
|
|
645
|
+
};
|
|
646
|
+
}
|
|
507
647
|
const name = err instanceof Error ? err.name : String(err);
|
|
508
648
|
const classification = name === "TimeoutError" || name === "AbortError"
|
|
509
649
|
? "timeout"
|
|
510
650
|
: "connect_error";
|
|
511
|
-
return { ok: false, status: null, durationMs, classification, authenticated
|
|
651
|
+
return { ok: false, status: null, durationMs, classification, authenticated };
|
|
512
652
|
}
|
|
513
653
|
}
|
|
514
654
|
|
|
@@ -523,6 +663,8 @@ export async function probeWham(fetchImpl: typeof fetch = fetch): Promise<WhamPr
|
|
|
523
663
|
export type ServiceMemoryData = {
|
|
524
664
|
pid: number;
|
|
525
665
|
bunVersion: string;
|
|
666
|
+
/** Launch-time provenance; absent for services installed before the marker existed. */
|
|
667
|
+
bunRuntimeSource?: BunRuntimeSource;
|
|
526
668
|
platform: string;
|
|
527
669
|
rss: number;
|
|
528
670
|
heapUsed: number;
|
|
@@ -558,20 +700,28 @@ function observedMemory(data: { rss: number; external?: number; arrayBuffers?: n
|
|
|
558
700
|
}
|
|
559
701
|
|
|
560
702
|
export async function fetchServiceMemory(
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
token: string | null,
|
|
564
|
-
fetchImpl: typeof fetch = fetch,
|
|
703
|
+
target: LiveProxy,
|
|
704
|
+
deps: LocalManagementReadDeps = {},
|
|
565
705
|
): Promise<ServiceMemoryReport> {
|
|
566
706
|
try {
|
|
567
|
-
const
|
|
568
|
-
|
|
569
|
-
|
|
707
|
+
const read = await fetchBoundLocalManagementRead(target, LOCAL_MANAGEMENT_READ_PATHS.systemMemory, {
|
|
708
|
+
...deps,
|
|
709
|
+
timeoutMs: SERVICE_MEMORY_TIMEOUT_MS,
|
|
570
710
|
});
|
|
711
|
+
if (read.kind === "unavailable") {
|
|
712
|
+
return read.reason === "transport"
|
|
713
|
+
? { status: "unreachable", error: "fetch failed" }
|
|
714
|
+
: { status: "unauthorized" };
|
|
715
|
+
}
|
|
716
|
+
const { response: res, targetPid } = read;
|
|
571
717
|
if (res.status === 401 || res.status === 403) return { status: "unauthorized" };
|
|
572
718
|
if (!res.ok) return { status: "unreachable", error: `http ${res.status}` };
|
|
573
719
|
const body = await res.json() as Partial<ServiceMemoryData>;
|
|
574
|
-
if (
|
|
720
|
+
if (
|
|
721
|
+
body.pid !== targetPid
|
|
722
|
+
|| typeof body.bunVersion !== "string"
|
|
723
|
+
|| typeof body.rss !== "number"
|
|
724
|
+
) {
|
|
575
725
|
return { status: "unreachable", error: "malformed response" };
|
|
576
726
|
}
|
|
577
727
|
return {
|
|
@@ -579,6 +729,9 @@ export async function fetchServiceMemory(
|
|
|
579
729
|
data: {
|
|
580
730
|
pid: body.pid,
|
|
581
731
|
bunVersion: body.bunVersion,
|
|
732
|
+
// Allowlisted independently of the server: an unrecognized wire value is
|
|
733
|
+
// treated as absent rather than echoed into user-facing guidance.
|
|
734
|
+
bunRuntimeSource: BUN_RUNTIME_SOURCES.find(source => source === body.bunRuntimeSource),
|
|
582
735
|
platform: typeof body.platform === "string" ? body.platform : "unknown",
|
|
583
736
|
rss: body.rss,
|
|
584
737
|
heapUsed: typeof body.heapUsed === "number" ? body.heapUsed : 0,
|
|
@@ -612,12 +765,118 @@ export async function fetchServiceMemory(
|
|
|
612
765
|
|
|
613
766
|
const mb = (bytes: number): string => `${Math.round(bytes / (1024 * 1024))}MB`;
|
|
614
767
|
|
|
768
|
+
export const RECLAIM_RESPONSE_TEMPS_FLAG = "--reclaim-response-temps";
|
|
769
|
+
export const RECOVER_ZERO_BYTE_COORDINATOR_FLAG = "--recover-zero-byte-coordinator";
|
|
770
|
+
/** Matches the dry run's entry bound so report and reclaim agree on a large backlog. */
|
|
771
|
+
const RESPONSE_TEMP_RECLAIM_MAX_CLEANUPS = 4_096;
|
|
772
|
+
/** Names the subsystem: other components mint temps with the same shape and are not covered. */
|
|
773
|
+
const CLEAN_RESPONSE_TEMP_LINE = " ok No abandoned response-state temp files.";
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Render the abandoned-temp section (testable without console capture).
|
|
777
|
+
*
|
|
778
|
+
* Report is the DEFAULT and reclaim is opt-in: `doctor` is a diagnostic an operator runs
|
|
779
|
+
* to understand a machine, so deleting files as a side effect of asking a question is the
|
|
780
|
+
* wrong default even for cache files.
|
|
781
|
+
*
|
|
782
|
+
* Counts come from `eligible`/`eligibleBytes`, never `matched`: `matched` is incremented
|
|
783
|
+
* before the file-type, age, boot-floor, and liveness gates, so reporting it would tell an
|
|
784
|
+
* operator that live-pid temps and young temps are "abandoned".
|
|
785
|
+
*/
|
|
786
|
+
export function formatResponseTempLines(
|
|
787
|
+
result: ResponseStateTempRecoveryResult,
|
|
788
|
+
reclaimed: boolean,
|
|
789
|
+
): string[] {
|
|
790
|
+
if (reclaimed) {
|
|
791
|
+
if (result.removed === 0 && result.failed === 0) return [CLEAN_RESPONSE_TEMP_LINE];
|
|
792
|
+
const lines = [` ok Reclaimed ${result.removed} abandoned response-state temp file(s), ${mb(result.bytesRemoved)} freed.`];
|
|
793
|
+
if (result.failed > 0) {
|
|
794
|
+
// Never "retried automatically": this command exists for the operator whose proxy will
|
|
795
|
+
// NOT start, and in that state nothing retries anything.
|
|
796
|
+
lines.push(` !! ${result.failed} file(s) could not be removed (in use or locked). Retried on the next reclaim — automatically while the proxy runs, otherwise re-run this command.`);
|
|
797
|
+
}
|
|
798
|
+
// `truncated`, not `eligible > removed + failed`: outside a dry run every eligible entry
|
|
799
|
+
// is unlinked or failed on the same iteration it is counted, so those two are always
|
|
800
|
+
// equal and the comparison never fired. An operator with a backlog past the budget was
|
|
801
|
+
// told the reclaim had finished.
|
|
802
|
+
if (result.truncated) {
|
|
803
|
+
lines.push(" !! Cleanup budget reached; files remain. Run the command again to continue.");
|
|
804
|
+
}
|
|
805
|
+
return lines;
|
|
806
|
+
}
|
|
807
|
+
if (result.eligible === 0) return [CLEAN_RESPONSE_TEMP_LINE];
|
|
808
|
+
const lines = [
|
|
809
|
+
` !! ${result.eligible} abandoned response-state temp file(s), ${mb(result.eligibleBytes)} reclaimable.`,
|
|
810
|
+
" These are interrupted snapshot writes (continuation cache only) and are safe to remove.",
|
|
811
|
+
" Reclaim them with: ocx doctor --reclaim-response-temps",
|
|
812
|
+
];
|
|
813
|
+
// The dry run skips the cleanup budget but is still bounded by the entry cap, so a large
|
|
814
|
+
// enough backlog makes this a floor rather than a total. Say so instead of letting an
|
|
815
|
+
// operator size the problem from a truncated count.
|
|
816
|
+
if (result.truncated) lines.push(" Scan stopped at its entry budget; the real total is higher.");
|
|
817
|
+
return lines;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
export function formatCoordinatorDoctorLines(diagnostic: CodexCoordinatorDiagnostic): string[] {
|
|
821
|
+
const pathLine = diagnostic.path ? [` path: ${diagnostic.path}`] : [];
|
|
822
|
+
const evidenceLines = "evidence" in diagnostic && diagnostic.evidence
|
|
823
|
+
? [
|
|
824
|
+
` size: ${diagnostic.evidence.sizeBytes} bytes; user_version: ${diagnostic.evidence.schemaVersion}`,
|
|
825
|
+
` tables: ${diagnostic.evidence.tables.length === 0 ? "none" : diagnostic.evidence.tables.join(", ")}`,
|
|
826
|
+
` transition rows: ${diagnostic.evidence.transitionRows ?? "not inspected"}; singleton=1 rows: ${diagnostic.evidence.singletonRows ?? "not inspected"}`,
|
|
827
|
+
]
|
|
828
|
+
: [];
|
|
829
|
+
switch (diagnostic.kind) {
|
|
830
|
+
case "absent":
|
|
831
|
+
return [" ok native-write coordinator not created yet", ...pathLine];
|
|
832
|
+
case "ready":
|
|
833
|
+
return [" ok native-write coordinator has an authoritative transition row", ...pathLine, ...evidenceLines];
|
|
834
|
+
case "zero-byte":
|
|
835
|
+
return [
|
|
836
|
+
" !! native-write coordinator is a zero-byte remnant and has no authority",
|
|
837
|
+
...pathLine,
|
|
838
|
+
...evidenceLines,
|
|
839
|
+
` Action: stop the OpenCodex proxy/service, then run ocx doctor ${RECOVER_ZERO_BYTE_COORDINATOR_FLAG} --yes`,
|
|
840
|
+
];
|
|
841
|
+
case "unversioned-empty":
|
|
842
|
+
return [
|
|
843
|
+
" !! native-write coordinator is a non-empty unversioned database; automatic recovery is refused",
|
|
844
|
+
...pathLine,
|
|
845
|
+
...evidenceLines,
|
|
846
|
+
];
|
|
847
|
+
case "rowless":
|
|
848
|
+
return [
|
|
849
|
+
" !! native-write coordinator has schema version 1 but no authoritative row; automatic recovery is refused",
|
|
850
|
+
...pathLine,
|
|
851
|
+
...evidenceLines,
|
|
852
|
+
];
|
|
853
|
+
case "unversioned-nonempty":
|
|
854
|
+
return [
|
|
855
|
+
" !! native-write coordinator is unversioned and contains unknown tables; automatic recovery is refused",
|
|
856
|
+
...pathLine,
|
|
857
|
+
...evidenceLines,
|
|
858
|
+
];
|
|
859
|
+
case "unsupported":
|
|
860
|
+
return [
|
|
861
|
+
` !! native-write coordinator schema version ${diagnostic.version} is unsupported; automatic recovery is refused`,
|
|
862
|
+
...pathLine,
|
|
863
|
+
...evidenceLines,
|
|
864
|
+
];
|
|
865
|
+
case "changed":
|
|
866
|
+
return [" -- native-write coordinator changed during diagnosis; re-run ocx doctor", ...pathLine];
|
|
867
|
+
case "unsafe":
|
|
868
|
+
return [` !! native-write coordinator path is unsafe: ${diagnostic.reason}`, ...pathLine];
|
|
869
|
+
case "unreadable":
|
|
870
|
+
return [` !! native-write coordinator is unreadable: ${diagnostic.reason}`, ...pathLine, ...evidenceLines];
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
615
874
|
/** Render the doctor "Memory / runtime" section lines (testable without console capture). */
|
|
616
875
|
export function formatServiceMemoryLines(report: ServiceMemoryReport): string[] {
|
|
617
876
|
const lines: string[] = [];
|
|
618
877
|
lines.push(` -- doctor process Bun ${Bun.version} (this is NOT the service process)`);
|
|
619
878
|
if (report.status === "unauthorized") {
|
|
620
|
-
lines.push(" --
|
|
879
|
+
lines.push(" -- local diagnostic capability unavailable — restart the running proxy with this OpenCodex version");
|
|
621
880
|
return lines;
|
|
622
881
|
}
|
|
623
882
|
if (report.status === "unreachable") {
|
|
@@ -652,12 +911,22 @@ export function formatServiceMemoryLines(report: ServiceMemoryReport): string[]
|
|
|
652
911
|
} else {
|
|
653
912
|
lines.push(" !! high RSS, indeterminate split — capture two doctor runs over time to see the trend");
|
|
654
913
|
}
|
|
655
|
-
// Version-claiming (never binary-claiming): the endpoint cannot distinguish
|
|
656
|
-
// the bundled binary from an OPENCODEX_BUN_PATH override of the same version.
|
|
657
914
|
if (d.platform === "win32" && d.eagerRelay?.reason === "auto-known-bad") {
|
|
658
915
|
lines.push(` service is running Bun ${d.bunVersion} on Windows — a version affected by the upstream Bun memory issue.`);
|
|
659
|
-
|
|
660
|
-
|
|
916
|
+
// The remediation depends on how the SERVICE was launched, which only the
|
|
917
|
+
// launch-time marker can answer. Telling someone to set OPENCODEX_BUN_PATH
|
|
918
|
+
// when it is already set is the bug this branch exists to avoid (#848).
|
|
919
|
+
if (d.bunRuntimeSource === "override") {
|
|
920
|
+
lines.push(` OPENCODEX_BUN_PATH is already active for this service — the override runtime is itself an affected version (unvalidated — own risk).`);
|
|
921
|
+
lines.push(" Options: point the override at a different runtime, or opt into streamMode \"eager-relay\" via PUT /api/settings (crash risk on this runtime; see docs).");
|
|
922
|
+
} else if (d.bunRuntimeSource === undefined) {
|
|
923
|
+
lines.push(" this service records no runtime origin (installed before provenance tracking), so OpenCodex cannot tell whether an override is already active.");
|
|
924
|
+
lines.push(" Reinstall the service to record it, or opt into streamMode \"eager-relay\" via PUT /api/settings (crash risk on this runtime; see docs).");
|
|
925
|
+
} else {
|
|
926
|
+
const origin = d.bunRuntimeSource === "process" ? "the runtime that launched it" : "the bundled runtime";
|
|
927
|
+
lines.push(` the service is using ${origin}. Options: wait for a bundled runtime update, or set OPENCODEX_BUN_PATH to a runtime you trust (unvalidated — own risk),`);
|
|
928
|
+
lines.push(" or opt into streamMode \"eager-relay\" via PUT /api/settings (crash risk on this runtime; see docs).");
|
|
929
|
+
}
|
|
661
930
|
}
|
|
662
931
|
return lines;
|
|
663
932
|
}
|
|
@@ -671,11 +940,21 @@ export function proxyDownRestartHint(input: {
|
|
|
671
940
|
proxyRunning: boolean;
|
|
672
941
|
port: number;
|
|
673
942
|
serviceViable: boolean;
|
|
943
|
+
/** Absent means "unknown"; the hint then keeps its pre-repair wording. */
|
|
944
|
+
serviceInstalled?: boolean;
|
|
945
|
+
serviceConflict?: boolean;
|
|
674
946
|
}): string | null {
|
|
675
947
|
if (input.proxyRunning) return null;
|
|
948
|
+
// `serviceViable` alone conflates "no service at all" with "registered but stale or
|
|
949
|
+
// stopped". Only the first wants `install`: re-registering an existing service costs a
|
|
950
|
+
// UAC prompt on Windows and can switch a WinSW backend to Task Scheduler. A conflict
|
|
951
|
+
// still needs uninstall-then-install, which repairService() refuses outright.
|
|
952
|
+
const installedButBroken = input.serviceInstalled === true && input.serviceConflict !== true;
|
|
676
953
|
const restart = input.serviceViable
|
|
677
954
|
? "Restart it with 'ocx service start' (service installed) or 'ocx start'."
|
|
678
|
-
:
|
|
955
|
+
: installedButBroken
|
|
956
|
+
? "Restart it with 'ocx start', or refresh the installed service: 'ocx service repair'."
|
|
957
|
+
: "Restart it with 'ocx start', or install the persistent service: 'ocx service install'.";
|
|
679
958
|
return `The ocx proxy is not running. Codex/Claude clients pinned to 127.0.0.1:${input.port} fail with errors like "error sending request for url (http://127.0.0.1:${input.port}/v1/responses)". ${restart}`;
|
|
680
959
|
}
|
|
681
960
|
|
|
@@ -704,7 +983,37 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
704
983
|
return;
|
|
705
984
|
}
|
|
706
985
|
|
|
986
|
+
if (args.includes(RECOVER_ZERO_BYTE_COORDINATOR_FLAG)) {
|
|
987
|
+
if (!args.includes("--yes")) {
|
|
988
|
+
console.log(`Recovery is explicit and creates a same-directory backup. Re-run: ocx doctor ${RECOVER_ZERO_BYTE_COORDINATOR_FLAG} --yes`);
|
|
989
|
+
process.exitCode = 1;
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
const diagnostics = readConfigDiagnostics().config;
|
|
993
|
+
const live = await findLiveProxy({
|
|
994
|
+
configFn: () => ({ port: diagnostics.port, hostname: diagnostics.hostname }),
|
|
995
|
+
});
|
|
996
|
+
if (live) {
|
|
997
|
+
console.log(`Recovery refused: OpenCodex proxy pid ${live.pid} is still running. Stop the proxy/service and retry.`);
|
|
998
|
+
process.exitCode = 1;
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
const recovered = recoverZeroByteCodexCoordinator();
|
|
1002
|
+
if (!recovered.ok) {
|
|
1003
|
+
console.log(`Recovery refused: ${recovered.reason}.`);
|
|
1004
|
+
process.exitCode = 1;
|
|
1005
|
+
return;
|
|
1006
|
+
}
|
|
1007
|
+
console.log(`Moved the non-authoritative coordinator to ${recovered.backupPath}`);
|
|
1008
|
+
console.log("Run `ocx sync` to retry Codex config injection. The backup was preserved and no Codex config/catalog file was changed by recovery.");
|
|
1009
|
+
process.exitCode = 0;
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
707
1013
|
console.log("opencodex doctor\n");
|
|
1014
|
+
// Reset per pass: the suite drives runDoctor several times in one process, and a sticky
|
|
1015
|
+
// flag would fail the second call because the first saw a problem.
|
|
1016
|
+
doctorSawFailure = false;
|
|
708
1017
|
|
|
709
1018
|
// Ordering note: the memory/runtime section renders after "Running proxy
|
|
710
1019
|
// process proxy env" below; helpers live above runDoctor for testability.
|
|
@@ -719,6 +1028,26 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
719
1028
|
console.log(` ${row.exists ? "ok " : "-- "} ${row.label}: ${row.path}${flags ? ` (${flags})` : ""}`);
|
|
720
1029
|
}
|
|
721
1030
|
|
|
1031
|
+
// Runs without the proxy on purpose: the worst accumulation happens when the proxy will
|
|
1032
|
+
// not start, which is exactly when the in-process periodic reclaim never ticks.
|
|
1033
|
+
const reclaimTemps = args.includes(RECLAIM_RESPONSE_TEMPS_FLAG);
|
|
1034
|
+
console.log("\nResponse-state temp files");
|
|
1035
|
+
// A typo must not silently degrade into "nothing to reclaim" — the operator would read the
|
|
1036
|
+
// report as an answer to a question they never actually asked.
|
|
1037
|
+
for (const arg of args) {
|
|
1038
|
+
if (arg !== RECLAIM_RESPONSE_TEMPS_FLAG && /^--reclaim/.test(arg)) {
|
|
1039
|
+
console.log(` !! Unrecognized flag ${arg}; did you mean ${RECLAIM_RESPONSE_TEMPS_FLAG}? Reporting only.`);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
for (const line of formatResponseTempLines(
|
|
1043
|
+
// The reclaim budget matches the report budget: a report bounded by entries and a removal
|
|
1044
|
+
// bounded by a smaller cleanup cap would tell an operator 816 and then silently free 512.
|
|
1045
|
+
reclaimTemps
|
|
1046
|
+
? reclaimAbandonedResponseStateTemps({ maxCleanups: RESPONSE_TEMP_RECLAIM_MAX_CLEANUPS })
|
|
1047
|
+
: inspectAbandonedResponseStateTemps(),
|
|
1048
|
+
reclaimTemps,
|
|
1049
|
+
)) console.log(line);
|
|
1050
|
+
|
|
722
1051
|
const orcaHome = collectOrcaCodexHomeDiagnostic();
|
|
723
1052
|
console.log("\nCodex app home targeting");
|
|
724
1053
|
console.log(` ${orcaHome.mismatch ? "!! " : "ok "} Effective Codex home: ${orcaHome.effectiveCodexHome}`);
|
|
@@ -733,7 +1062,7 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
733
1062
|
const startup = collectStartupHealth(doctorConfig);
|
|
734
1063
|
console.log("\nCodex restart safety");
|
|
735
1064
|
console.log(` ${startup.rebootSafe ? "ok " : "!! "} ${startupHealthSummary(startup)}`);
|
|
736
|
-
console.log(`
|
|
1065
|
+
console.log(` ${formatStartupRoutingDetail(startup)}`);
|
|
737
1066
|
|
|
738
1067
|
console.log("\nCodex runtime selection");
|
|
739
1068
|
{
|
|
@@ -769,10 +1098,20 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
769
1098
|
const live = await findLiveProxy({
|
|
770
1099
|
configFn: () => ({ port: doctorConfig.port, hostname: doctorConfig.hostname }),
|
|
771
1100
|
});
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
1101
|
+
|
|
1102
|
+
// Mirrors `ocx status` through the same comparison rather than a second implementation:
|
|
1103
|
+
// two diagnostics disagreeing about whether an install is stale is worse than one (#2701).
|
|
1104
|
+
// No extra probe -- findLiveProxy already carried the version back.
|
|
1105
|
+
{
|
|
1106
|
+
const { packageVersion } = await import("./help");
|
|
1107
|
+
const { computeVersionSkew } = await import("./version-skew");
|
|
1108
|
+
const skew = computeVersionSkew(packageVersion(), live?.version);
|
|
1109
|
+
if (skew.skewed && skew.warning) {
|
|
1110
|
+
console.log(`!! ${skew.warning}`);
|
|
1111
|
+
} else if (skew.proxyVersion !== null) {
|
|
1112
|
+
console.log(`ok ocx ${skew.cliVersion} matches the running proxy`);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
776
1115
|
|
|
777
1116
|
const currentProxyEnv = collectProxyEnv();
|
|
778
1117
|
const configuredProxy = collectConfiguredProxy();
|
|
@@ -812,13 +1151,11 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
812
1151
|
|
|
813
1152
|
console.log("\nMemory / runtime");
|
|
814
1153
|
{
|
|
815
|
-
|
|
816
|
-
if (!runtime || !live) {
|
|
1154
|
+
if (!live) {
|
|
817
1155
|
console.log(` -- doctor process Bun ${Bun.version} (this is NOT the service process)`);
|
|
818
1156
|
console.log(" -- no running ocx proxy found (no live pid/runtime record)");
|
|
819
1157
|
} else {
|
|
820
|
-
const
|
|
821
|
-
const report = await fetchServiceMemory(gracefulStopHost(runtime.hostname), runtime.port, token);
|
|
1158
|
+
const report = await fetchServiceMemory(live);
|
|
822
1159
|
for (const line of formatServiceMemoryLines(report)) console.log(line);
|
|
823
1160
|
}
|
|
824
1161
|
}
|
|
@@ -829,17 +1166,41 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
829
1166
|
console.log(` ${probe.ok ? "ok " : "-- "} ${WHAM_USAGE_URL}`);
|
|
830
1167
|
console.log(` ${detail}, ${probe.durationMs}ms, ${probe.authenticated ? "authenticated" : "unauthenticated"}`);
|
|
831
1168
|
|
|
832
|
-
// Design B upgrade visibility:
|
|
833
|
-
//
|
|
834
|
-
//
|
|
835
|
-
console.log("\nCodex history
|
|
1169
|
+
// Design B upgrade visibility: only the backup manifest authorizes restoring provider
|
|
1170
|
+
// metadata. Bare routed rows have unknown provenance and remain unchanged. This read-only
|
|
1171
|
+
// probe reports manifest work and database readability; it never mutates.
|
|
1172
|
+
console.log("\nCodex history metadata restore");
|
|
1173
|
+
// The history failure messages point here; make the visit worthwhile by
|
|
1174
|
+
// probing the coordinator namespace the locks live in. The probe exercises
|
|
1175
|
+
// identity, runtime-root, and permission checks without taking any lock or
|
|
1176
|
+
// creating anything (a doctor run must observe, not initialize).
|
|
1177
|
+
try {
|
|
1178
|
+
const identity = resolveEffectiveUserIdentity();
|
|
1179
|
+
const probe = probeCodexCoordinatorNamespace(identity);
|
|
1180
|
+
if (probe.status === "missing") {
|
|
1181
|
+
console.log(" ok history coordinator namespace not created yet (no history operation has run)");
|
|
1182
|
+
} else {
|
|
1183
|
+
console.log(" ok history coordinator namespace resolves");
|
|
1184
|
+
}
|
|
1185
|
+
} catch (cause) {
|
|
1186
|
+
const reason = cause instanceof CodexUserIdentityRefusal ? cause.message : String(cause);
|
|
1187
|
+
console.log(` -- history coordinator namespace refused: ${reason}`);
|
|
1188
|
+
}
|
|
1189
|
+
console.log("\nCodex native-write coordinator");
|
|
1190
|
+
for (const line of formatCoordinatorDoctorLines(inspectCodexCoordinator())) console.log(line);
|
|
836
1191
|
const pending = countPendingOpencodexHistory();
|
|
837
1192
|
if (pending.failed) {
|
|
838
|
-
|
|
1193
|
+
if (pending.failureReason === "busy") {
|
|
1194
|
+
console.log(" -- history database, backup manifest, or rollout file is busy — exact metadata restore is pending");
|
|
1195
|
+
} else if (pending.failureReason === "permission") {
|
|
1196
|
+
console.log(" -- state DB or backup manifest access was denied — restore state unknown");
|
|
1197
|
+
} else {
|
|
1198
|
+
console.log(" -- backup manifest or restore target failed integrity checks — manual review required");
|
|
1199
|
+
}
|
|
839
1200
|
} else if (pending.pendingRows === 0 && pending.backupEntries === 0) {
|
|
840
|
-
console.log(" ok no
|
|
1201
|
+
console.log(" ok no manifest-backed provider metadata pending; untracked routed history is unchanged");
|
|
841
1202
|
} else {
|
|
842
|
-
console.log(` -- ${pending.
|
|
1203
|
+
console.log(` -- ${pending.backupEntries} backup manifest entr${pending.backupEntries === 1 ? "y" : "ies"} pending exact metadata restore`);
|
|
843
1204
|
}
|
|
844
1205
|
|
|
845
1206
|
console.log("\nProject Codex configs");
|
|
@@ -852,6 +1213,15 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
852
1213
|
}
|
|
853
1214
|
}
|
|
854
1215
|
|
|
1216
|
+
console.log("\nCodex agent role files");
|
|
1217
|
+
const tomlFallbackRoles = scanCodexAgentRolesWithTomlModelFallback(resolveCodexHomeDirImpl());
|
|
1218
|
+
if (tomlFallbackRoles.length === 0) {
|
|
1219
|
+
console.log(" ok no per-role model_fallback fields in $CODEX_HOME/agents/*.toml");
|
|
1220
|
+
} else {
|
|
1221
|
+
console.log(` [WARN] ${tomlFallbackRoles.length} agent role file${tomlFallbackRoles.length === 1 ? "" : "s"} contain${tomlFallbackRoles.length === 1 ? "s" : ""} \`model_fallback\`: ${tomlFallbackRoles.join(", ")}`);
|
|
1222
|
+
console.log(" Codex >= 0.146 rejects that field as unknown and skips the whole role. Move the chains to opencodex config `subagentModelFallbackByModel` (keyed by primary model) and remove the field from the TOML files.");
|
|
1223
|
+
}
|
|
1224
|
+
|
|
855
1225
|
const dual = collectWslDualInstall();
|
|
856
1226
|
if (dual.wsl) {
|
|
857
1227
|
console.log("\nWSL Codex installs");
|
|
@@ -871,6 +1241,12 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
871
1241
|
console.log("\nOAuth reliability");
|
|
872
1242
|
for (const check of await collectOAuthDoctorChecks()) {
|
|
873
1243
|
console.log(` [${check.level}] ${check.message}`);
|
|
1244
|
+
// A diagnostic that always exits 0 cannot gate anything, which defeats the point of
|
|
1245
|
+
// running it from a script (#2697's sibling defect). FAIL is the level reserved for a
|
|
1246
|
+
// surface that is unusable rather than degraded, so it -- and only it -- fails the
|
|
1247
|
+
// command. WARN stays exit 0 on purpose: warning on a degraded-but-working install
|
|
1248
|
+
// must not break a pipeline that is legitimately green.
|
|
1249
|
+
if (check.level === "FAIL") recordDoctorFailure();
|
|
874
1250
|
}
|
|
875
1251
|
|
|
876
1252
|
// #857: a running Codex app-server can keep an older in-memory catalog than
|
|
@@ -878,7 +1254,7 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
878
1254
|
const { collectCodexAppServerCatalogState } = await import("../codex/app-server-processes");
|
|
879
1255
|
const catalogState = collectCodexAppServerCatalogState();
|
|
880
1256
|
if (catalogState.state === "stale") {
|
|
881
|
-
console.log(` [WARN] Codex app-server (PID(s): ${catalogState.processes.map(p => p.pid).join(", ")}) started before the on-disk catalog changed; its in-memory model list disagrees with ocx. Action: restart Codex (or run \`ocx sync --restart-codex\`)`);
|
|
1257
|
+
console.log(` [WARN] Codex app-server (PID(s): ${catalogState.processes.map(p => p.pid).join(", ")}) started before the on-disk catalog changed; its in-memory model list disagrees with ocx. Action: restart Codex (or run \`ocx sync --restart-codex\`; on Windows the desktop app may need \`ocx sync --restart-desktop-app\`)`);
|
|
882
1258
|
} else if (catalogState.state === "unknown") {
|
|
883
1259
|
console.log(" [WARN] Could not verify whether the running Codex app-server's model catalog is current (start time or catalog unreadable). Action: if the model list looks stale, restart Codex");
|
|
884
1260
|
} else if (catalogState.state === "fresh") {
|
|
@@ -891,6 +1267,8 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
891
1267
|
proxyRunning: Boolean(live),
|
|
892
1268
|
port: live?.port ?? doctorConfig.port ?? 10100,
|
|
893
1269
|
serviceViable: startup.serviceViable,
|
|
1270
|
+
serviceInstalled: startup.serviceInstalled,
|
|
1271
|
+
serviceConflict: startup.serviceConflict,
|
|
894
1272
|
});
|
|
895
1273
|
if (proxyDown) hints.push(proxyDown);
|
|
896
1274
|
for (const row of providerApiKeys) {
|
|
@@ -913,8 +1291,14 @@ export async function runDoctor(args: string[] = []): Promise<void> {
|
|
|
913
1291
|
}
|
|
914
1292
|
}
|
|
915
1293
|
}
|
|
916
|
-
if (pending.failed
|
|
917
|
-
hints.push("
|
|
1294
|
+
if (pending.failed && pending.failureReason === "busy") {
|
|
1295
|
+
hints.push("Backed-up history metadata is pending or its state is unreadable. The running proxy retries exact restoration automatically; to force it now, close the Codex app and run 'ocx sync'. Untracked routed history is not relabeled.");
|
|
1296
|
+
} else if (pending.failed && pending.failureReason === "permission") {
|
|
1297
|
+
hints.push("Backed-up history metadata could not be inspected because access was denied. Fix access to the reported Codex history paths, then run 'ocx sync'; repeated retries do not repair permissions.");
|
|
1298
|
+
} else if (pending.failed) {
|
|
1299
|
+
hints.push("The history manifest or its target is invalid or changed. Preserve both, inspect the manifest/database/rollout identity, and do not repeatedly run 'ocx sync' until the mismatch is understood. Untracked routed history is not relabeled.");
|
|
1300
|
+
} else if (pending.backupEntries > 0) {
|
|
1301
|
+
hints.push("Backed-up history metadata is pending. The running proxy retries exact restoration automatically; to force it now, close the Codex app and run 'ocx sync'. Untracked routed history is not relabeled.");
|
|
918
1302
|
}
|
|
919
1303
|
if (dual.dualInstall && !dual.effectiveIsWindowsMount) {
|
|
920
1304
|
hints.push(`Codex is installed on BOTH WSL and Windows. Each side keeps its own ~/.codex (logins, config, catalog are separate); ocx here manages the Linux one. To share a single home, set CODEX_HOME=${dual.windowsCodexHomes[0] ?? `${dual.automountRoot}/c/Users/<you>/.codex`} in WSL (drvfs file locking is less reliable).`);
|