@yansigit/opencodex 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS_INSTALL.md +109 -0
- package/LICENSE +21 -0
- package/README.md +303 -0
- package/assets/architecture.png +0 -0
- package/assets/banner.png +0 -0
- package/assets/claude-code-models.gif +0 -0
- package/assets/codex-app-picker.png +0 -0
- package/bin/ocx.mjs +587 -0
- package/bin/package-main.mjs +9 -0
- package/gui/dist/assets/index-BNJ7r4Gd.js +102 -0
- package/gui/dist/assets/index-CGoDO3uO.css +1 -0
- package/gui/dist/favicon.png +0 -0
- package/gui/dist/icons.svg +24 -0
- package/gui/dist/index.html +25 -0
- package/gui/dist/logo.png +0 -0
- package/gui/dist/provider-icons/alibaba-color.svg +1 -0
- package/gui/dist/provider-icons/antigravity-color.svg +1 -0
- package/gui/dist/provider-icons/claude-color.svg +1 -0
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -0
- package/gui/dist/provider-icons/cursor-color.svg +2 -0
- package/gui/dist/provider-icons/deepseek-color.svg +1 -0
- package/gui/dist/provider-icons/discord.svg +1 -0
- package/gui/dist/provider-icons/firepass-color.svg +1 -0
- package/gui/dist/provider-icons/fireworks-color.svg +1 -0
- package/gui/dist/provider-icons/gemini-color.svg +1 -0
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
- package/gui/dist/provider-icons/grok.svg +1 -0
- package/gui/dist/provider-icons/groq-color.svg +1 -0
- package/gui/dist/provider-icons/huggingface-color.svg +1 -0
- package/gui/dist/provider-icons/kimi-color.svg +1 -0
- package/gui/dist/provider-icons/kiro-color.svg +15 -0
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
- package/gui/dist/provider-icons/mistral-color.svg +1 -0
- package/gui/dist/provider-icons/moonshot-color.svg +1 -0
- package/gui/dist/provider-icons/nvidia-color.svg +1 -0
- package/gui/dist/provider-icons/ollama-color.svg +1 -0
- package/gui/dist/provider-icons/openai.svg +1 -0
- package/gui/dist/provider-icons/opencode.svg +2 -0
- package/gui/dist/provider-icons/openrouter-color.svg +1 -0
- package/gui/dist/provider-icons/pi.svg +21 -0
- package/gui/dist/provider-icons/qianfan-color.svg +1 -0
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
- package/gui/dist/provider-icons/telegram.svg +1 -0
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/vllm-color.svg +1 -0
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
- package/package.json +108 -0
- package/src/AGENTS.md +28 -0
- package/src/adapters/anthropic-image-guard.ts +251 -0
- package/src/adapters/anthropic-image-normalize.ts +518 -0
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +1327 -0
- package/src/adapters/azure.ts +36 -0
- package/src/adapters/base.ts +121 -0
- package/src/adapters/client-fingerprint.ts +65 -0
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +601 -0
- package/src/adapters/cursor/arg-codec.ts +38 -0
- package/src/adapters/cursor/arg-normalize.ts +104 -0
- package/src/adapters/cursor/checkpoint-store.ts +303 -0
- package/src/adapters/cursor/cursor-errors.ts +288 -0
- package/src/adapters/cursor/discovery.ts +333 -0
- package/src/adapters/cursor/effort-map.ts +151 -0
- package/src/adapters/cursor/exec-policy.ts +88 -0
- package/src/adapters/cursor/framing.ts +250 -0
- package/src/adapters/cursor/gen/agent_pb.ts +15274 -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/kv-store.ts +52 -0
- package/src/adapters/cursor/live-models.ts +269 -0
- package/src/adapters/cursor/live-smoke-gate.ts +41 -0
- package/src/adapters/cursor/live-transport.ts +1653 -0
- package/src/adapters/cursor/mcp-config.ts +42 -0
- package/src/adapters/cursor/mcp-manager.ts +333 -0
- package/src/adapters/cursor/message-mapper.ts +49 -0
- package/src/adapters/cursor/native-exec-common.ts +76 -0
- package/src/adapters/cursor/native-exec-desktop.ts +184 -0
- package/src/adapters/cursor/native-exec-fs.ts +332 -0
- package/src/adapters/cursor/native-exec-mcp.ts +153 -0
- package/src/adapters/cursor/native-exec-network.ts +43 -0
- package/src/adapters/cursor/native-exec-shell.ts +547 -0
- package/src/adapters/cursor/native-exec-tools.ts +118 -0
- package/src/adapters/cursor/native-exec.ts +663 -0
- package/src/adapters/cursor/protobuf-events.ts +1381 -0
- package/src/adapters/cursor/protobuf-request.ts +1032 -0
- package/src/adapters/cursor/request-builder.ts +461 -0
- package/src/adapters/cursor/thread-continuity.ts +67 -0
- package/src/adapters/cursor/tool-definitions.ts +735 -0
- package/src/adapters/cursor/tool-result-normalize.ts +92 -0
- package/src/adapters/cursor/transport-retry.ts +132 -0
- package/src/adapters/cursor/transport.ts +79 -0
- package/src/adapters/cursor/types.ts +79 -0
- package/src/adapters/cursor.ts +322 -0
- package/src/adapters/google-antigravity-hosts.ts +48 -0
- package/src/adapters/google-antigravity-replay.ts +827 -0
- package/src/adapters/google-antigravity-tools.ts +105 -0
- package/src/adapters/google-antigravity-wire.ts +141 -0
- package/src/adapters/google-errors.ts +92 -0
- package/src/adapters/google-http.ts +460 -0
- package/src/adapters/google-tool-schema.ts +238 -0
- package/src/adapters/google-truncation.ts +24 -0
- package/src/adapters/google-wire-compiler.ts +232 -0
- package/src/adapters/google.ts +1377 -0
- package/src/adapters/identity.ts +77 -0
- package/src/adapters/image.ts +23 -0
- package/src/adapters/kiro-constants.ts +16 -0
- package/src/adapters/kiro-errors.ts +208 -0
- package/src/adapters/kiro-events.ts +197 -0
- package/src/adapters/kiro-images.ts +129 -0
- package/src/adapters/kiro-retry.ts +312 -0
- package/src/adapters/kiro-thinking.ts +112 -0
- package/src/adapters/kiro-tool-fallback.ts +36 -0
- package/src/adapters/kiro-tools.ts +224 -0
- package/src/adapters/kiro-truncation.ts +33 -0
- package/src/adapters/kiro-wire.ts +129 -0
- package/src/adapters/kiro.ts +1936 -0
- package/src/adapters/mimo-free.ts +280 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1980 -0
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +1911 -0
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/run-turn-queue.ts +114 -0
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +154 -0
- package/src/adapters/upstream-http-error.ts +48 -0
- package/src/adapters/xai-web-search.ts +185 -0
- package/src/bridge.ts +1986 -0
- package/src/chat/inbound.ts +319 -0
- package/src/chat/outbound.ts +821 -0
- package/src/claude/agents-inject.ts +266 -0
- package/src/claude/alias.ts +149 -0
- package/src/claude/auth-detect.ts +229 -0
- package/src/claude/auth-mode-migration.ts +32 -0
- package/src/claude/auth-mode.ts +62 -0
- package/src/claude/context-windows.ts +205 -0
- package/src/claude/desktop-3p-guard.ts +35 -0
- package/src/claude/desktop-3p-paths.ts +84 -0
- package/src/claude/desktop-3p.ts +615 -0
- package/src/claude/desktop-health.ts +26 -0
- package/src/claude/desktop-profile.ts +263 -0
- package/src/claude/gateway-cache.ts +107 -0
- package/src/claude/inbound-debug.ts +163 -0
- package/src/claude/inbound.ts +578 -0
- package/src/claude/model-info.ts +174 -0
- package/src/claude/outbound.ts +926 -0
- package/src/cli/access.ts +108 -0
- package/src/cli/account-api.ts +302 -0
- package/src/cli/account-auth.ts +250 -0
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +737 -0
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +299 -0
- package/src/cli/agent-driven.ts +70 -0
- package/src/cli/agent.ts +290 -0
- package/src/cli/catalog-prewarm.ts +27 -0
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +213 -0
- package/src/cli/claude.ts +355 -0
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +47 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +127 -0
- package/src/cli/config-command.ts +209 -0
- package/src/cli/debug.ts +228 -0
- package/src/cli/dispatch.ts +585 -0
- package/src/cli/doctor.ts +1202 -0
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +213 -0
- package/src/cli/help.ts +101 -0
- package/src/cli/index.ts +973 -0
- package/src/cli/init.ts +211 -0
- package/src/cli/integrations.ts +260 -0
- package/src/cli/interactive-confirm.ts +133 -0
- 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 +245 -0
- package/src/cli/models.ts +422 -0
- package/src/cli/observe.ts +206 -0
- package/src/cli/opencode.ts +588 -0
- package/src/cli/provider-replit.ts +232 -0
- package/src/cli/provider-runtime.ts +179 -0
- package/src/cli/provider.ts +492 -0
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +422 -0
- package/src/cli/replit-gateway-key-input.ts +138 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +328 -0
- package/src/cli/star-prompt.ts +211 -0
- package/src/cli/status-oauth.ts +78 -0
- package/src/cli/status.ts +328 -0
- package/src/cli/system-command.ts +112 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +199 -0
- package/src/cli/v2.ts +268 -0
- package/src/cli.ts +10 -0
- package/src/clients/config-export.ts +1704 -0
- package/src/codex/account-id.ts +34 -0
- package/src/codex/account-label.ts +47 -0
- package/src/codex/account-lifecycle.ts +172 -0
- package/src/codex/account-namespace-match.ts +63 -0
- package/src/codex/account-namespaces.ts +195 -0
- package/src/codex/account-pause.ts +20 -0
- package/src/codex/account-priority.ts +83 -0
- package/src/codex/account-runtime-state.ts +31 -0
- package/src/codex/account-store.ts +544 -0
- package/src/codex/account-usability.ts +43 -0
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/agent-roles-sync.ts +225 -0
- package/src/codex/agent-roles.ts +238 -0
- package/src/codex/app-server-processes.ts +1143 -0
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +2147 -0
- package/src/codex/auth-collision.ts +109 -0
- package/src/codex/auth-context.ts +665 -0
- package/src/codex/autostart-health.ts +156 -0
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +436 -0
- package/src/codex/catalog/bundled.ts +549 -0
- package/src/codex/catalog/effort.ts +446 -0
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +664 -0
- package/src/codex/catalog/native-models.ts +72 -0
- package/src/codex/catalog/parsing.ts +650 -0
- package/src/codex/catalog/provider-fetch.ts +2064 -0
- package/src/codex/catalog/sync.ts +1883 -0
- 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 +14 -0
- package/src/codex/codex-write-lock.ts +384 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +651 -0
- package/src/codex/coordinator-doctor.ts +332 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/data/upstream-models.json +830 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/exec-invocation.ts +22 -0
- package/src/codex/features.ts +1566 -0
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +407 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-migration-guardian.ts +108 -0
- package/src/codex/history-provider.ts +979 -0
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +220 -0
- package/src/codex/home.ts +206 -0
- package/src/codex/inject-coordination.ts +290 -0
- package/src/codex/inject.ts +1733 -0
- package/src/codex/injected-marker.ts +106 -0
- package/src/codex/integration-record.ts +266 -0
- package/src/codex/internal/catalog-writer.ts +203 -0
- package/src/codex/internal/history-writer.ts +80 -0
- package/src/codex/journal.ts +225 -0
- package/src/codex/log-guard/inspect.ts +506 -0
- package/src/codex/log-guard/lock.ts +150 -0
- package/src/codex/log-guard/maintenance.ts +403 -0
- package/src/codex/log-guard/path-safety.ts +88 -0
- package/src/codex/log-guard/policy.ts +44 -0
- package/src/codex/log-guard/processes.ts +205 -0
- package/src/codex/log-guard/protection.ts +489 -0
- package/src/codex/log-guard/sqlite-errors.ts +9 -0
- package/src/codex/main-account-cache.ts +56 -0
- package/src/codex/main-account.ts +68 -0
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +273 -0
- package/src/codex/model-entitlements.ts +353 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +178 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +492 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +682 -0
- package/src/codex/paths.ts +144 -0
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +242 -0
- package/src/codex/pool-rotation.ts +295 -0
- package/src/codex/project-config-warnings.ts +425 -0
- package/src/codex/prompt-journal.ts +352 -0
- package/src/codex/prompt-layers.ts +967 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +573 -0
- package/src/codex/refresh.ts +62 -0
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +1888 -0
- package/src/codex/runtime.ts +659 -0
- package/src/codex/shim.ts +2170 -0
- package/src/codex/subagent-defaults.ts +550 -0
- package/src/codex/subagent-model-fallback.ts +784 -0
- package/src/codex/sync.ts +319 -0
- package/src/codex/transition-state.ts +612 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +557 -0
- package/src/codex/warmup.ts +298 -0
- package/src/codex/websocket-registry.ts +100 -0
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +160 -0
- package/src/combos/index.ts +45 -0
- package/src/combos/request.ts +94 -0
- package/src/combos/resolve.ts +232 -0
- package/src/combos/types.ts +398 -0
- package/src/config/provider-name.ts +24 -0
- package/src/config.ts +4041 -0
- package/src/fork/register.ts +3 -0
- package/src/generated/compatibility-version.json +3116 -0
- package/src/generated/model-metadata.ts +106 -0
- package/src/github/star-state.ts +203 -0
- package/src/grok/inject.ts +530 -0
- package/src/grok/inspect.ts +45 -0
- package/src/grok/status.ts +121 -0
- package/src/grok/sync.ts +66 -0
- package/src/images/artifacts.ts +516 -0
- package/src/images/fulfill-video.ts +163 -0
- package/src/images/fulfill.ts +149 -0
- package/src/images/index.ts +4 -0
- package/src/images/loop.ts +955 -0
- package/src/images/plan.ts +143 -0
- package/src/images/synthetic-tool.ts +133 -0
- package/src/images/types.ts +41 -0
- package/src/images/xai-client.ts +141 -0
- package/src/images/xai-video-client.ts +163 -0
- package/src/index.ts +22 -0
- package/src/integrations/config-io.ts +269 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/mutation-flight.ts +71 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/omp-yaml-source.ts +358 -0
- package/src/integrations/owned-refresh.ts +74 -0
- package/src/integrations/ownership.ts +111 -0
- package/src/integrations/registry.ts +159 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +361 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +691 -0
- package/src/lab/artifacts/sanitize.ts +586 -0
- package/src/lab/artifacts/secure-fs.ts +475 -0
- package/src/lab/artifacts/store.ts +310 -0
- package/src/lab/automation/budgets.ts +78 -0
- package/src/lab/automation/config-persistence.ts +256 -0
- package/src/lab/automation/constants.ts +39 -0
- package/src/lab/automation/cooldown.ts +103 -0
- package/src/lab/automation/dispatch.ts +211 -0
- package/src/lab/automation/index.ts +13 -0
- package/src/lab/automation/orchestrator.ts +499 -0
- package/src/lab/automation/persistence.ts +512 -0
- package/src/lab/automation/planner.ts +371 -0
- package/src/lab/automation/policy.ts +136 -0
- package/src/lab/automation/queue.ts +191 -0
- package/src/lab/automation/recovery.ts +24 -0
- package/src/lab/automation/route-context.ts +21 -0
- package/src/lab/automation/run-key.ts +44 -0
- package/src/lab/automation/runs-query.ts +34 -0
- package/src/lab/automation/types.ts +160 -0
- package/src/lab/conformance/assertion.ts +325 -0
- package/src/lab/conformance/digest.ts +22 -0
- package/src/lab/conformance/executor.ts +741 -0
- package/src/lab/conformance/fixture-provider.ts +27 -0
- package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
- package/src/lab/conformance/harness-budget.ts +47 -0
- package/src/lab/conformance/index.ts +5 -0
- package/src/lab/conformance/jcs.ts +64 -0
- package/src/lab/conformance/json-pointer.ts +39 -0
- package/src/lab/conformance/manifest.ts +180 -0
- package/src/lab/conformance/mcp-stub.ts +179 -0
- package/src/lab/conformance/negative-controls.ts +164 -0
- package/src/lab/conformance/observation.ts +355 -0
- package/src/lab/conformance/runner.ts +68 -0
- package/src/lab/conformance/sse-normalize.ts +59 -0
- package/src/lab/conformance/suite-manifest.ts +78 -0
- package/src/lab/conformance/types.ts +214 -0
- package/src/lab/constants.ts +126 -0
- package/src/lab/digest.ts +64 -0
- package/src/lab/events/errors.ts +9 -0
- package/src/lab/events/limits.ts +117 -0
- package/src/lab/events/types.ts +229 -0
- package/src/lab/events/validate.ts +781 -0
- package/src/lab/fabric/constants.ts +40 -0
- package/src/lab/fabric/executor.ts +492 -0
- package/src/lab/fabric/index.ts +80 -0
- package/src/lab/fabric/manifest.ts +222 -0
- package/src/lab/fabric/observe.ts +489 -0
- package/src/lab/fabric/patch.ts +79 -0
- package/src/lab/fabric/producer-child.ts +139 -0
- package/src/lab/fabric/producer-isolate.ts +276 -0
- package/src/lab/fabric/producer-protocol.ts +61 -0
- package/src/lab/fabric/scratch.ts +439 -0
- package/src/lab/fabric/subject.ts +106 -0
- package/src/lab/fabric/types.ts +134 -0
- package/src/lab/fabric/verifier.ts +98 -0
- package/src/lab/index.ts +54 -0
- package/src/lab/ledger/artifact-refs.ts +127 -0
- package/src/lab/ledger/invalidation.ts +136 -0
- package/src/lab/ledger/purge.ts +310 -0
- package/src/lab/ledger/store.ts +532 -0
- package/src/lab/live/credential-lease.ts +53 -0
- package/src/lab/live/destination.ts +155 -0
- package/src/lab/live/executor.ts +336 -0
- package/src/lab/live/inert-tools.ts +56 -0
- package/src/lab/live/manifest.ts +85 -0
- package/src/lab/live/mcp-loopback.ts +57 -0
- package/src/lab/live/runner.ts +19 -0
- package/src/lab/live/sandbox.ts +61 -0
- package/src/lab/live/suite-manifest.ts +41 -0
- package/src/lab/live/transport.ts +118 -0
- package/src/lab/live/types.ts +197 -0
- package/src/lab/observe/from-conformance.ts +301 -0
- package/src/lab/observe/from-live.ts +117 -0
- package/src/lab/paths.ts +153 -0
- package/src/lab/projection/rebuild.ts +495 -0
- package/src/lab/projection/schema.ts +135 -0
- package/src/lab/projection/verdicts.ts +474 -0
- package/src/lab/projection/verification.ts +412 -0
- package/src/lab/public/bundle.ts +217 -0
- package/src/lab/public/community-authority.ts +175 -0
- package/src/lab/public/community-files.ts +29 -0
- package/src/lab/public/community.ts +479 -0
- package/src/lab/public/file-safety.ts +155 -0
- package/src/lab/public/ids.ts +26 -0
- package/src/lab/public/index.ts +16 -0
- package/src/lab/public/mutation-lock.ts +424 -0
- package/src/lab/public/operator.ts +353 -0
- package/src/lab/public/origin-purge.ts +79 -0
- package/src/lab/public/origin.ts +203 -0
- package/src/lab/public/privacy.ts +143 -0
- package/src/lab/public/private-file.ts +261 -0
- package/src/lab/public/project.ts +124 -0
- package/src/lab/public/purge-test-fault.ts +21 -0
- package/src/lab/public/purge.ts +223 -0
- package/src/lab/public/registry.ts +44 -0
- package/src/lab/public/revocation.ts +252 -0
- package/src/lab/public/signature.ts +243 -0
- package/src/lab/public/storage.ts +105 -0
- package/src/lab/public/strict-json.ts +206 -0
- package/src/lab/public/time.ts +26 -0
- package/src/lab/public/types.ts +172 -0
- package/src/lab/public/validate.ts +391 -0
- package/src/lab/query/catalog.ts +101 -0
- package/src/lab/query/connection.ts +107 -0
- package/src/lab/query/constants.ts +4 -0
- package/src/lab/query/cursor.ts +132 -0
- package/src/lab/query/dto-map.ts +277 -0
- package/src/lab/query/errors.ts +22 -0
- package/src/lab/query/freshness.ts +53 -0
- package/src/lab/query/index.ts +45 -0
- package/src/lab/query/latest-observation.ts +59 -0
- package/src/lab/query/passive-production.ts +159 -0
- package/src/lab/query/queries.ts +444 -0
- package/src/lab/query/types.ts +266 -0
- package/src/lab/subject/behavior-fingerprint.ts +77 -0
- package/src/lab/subject/installation-salt.ts +112 -0
- package/src/lab/subject/protocol-subject.ts +80 -0
- package/src/lab/subject/route-subject.ts +74 -0
- package/src/lib/abort.ts +146 -0
- package/src/lib/admin-secrets.ts +25 -0
- package/src/lib/admission.ts +83 -0
- package/src/lib/app-owned-memory-stores.ts +195 -0
- package/src/lib/app-owned-memory.ts +265 -0
- package/src/lib/bounded-body.ts +346 -0
- package/src/lib/bun-binary-validator.d.mts +3 -0
- package/src/lib/bun-binary-validator.mjs +18 -0
- package/src/lib/bun-runtime.ts +184 -0
- package/src/lib/bun-stream-caps.ts +130 -0
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +364 -0
- package/src/lib/crash-guard.ts +344 -0
- package/src/lib/debug-log-buffer.ts +83 -0
- package/src/lib/debug-settings.ts +108 -0
- package/src/lib/debug.ts +31 -0
- package/src/lib/destination-policy.ts +380 -0
- package/src/lib/errors.ts +406 -0
- package/src/lib/eventstream-decoder.ts +253 -0
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/gcp-adc.ts +341 -0
- package/src/lib/injection-debug-log.ts +58 -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/open-url.ts +25 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/pinned-http.ts +270 -0
- package/src/lib/privacy.ts +20 -0
- package/src/lib/process-control.ts +168 -0
- package/src/lib/provider-outbound.ts +210 -0
- package/src/lib/provider-url.ts +14 -0
- package/src/lib/proxy-env.ts +18 -0
- package/src/lib/redact.ts +521 -0
- package/src/lib/retry-after.ts +55 -0
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/service-secrets.ts +25 -0
- package/src/lib/shadow-call.ts +61 -0
- package/src/lib/sidecar-tracker.ts +52 -0
- package/src/lib/sse-decoder.ts +364 -0
- package/src/lib/state-store-registrations.ts +119 -0
- package/src/lib/state-store-sweeper.ts +184 -0
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/test-home-guard.ts +90 -0
- package/src/lib/token-estimate.ts +86 -0
- package/src/lib/tool-argument-integers.ts +202 -0
- package/src/lib/translator-budget.ts +400 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +392 -0
- package/src/lib/win-exec.ts +115 -0
- package/src/lib/win-paths.ts +68 -0
- package/src/lib/windows-atomic-replace.ts +156 -0
- package/src/lib/windows-elevation.ts +773 -0
- package/src/lib/windows-secret-acl.ts +854 -0
- 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 +403 -0
- 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-routing.ts +594 -0
- package/src/oauth/anthropic.ts +188 -0
- package/src/oauth/antigravity-routing.ts +151 -0
- package/src/oauth/callback-server.ts +300 -0
- package/src/oauth/chatgpt.ts +161 -0
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +252 -0
- package/src/oauth/github-copilot.ts +428 -0
- package/src/oauth/google-antigravity.ts +262 -0
- package/src/oauth/health.ts +407 -0
- package/src/oauth/index.ts +1504 -0
- package/src/oauth/key-providers.ts +124 -0
- package/src/oauth/kimi.ts +227 -0
- package/src/oauth/kiro-credentials.ts +726 -0
- package/src/oauth/kiro.ts +621 -0
- package/src/oauth/local-token-detect.ts +130 -0
- package/src/oauth/log.ts +50 -0
- package/src/oauth/login-cli.ts +223 -0
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/pkce.ts +15 -0
- package/src/oauth/store.ts +728 -0
- package/src/oauth/token-guardian.ts +309 -0
- package/src/oauth/types.ts +62 -0
- package/src/oauth/xai.ts +241 -0
- package/src/providers/alibaba-region-backup.ts +75 -0
- package/src/providers/alibaba-region-migration.ts +156 -0
- package/src/providers/alibaba-region-startup.ts +36 -0
- package/src/providers/antigravity-models.ts +695 -0
- package/src/providers/antigravity-quota.ts +216 -0
- package/src/providers/api-keys.ts +140 -0
- package/src/providers/base-url-choices.ts +74 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +144 -0
- package/src/providers/context-cap.ts +82 -0
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/derive.ts +586 -0
- package/src/providers/fastwire.ts +501 -0
- package/src/providers/free-directory.ts +187 -0
- package/src/providers/github-copilot-transport.ts +56 -0
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +271 -0
- package/src/providers/kiro-models.ts +67 -0
- package/src/providers/label.ts +19 -0
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +449 -0
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/openai-sidecar.ts +243 -0
- package/src/providers/openai-tier-startup.ts +56 -0
- package/src/providers/openai-tiers.ts +423 -0
- package/src/providers/openai-virtual-models.ts +83 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/openrouter-routing.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +185 -0
- package/src/providers/quota.ts +2345 -0
- package/src/providers/registry.ts +2918 -0
- package/src/providers/replit/constants.ts +27 -0
- package/src/providers/replit/derive.ts +85 -0
- package/src/providers/replit/headers.ts +28 -0
- package/src/providers/replit/origin.ts +55 -0
- package/src/providers/replit/pair-install-response.ts +72 -0
- package/src/providers/replit/probe.ts +199 -0
- package/src/providers/replit/setup.ts +350 -0
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +103 -0
- 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 +148 -0
- package/src/reasoning-effort.ts +183 -0
- package/src/responses/compaction.ts +142 -0
- package/src/responses/custom-tool-compat.ts +266 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +355 -0
- package/src/responses/parser.ts +838 -0
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +60 -0
- package/src/responses/reasoning-replay-cache.ts +426 -0
- package/src/responses/schema.ts +165 -0
- package/src/responses/spill-store.ts +459 -0
- package/src/responses/state.ts +1433 -0
- package/src/responses/thought-signature-replay.ts +347 -0
- package/src/responses/tool-groups.ts +19 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/router.ts +761 -0
- package/src/routing/analytics.ts +378 -0
- package/src/routing/capability.ts +244 -0
- package/src/routing/compatibility/assemble.ts +73 -0
- package/src/routing/compatibility/behavior.ts +278 -0
- package/src/routing/compatibility/catalog.ts +99 -0
- package/src/routing/compatibility/endpoint.ts +52 -0
- package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
- package/src/routing/compatibility/policy.ts +181 -0
- package/src/routing/compatibility/provider-slot.ts +56 -0
- package/src/routing/compatibility/reader.ts +110 -0
- package/src/routing/compatibility/subject.ts +191 -0
- package/src/routing/compatibility/types.ts +64 -0
- package/src/routing/compatibility/version.ts +104 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +495 -0
- package/src/routing/health.ts +412 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +547 -0
- package/src/routing/quota.ts +145 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +776 -0
- package/src/server/adapter-resolve.ts +53 -0
- package/src/server/auth-cors.ts +751 -0
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +442 -0
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +426 -0
- package/src/server/claude-messages.ts +1030 -0
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +190 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +152 -0
- package/src/server/image-retry.ts +42 -0
- package/src/server/images.ts +568 -0
- package/src/server/index.ts +1813 -0
- package/src/server/lifecycle.ts +498 -0
- package/src/server/live.ts +717 -0
- 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 +1433 -0
- package/src/server/management/api-access.ts +141 -0
- package/src/server/management/api-key-usage.ts +193 -0
- package/src/server/management/body.ts +41 -0
- package/src/server/management/combo-routes.ts +263 -0
- package/src/server/management/config-routes.ts +835 -0
- package/src/server/management/context.ts +113 -0
- 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 +586 -0
- package/src/server/management/model-routes.ts +560 -0
- package/src/server/management/model-rows.ts +163 -0
- package/src/server/management/native-integration-routes.ts +769 -0
- package/src/server/management/oauth-account-routes.ts +637 -0
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +1033 -0
- package/src/server/management/replit-provider-routes.ts +86 -0
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +385 -0
- package/src/server/management/shared.ts +286 -0
- package/src/server/management/sidebar-routes.ts +106 -0
- 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 +435 -0
- package/src/server/management/system-routes.ts +194 -0
- package/src/server/management/usage-summary-cache.ts +94 -0
- 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 +314 -0
- package/src/server/management-auth.ts +482 -0
- package/src/server/memory-watchdog.ts +156 -0
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/port-reclaim.ts +307 -0
- package/src/server/ports.ts +156 -0
- package/src/server/proxy-liveness.ts +328 -0
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +353 -0
- package/src/server/relay.ts +1209 -0
- package/src/server/request-decompress.ts +239 -0
- package/src/server/request-log-conversation.ts +168 -0
- package/src/server/request-log.ts +1259 -0
- package/src/server/responses/agent-task-recovery-cache.ts +143 -0
- package/src/server/responses/agent-task-recovery.ts +465 -0
- package/src/server/responses/collaboration.ts +551 -0
- package/src/server/responses/compact.ts +771 -0
- package/src/server/responses/core.ts +5389 -0
- package/src/server/responses/empty-completion-guard.ts +276 -0
- package/src/server/responses/encrypted-payload.ts +331 -0
- package/src/server/responses/fetch-helpers.ts +232 -0
- package/src/server/responses/input-admission.ts +185 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/passthrough-error.ts +78 -0
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +251 -0
- package/src/server/responses/terminal-guard.ts +251 -0
- package/src/server/responses/upstream-error.ts +53 -0
- package/src/server/responses/ws-upstream.ts +308 -0
- package/src/server/responses-custom-tool-repair.ts +282 -0
- package/src/server/responses-image-gen-repair.ts +132 -0
- package/src/server/responses-item-id-repair.ts +272 -0
- package/src/server/responses-json-events.ts +90 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses-terminal-repair.ts +342 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +153 -0
- package/src/server/responses.ts +25 -0
- package/src/server/search.ts +201 -0
- package/src/server/sse-frame-buffer.ts +292 -0
- package/src/server/sse-payload-rewrite.ts +263 -0
- package/src/server/startup-action-control.ts +315 -0
- package/src/server/startup-health-cache.ts +131 -0
- package/src/server/system-env.ts +484 -0
- package/src/server/windows-tcp-drop.ts +184 -0
- package/src/server/windows-tray-control.ts +41 -0
- package/src/server/ws-bridge.ts +472 -0
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +3575 -0
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/stall-timeout.ts +20 -0
- package/src/storage/cleanup-job.ts +57 -0
- package/src/storage/cleanup.ts +3085 -0
- package/src/storage/policy-job.ts +457 -0
- package/src/storage/policy-scheduler.ts +40 -0
- package/src/storage/policy-worker.ts +59 -0
- package/src/storage/policy.ts +527 -0
- package/src/storage/restore-job.ts +299 -0
- package/src/storage/restore-worker.ts +58 -0
- package/src/storage/scanner.ts +238 -0
- package/src/storage/storage-mutation-coordinator.ts +139 -0
- package/src/storage/worker-lifecycle.ts +215 -0
- package/src/tray/assets/opencodex-tray-offline.ico +0 -0
- package/src/tray/assets/opencodex-tray-online.ico +0 -0
- package/src/tray/assets/opencodex-tray-warning.ico +0 -0
- package/src/tray/assets/opencodex-tray.png +0 -0
- package/src/tray/windows-tray.ps1 +364 -0
- package/src/tray/windows.ts +757 -0
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +876 -0
- package/src/types/provider.ts +545 -0
- package/src/types/request.ts +384 -0
- package/src/types/tools.ts +131 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +106 -0
- package/src/update/badge.ts +72 -0
- package/src/update/index.ts +415 -0
- package/src/update/job.ts +1887 -0
- package/src/update/notify.ts +263 -0
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/npm-invocation.d.mts +23 -0
- package/src/update/npm-invocation.mjs +94 -0
- package/src/update/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +259 -0
- package/src/update/tray-update-plan.d.mts +18 -0
- package/src/update/tray-update-plan.mjs +38 -0
- package/src/usage/cost.ts +625 -0
- package/src/usage/debug.ts +97 -0
- package/src/usage/expected-prices.ts +416 -0
- package/src/usage/log.ts +1223 -0
- package/src/usage/summary.ts +753 -0
- package/src/usage/totals.ts +14 -0
- 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 +189 -0
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +131 -0
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +681 -0
- 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 +195 -0
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +88 -0
- package/src/web-search/executor.ts +113 -0
- package/src/web-search/format-result.ts +89 -0
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +331 -0
- package/src/web-search/loop.ts +896 -0
- package/src/web-search/parse.ts +315 -0
- package/src/web-search/progress-stream.ts +342 -0
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/synthetic-tool.ts +47 -0
- package/src/web-search/xai-executor.ts +219 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { readFileSync, realpathSync, statSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
3
|
+
import { expandUserPath } from "../config";
|
|
4
|
+
import { defaultCodexHome } from "./home";
|
|
5
|
+
|
|
6
|
+
function resolveCodexHome(): string {
|
|
7
|
+
const raw = process.env.CODEX_HOME?.trim();
|
|
8
|
+
if (raw) {
|
|
9
|
+
const path = resolve(expandUserPath(raw));
|
|
10
|
+
let stat;
|
|
11
|
+
try {
|
|
12
|
+
stat = statSync(path);
|
|
13
|
+
} catch (err) {
|
|
14
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
15
|
+
throw new Error(`CODEX_HOME points to ${raw}, but that path could not be read: ${message}`);
|
|
16
|
+
}
|
|
17
|
+
if (!stat.isDirectory()) {
|
|
18
|
+
throw new Error(`CODEX_HOME points to ${raw}, but that path is not a directory`);
|
|
19
|
+
}
|
|
20
|
+
return realpathSync.native(path);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return defaultCodexHome();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const CODEX_HOME = resolveCodexHome();
|
|
27
|
+
export const CODEX_CONFIG_PATH = join(CODEX_HOME, "config.toml");
|
|
28
|
+
export const CODEX_PROFILE_PATH = join(CODEX_HOME, "opencodex.config.toml");
|
|
29
|
+
export const DEFAULT_CATALOG_PATH = join(CODEX_HOME, "opencodex-catalog.json");
|
|
30
|
+
export const CODEX_MODELS_CACHE_PATH = join(CODEX_HOME, "models_cache.json");
|
|
31
|
+
|
|
32
|
+
/** Runtime CODEX_HOME lookup (honors CODEX_HOME env changes after import). */
|
|
33
|
+
export function getCodexHome(): string {
|
|
34
|
+
return resolveCodexHome();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface CodexSqliteHomeDeps {
|
|
38
|
+
env?: NodeJS.ProcessEnv;
|
|
39
|
+
cwd?: () => string;
|
|
40
|
+
codexHome?: string;
|
|
41
|
+
readConfig?: (path: string) => string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type RootTomlStringState =
|
|
45
|
+
| { kind: "absent" }
|
|
46
|
+
| { kind: "value"; value: string }
|
|
47
|
+
| { kind: "invalid" };
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Parse the authoritative SQLite setting without changing the tolerant helper
|
|
51
|
+
* used by injection/catalog readers. History ownership must distinguish a
|
|
52
|
+
* missing key from a present value that Codex cannot interpret as a path.
|
|
53
|
+
*/
|
|
54
|
+
function readAuthoritativeRootTomlString(content: string, key: string): RootTomlStringState {
|
|
55
|
+
let parsed: unknown;
|
|
56
|
+
try {
|
|
57
|
+
parsed = Bun.TOML.parse(content);
|
|
58
|
+
} catch {
|
|
59
|
+
return { kind: "invalid" };
|
|
60
|
+
}
|
|
61
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return { kind: "invalid" };
|
|
62
|
+
const root = parsed as Record<string, unknown>;
|
|
63
|
+
if (!Object.prototype.hasOwnProperty.call(root, key)) return { kind: "absent" };
|
|
64
|
+
const value = root[key];
|
|
65
|
+
if (typeof value !== "string" || value.trim() === "") return { kind: "invalid" };
|
|
66
|
+
return { kind: "value", value: value.trim() };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Resolve Codex's SQLite state root at call time.
|
|
71
|
+
*
|
|
72
|
+
* Codex permits SQLite-backed state to live outside CODEX_HOME, especially for
|
|
73
|
+
* Windows Desktop sessions whose app-server runs in WSL. Keep the precedence
|
|
74
|
+
* identical to Codex: root config, then environment, then the effective home.
|
|
75
|
+
*/
|
|
76
|
+
export function resolveCodexSqliteHome(deps: CodexSqliteHomeDeps = {}): string {
|
|
77
|
+
const codexHome = deps.codexHome ?? getCodexHome();
|
|
78
|
+
const readConfig = deps.readConfig ?? (path => readFileSync(path, "utf8"));
|
|
79
|
+
const configPath = join(codexHome, "config.toml");
|
|
80
|
+
let configured: RootTomlStringState = { kind: "absent" };
|
|
81
|
+
try {
|
|
82
|
+
configured = readAuthoritativeRootTomlString(readConfig(configPath), "sqlite_home");
|
|
83
|
+
} catch (cause) {
|
|
84
|
+
if ((cause as NodeJS.ErrnoException | undefined)?.code !== "ENOENT") {
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Codex config could not be read while resolving sqlite_home: ${configPath}`,
|
|
87
|
+
{ cause },
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
// A genuinely absent config cannot contain the authoritative root override,
|
|
91
|
+
// so only ENOENT may continue to the documented environment/home fallback.
|
|
92
|
+
}
|
|
93
|
+
if (configured.kind === "invalid") {
|
|
94
|
+
throw new Error(`Codex config has an invalid sqlite_home setting: ${configPath}`);
|
|
95
|
+
}
|
|
96
|
+
const raw = configured.kind === "value"
|
|
97
|
+
? configured.value
|
|
98
|
+
: (deps.env ?? process.env).CODEX_SQLITE_HOME?.trim() || "";
|
|
99
|
+
if (!raw) return codexHome;
|
|
100
|
+
const expanded = expandUserPath(raw);
|
|
101
|
+
return isAbsolute(expanded)
|
|
102
|
+
? resolve(expanded)
|
|
103
|
+
: resolve((deps.cwd ?? process.cwd)(), expanded);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Active Codex thread-state database, derived from the call-time SQLite root. */
|
|
107
|
+
export function resolveCodexStateDbPath(deps: CodexSqliteHomeDeps = {}): string {
|
|
108
|
+
return join(resolveCodexSqliteHome(deps), "state_5.sqlite");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Active Codex diagnostic-log database, derived from the call-time SQLite root. */
|
|
112
|
+
export function resolveCodexLogsDbPath(deps: CodexSqliteHomeDeps = {}): string {
|
|
113
|
+
return join(resolveCodexSqliteHome(deps), "logs_2.sqlite");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function tomlString(value: string): string {
|
|
117
|
+
return JSON.stringify(value);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function parseTomlString(raw: string): string {
|
|
121
|
+
if (raw.startsWith("\"")) {
|
|
122
|
+
try {
|
|
123
|
+
return JSON.parse(raw) as string;
|
|
124
|
+
} catch {
|
|
125
|
+
return raw.slice(1, -1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return raw.slice(1, -1);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function readRootTomlString(content: string, key: string): string | null {
|
|
132
|
+
const lines = content.split("\n");
|
|
133
|
+
const firstTable = lines.findIndex(l => /^\s*\[/.test(l));
|
|
134
|
+
const rootLines = firstTable === -1 ? lines : lines.slice(0, firstTable);
|
|
135
|
+
for (const line of rootLines) {
|
|
136
|
+
const m = line.match(new RegExp(`^\\s*${key}\\s*=\\s*(\"(?:\\\\.|[^\"])*\"|'[^']*')`));
|
|
137
|
+
if (m) return parseTomlString(m[1]);
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function resolveCodexConfigPath(path: string): string {
|
|
143
|
+
return isAbsolute(path) ? path : join(CODEX_HOME, path);
|
|
144
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfigMutationLockError,
|
|
3
|
+
loadConfig,
|
|
4
|
+
mutatePersistedConfig,
|
|
5
|
+
} from "../config";
|
|
6
|
+
import type { CodexAccount, OcxConfig } from "../types";
|
|
7
|
+
import { isSelectableCodexPoolAccount, isValidCodexAccountId } from "./account-id";
|
|
8
|
+
import {
|
|
9
|
+
getCodexAccountCredential,
|
|
10
|
+
isCodexAccountGenerationLive,
|
|
11
|
+
readCodexAccountRecord,
|
|
12
|
+
} from "./account-store";
|
|
13
|
+
import { extractChatgptPlanType, codexPlanValue } from "./plan";
|
|
14
|
+
|
|
15
|
+
interface FreshPoolPlanUpdate {
|
|
16
|
+
accountId: string;
|
|
17
|
+
plan: string;
|
|
18
|
+
credentialGeneration: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function configuredPoolAccount(config: OcxConfig, accountId: string): CodexAccount | null {
|
|
22
|
+
if (!isValidCodexAccountId(accountId)) return null;
|
|
23
|
+
return (config.codexAccounts ?? [])
|
|
24
|
+
.find(account => account.id === accountId && isSelectableCodexPoolAccount(account)) ?? null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function jwtPlanFromPoolCredential(accountId: string): string | undefined {
|
|
28
|
+
const cred = getCodexAccountCredential(accountId);
|
|
29
|
+
return cred ? extractChatgptPlanType(undefined, cred.accessToken) : undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* WHAM-wins gate (release-audit fix). A JWT-derived plan may be persisted only when no
|
|
34
|
+
* WHAM-sourced plan exists for the CURRENT credential generation. A token refresh bumps the
|
|
35
|
+
* generation, and the refreshed JWT is then genuinely newer information than the previous
|
|
36
|
+
* generation's WHAM read, so it may write again until WHAM re-observes. Records without
|
|
37
|
+
* provenance (legacy) stay writable so the original #1989 recovery still works.
|
|
38
|
+
*/
|
|
39
|
+
function jwtMayWritePlan(account: CodexAccount, generation: number): boolean {
|
|
40
|
+
if (account.planSource !== "wham") return true;
|
|
41
|
+
const whamGeneration = account.planCredentialGeneration;
|
|
42
|
+
return whamGeneration !== undefined && generation > whamGeneration;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function collectJwtPoolPlanUpdates(runtimeConfig: OcxConfig): FreshPoolPlanUpdate[] {
|
|
46
|
+
const updates: FreshPoolPlanUpdate[] = [];
|
|
47
|
+
for (const account of (runtimeConfig.codexAccounts ?? []).filter(isSelectableCodexPoolAccount)) {
|
|
48
|
+
const jwtPlan = jwtPlanFromPoolCredential(account.id);
|
|
49
|
+
if (!jwtPlan || codexPlanValue(account.plan) === jwtPlan) continue;
|
|
50
|
+
const generation = readCodexAccountRecord(account.id)?.generation;
|
|
51
|
+
if (generation === undefined) continue;
|
|
52
|
+
if (!jwtMayWritePlan(account, generation)) continue;
|
|
53
|
+
updates.push({ accountId: account.id, plan: jwtPlan, credentialGeneration: generation });
|
|
54
|
+
}
|
|
55
|
+
return updates;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const appliedJwtPlans = new Map<string, string>();
|
|
59
|
+
|
|
60
|
+
function persistJwtPlanUpdates(runtimeConfig: OcxConfig, updates: FreshPoolPlanUpdate[]): void {
|
|
61
|
+
if (updates.length === 0) return;
|
|
62
|
+
let outcome: ReturnType<typeof mutatePersistedConfig<FreshPoolPlanUpdate[]>>;
|
|
63
|
+
try {
|
|
64
|
+
outcome = mutatePersistedConfig(persistedConfig => {
|
|
65
|
+
const accepted: FreshPoolPlanUpdate[] = [];
|
|
66
|
+
let changed = false;
|
|
67
|
+
for (const update of updates) {
|
|
68
|
+
if (!isCodexAccountGenerationLive(update.accountId, update.credentialGeneration)) continue;
|
|
69
|
+
const liveAccount = configuredPoolAccount(runtimeConfig, update.accountId);
|
|
70
|
+
const persistedAccount = configuredPoolAccount(persistedConfig, update.accountId);
|
|
71
|
+
if (!liveAccount || !persistedAccount) continue;
|
|
72
|
+
// Re-check against the PERSISTED row: another process may have landed a WHAM
|
|
73
|
+
// observation between collect and this mutation.
|
|
74
|
+
if (!jwtMayWritePlan(persistedAccount, update.credentialGeneration)) continue;
|
|
75
|
+
accepted.push(update);
|
|
76
|
+
if (persistedAccount.plan !== update.plan) {
|
|
77
|
+
persistedAccount.plan = update.plan;
|
|
78
|
+
changed = true;
|
|
79
|
+
}
|
|
80
|
+
if (persistedAccount.planSource !== "jwt" || persistedAccount.planCredentialGeneration !== update.credentialGeneration) {
|
|
81
|
+
persistedAccount.planSource = "jwt";
|
|
82
|
+
persistedAccount.planCredentialGeneration = update.credentialGeneration;
|
|
83
|
+
changed = true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { changed, value: accepted };
|
|
87
|
+
});
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (error instanceof ConfigMutationLockError) return;
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
if (outcome.status === "unavailable") return;
|
|
93
|
+
for (const update of outcome.value) {
|
|
94
|
+
if (!isCodexAccountGenerationLive(update.accountId, update.credentialGeneration)) continue;
|
|
95
|
+
const liveAccount = configuredPoolAccount(runtimeConfig, update.accountId);
|
|
96
|
+
if (liveAccount) {
|
|
97
|
+
liveAccount.plan = update.plan;
|
|
98
|
+
liveAccount.planSource = "jwt";
|
|
99
|
+
liveAccount.planCredentialGeneration = update.credentialGeneration;
|
|
100
|
+
appliedJwtPlans.set(update.accountId, update.plan);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Persist JWT `chatgpt_plan_type` onto `codexAccounts[].plan` when it contradicts the stored
|
|
107
|
+
* label. Generation-gated, same fail-closed lock policy as the WHAM plan patch. Does not
|
|
108
|
+
* overwrite a plan that already matches the token.
|
|
109
|
+
*/
|
|
110
|
+
export function reconcileCodexPlansFromTokens(runtimeConfig: OcxConfig = loadConfig()): void {
|
|
111
|
+
persistJwtPlanUpdates(runtimeConfig, collectJwtPoolPlanUpdates(runtimeConfig));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function resetJwtPlanNotesForTests(): void {
|
|
115
|
+
appliedJwtPlans.clear();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Apply one account's live token claim without blocking the credential read path. */
|
|
119
|
+
export function noteCodexAccountAccessToken(
|
|
120
|
+
accountId: string,
|
|
121
|
+
accessToken: string,
|
|
122
|
+
credentialGeneration: number,
|
|
123
|
+
): void {
|
|
124
|
+
const jwtPlan = extractChatgptPlanType(undefined, accessToken);
|
|
125
|
+
if (!jwtPlan) return;
|
|
126
|
+
if (appliedJwtPlans.get(accountId) === jwtPlan) return;
|
|
127
|
+
try {
|
|
128
|
+
const runtimeConfig = loadConfig();
|
|
129
|
+
const live = configuredPoolAccount(runtimeConfig, accountId);
|
|
130
|
+
if (!live || codexPlanValue(live.plan) === jwtPlan) {
|
|
131
|
+
appliedJwtPlans.set(accountId, jwtPlan);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (!jwtMayWritePlan(live, credentialGeneration)) return;
|
|
135
|
+
persistJwtPlanUpdates(runtimeConfig, [{ accountId, plan: jwtPlan, credentialGeneration }]);
|
|
136
|
+
if (codexPlanValue(live.plan) === jwtPlan) appliedJwtPlans.set(accountId, jwtPlan);
|
|
137
|
+
} catch {
|
|
138
|
+
appliedJwtPlans.delete(accountId);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { decodeJwtPayload } from "../oauth/chatgpt";
|
|
2
|
+
|
|
3
|
+
/** Preserve user/provider plan labels only when they are usable strings. */
|
|
4
|
+
export function codexPlanValue(value: unknown): string | undefined {
|
|
5
|
+
if (typeof value !== "string") return undefined;
|
|
6
|
+
return value.trim() ? value : undefined;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Case-insensitive key used by quota, capacity, and collision policy. */
|
|
10
|
+
export function codexPlanKey(value: unknown): string | undefined {
|
|
11
|
+
return codexPlanValue(value)?.trim().toLowerCase();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function isThirtyDayOnlyCodexPlan(value: unknown): boolean {
|
|
15
|
+
const key = codexPlanKey(value);
|
|
16
|
+
return key === "go" || key === "free";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* ChatGPT plan label from a live access/id token (`chatgpt_plan_type`).
|
|
21
|
+
* Used when WHAM has not run yet so a stale stored `free` cannot outrank the token (#1989).
|
|
22
|
+
*/
|
|
23
|
+
export function extractChatgptPlanType(idToken?: string, accessToken?: string): string | undefined {
|
|
24
|
+
for (const token of [idToken, accessToken]) {
|
|
25
|
+
if (!token) continue;
|
|
26
|
+
const payload = decodeJwtPayload(token);
|
|
27
|
+
if (!payload) continue;
|
|
28
|
+
if (typeof payload.chatgpt_plan_type === "string") {
|
|
29
|
+
const plan = codexPlanValue(payload.chatgpt_plan_type);
|
|
30
|
+
if (plan) return plan;
|
|
31
|
+
}
|
|
32
|
+
const ns = payload["https://api.openai.com/auth"];
|
|
33
|
+
if (ns && typeof ns === "object") {
|
|
34
|
+
const nested = (ns as Record<string, unknown>).chatgpt_plan_type;
|
|
35
|
+
const plan = codexPlanValue(nested);
|
|
36
|
+
if (plan) return plan;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, join } from "node:path";
|
|
3
|
+
import { CODEX_CONFIG_PATH } from "./paths";
|
|
4
|
+
import { redactUserPath } from "../lib/redact";
|
|
5
|
+
|
|
6
|
+
// Mirrors codex-rs core-plugins/src/marketplace.rs MARKETPLACE_MANIFEST_RELATIVE_PATHS.
|
|
7
|
+
// A marketplace root "resolves" only when one of these files exists under it.
|
|
8
|
+
const MARKETPLACE_MANIFEST_RELATIVE_PATHS = [
|
|
9
|
+
".agents/plugins/marketplace.json",
|
|
10
|
+
".claude-plugin/marketplace.json",
|
|
11
|
+
] as const;
|
|
12
|
+
|
|
13
|
+
const OPENAI_BUNDLED_MARKETPLACE_NAME = "openai-bundled";
|
|
14
|
+
|
|
15
|
+
// Where the Codex desktop app's bundled plugins live, relative to an install
|
|
16
|
+
// root. Windows app-package paths embed the app version, so the actual install
|
|
17
|
+
// root is discovered by scanning candidate bases (LOCALAPPDATA, etc.) rather
|
|
18
|
+
// than hardcoded. The bundled marketplace dir is named after the marketplace.
|
|
19
|
+
const BUNDLED_MARKETPLACE_LEAF = join("plugins", "bundled-marketplaces", OPENAI_BUNDLED_MARKETPLACE_NAME);
|
|
20
|
+
const CODEX_APP_DIR_SEGMENTS = [join("Programs", "@openai", "codex"), join("Programs", "codex"), join("@openai", "codex"), "codex"] as const;
|
|
21
|
+
|
|
22
|
+
// Plugins the issue (#43) calls out. Treated as data, not as an authoritative
|
|
23
|
+
// allowlist: codex-rs only allowlists chrome/computer-use, but the diagnostic
|
|
24
|
+
// just reports presence, so listing browser here is informational only.
|
|
25
|
+
const COMMON_BUNDLED_PLUGINS = ["computer-use", "browser", "chrome"] as const;
|
|
26
|
+
|
|
27
|
+
export type CodexPluginsDiagnostic =
|
|
28
|
+
| { applicable: false; reason: string; summary: string }
|
|
29
|
+
| {
|
|
30
|
+
applicable: true;
|
|
31
|
+
stale: boolean;
|
|
32
|
+
marketplace: {
|
|
33
|
+
name: string;
|
|
34
|
+
present: boolean;
|
|
35
|
+
sourceType: string | null;
|
|
36
|
+
source: string | null;
|
|
37
|
+
resolvesToManifest: boolean;
|
|
38
|
+
currentBundledPath: string | null;
|
|
39
|
+
pathMismatch: boolean;
|
|
40
|
+
};
|
|
41
|
+
bundledPlugins: Array<{ id: string; configured: boolean }>;
|
|
42
|
+
suggestedRepair: string | null;
|
|
43
|
+
summary: string;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** True when the table at `[marketplaces.<name>]` exists in the config text. */
|
|
47
|
+
function readMarketplaceTable(configText: string, name: string): Record<string, string> | null {
|
|
48
|
+
// Split on CRLF or LF: config.toml on Windows (the platform this diagnostic
|
|
49
|
+
// targets) uses CRLF, and a leftover \r would defeat the `$`-anchored regexes.
|
|
50
|
+
const lines = configText.split(/\r?\n/);
|
|
51
|
+
const header = new RegExp(`^\\s*\\[marketplaces\\.(?:"${escapeRegExp(name)}"|${escapeRegExp(name)})\\]\\s*(?:#.*)?$`);
|
|
52
|
+
let start = -1;
|
|
53
|
+
for (let i = 0; i < lines.length; i++) {
|
|
54
|
+
if (header.test(lines[i] ?? "")) { start = i + 1; break; }
|
|
55
|
+
}
|
|
56
|
+
if (start === -1) return null;
|
|
57
|
+
|
|
58
|
+
const table: Record<string, string> = {};
|
|
59
|
+
for (let i = start; i < lines.length; i++) {
|
|
60
|
+
const line = lines[i] ?? "";
|
|
61
|
+
if (/^\s*\[/.test(line)) break; // next table starts; stop
|
|
62
|
+
const m = line.match(/^\s*([A-Za-z0-9_-]+)\s*=\s*("(?:\\.|[^"\\])*"|'[^']*'|(?!["'])[^\s#]+)\s*(?:#.*)?$/);
|
|
63
|
+
if (!m) continue;
|
|
64
|
+
table[m[1]] = unquoteTomlValue(m[2].trim());
|
|
65
|
+
}
|
|
66
|
+
return table;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function unquoteTomlValue(raw: string): string {
|
|
70
|
+
if (raw.startsWith("\"")) {
|
|
71
|
+
try { return JSON.parse(raw) as string; } catch { return raw.slice(1, -1); }
|
|
72
|
+
}
|
|
73
|
+
if (raw.startsWith("'")) return raw.slice(1, -1);
|
|
74
|
+
return raw;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function escapeRegExp(value: string): string {
|
|
78
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** A directory is a bundled-marketplace root when it holds a supported manifest. */
|
|
82
|
+
function dirHasManifest(dir: string): boolean {
|
|
83
|
+
return MARKETPLACE_MANIFEST_RELATIVE_PATHS.some(rel => existsSync(join(dir, rel)));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Locate the bundled `openai-bundled` marketplace dir under the installed Codex
|
|
88
|
+
* desktop app on Windows. Windows app paths embed the app version, so we scan
|
|
89
|
+
* candidate install bases for a versioned app dir whose
|
|
90
|
+
* `plugins/bundled-marketplaces/openai-bundled` holds a manifest. Returns the
|
|
91
|
+
* newest matching dir (by mtime) or null. Filesystem access is injectable for
|
|
92
|
+
* tests so a Windows layout can be exercised on any OS.
|
|
93
|
+
*/
|
|
94
|
+
export function locateCurrentBundledMarketplace(
|
|
95
|
+
options: {
|
|
96
|
+
env?: NodeJS.ProcessEnv;
|
|
97
|
+
listDir?: (dir: string) => string[];
|
|
98
|
+
isManifestRoot?: (dir: string) => boolean;
|
|
99
|
+
mtimeOf?: (dir: string) => number;
|
|
100
|
+
} = {},
|
|
101
|
+
): string | null {
|
|
102
|
+
const env = options.env ?? process.env;
|
|
103
|
+
const listDir = options.listDir ?? ((dir: string) => {
|
|
104
|
+
try { return readdirSync(dir); } catch { return []; }
|
|
105
|
+
});
|
|
106
|
+
const isManifestRoot = options.isManifestRoot ?? dirHasManifest;
|
|
107
|
+
const mtimeOf = options.mtimeOf ?? ((dir: string) => {
|
|
108
|
+
try { return statSync(dir).mtimeMs; } catch { return 0; }
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const bases = [env.LOCALAPPDATA, env.PROGRAMFILES, env["ProgramFiles(x86)"], env.APPDATA]
|
|
112
|
+
.filter((b): b is string => typeof b === "string" && b.length > 0);
|
|
113
|
+
|
|
114
|
+
const candidates: string[] = [];
|
|
115
|
+
for (const base of bases) {
|
|
116
|
+
for (const seg of CODEX_APP_DIR_SEGMENTS) {
|
|
117
|
+
const appRoot = join(base, seg);
|
|
118
|
+
// Direct (unversioned) layout.
|
|
119
|
+
const direct = join(appRoot, BUNDLED_MARKETPLACE_LEAF);
|
|
120
|
+
if (isManifestRoot(direct)) candidates.push(direct);
|
|
121
|
+
// Versioned layout: appRoot/<version>/plugins/bundled-marketplaces/openai-bundled
|
|
122
|
+
for (const child of listDir(appRoot)) {
|
|
123
|
+
const versioned = join(appRoot, child, BUNDLED_MARKETPLACE_LEAF);
|
|
124
|
+
if (isManifestRoot(versioned)) candidates.push(versioned);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (candidates.length === 0) return null;
|
|
129
|
+
candidates.sort((a, b) => mtimeOf(b) - mtimeOf(a));
|
|
130
|
+
return candidates[0] ?? null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Normalize a path for comparison: lowercase + unify separators (Windows is case-insensitive). */
|
|
134
|
+
function normalizePathForCompare(path: string): string {
|
|
135
|
+
return path.replace(/[\\/]+/g, "\\").replace(/\\+$/, "").toLowerCase();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** A local marketplace `source` resolves when it holds a supported manifest. */
|
|
139
|
+
function sourceResolvesToManifest(source: string): boolean {
|
|
140
|
+
if (!isAbsolute(source)) return false;
|
|
141
|
+
if (!existsSync(source)) return false;
|
|
142
|
+
return MARKETPLACE_MANIFEST_RELATIVE_PATHS.some(rel => existsSync(join(source, rel)));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Read-only diagnostic for the Codex `openai-bundled` plugin marketplace.
|
|
147
|
+
*
|
|
148
|
+
* Only meaningful on Windows, where app-package paths embed the app version and
|
|
149
|
+
* go stale after an update. On other platforms it reports "not applicable".
|
|
150
|
+
* NEVER mutates config.toml, never invokes `codex plugin marketplace add`.
|
|
151
|
+
*/
|
|
152
|
+
export function diagnoseCodexBundledPlugins(
|
|
153
|
+
options: {
|
|
154
|
+
platform?: NodeJS.Platform;
|
|
155
|
+
configPath?: string;
|
|
156
|
+
locateCurrent?: () => string | null;
|
|
157
|
+
} = {},
|
|
158
|
+
): CodexPluginsDiagnostic {
|
|
159
|
+
const platform = options.platform ?? process.platform;
|
|
160
|
+
if (platform !== "win32") {
|
|
161
|
+
return {
|
|
162
|
+
applicable: false,
|
|
163
|
+
reason: "not_windows",
|
|
164
|
+
summary: "not applicable (bundled-marketplace staleness is Windows-specific)",
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const configPath = options.configPath ?? CODEX_CONFIG_PATH;
|
|
169
|
+
let configText: string;
|
|
170
|
+
try {
|
|
171
|
+
configText = readFileSync(configPath, "utf8");
|
|
172
|
+
} catch {
|
|
173
|
+
return {
|
|
174
|
+
applicable: false,
|
|
175
|
+
reason: "config_unreadable",
|
|
176
|
+
summary: "not applicable (Codex config.toml not found or unreadable)",
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const table = readMarketplaceTable(configText, OPENAI_BUNDLED_MARKETPLACE_NAME);
|
|
181
|
+
const present = table !== null;
|
|
182
|
+
const sourceType = table?.source_type ?? null;
|
|
183
|
+
const source = table?.source ?? null;
|
|
184
|
+
const isLocal = sourceType === "local" && !!source;
|
|
185
|
+
const resolvesToManifest = isLocal ? sourceResolvesToManifest(source as string) : false;
|
|
186
|
+
|
|
187
|
+
// Locate the bundled marketplace under the currently installed Codex app, so
|
|
188
|
+
// we can tell "registered path differs from the live app path" (the Windows
|
|
189
|
+
// app-update staleness signal) apart from a merely missing manifest.
|
|
190
|
+
const locateCurrent = options.locateCurrent ?? (() => locateCurrentBundledMarketplace());
|
|
191
|
+
const currentBundledPath = locateCurrent();
|
|
192
|
+
const pathMismatch = !!(
|
|
193
|
+
currentBundledPath && source && isLocal &&
|
|
194
|
+
normalizePathForCompare(currentBundledPath) !== normalizePathForCompare(source)
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
// Stale = a registered local bundled marketplace whose source no longer
|
|
198
|
+
// resolves to a manifest, OR whose registered path differs from the live
|
|
199
|
+
// app's bundled path (the Windows app-update signal). A missing marketplace
|
|
200
|
+
// is "not stale" but flagged separately by `present: false`.
|
|
201
|
+
const stale = present && isLocal && (!resolvesToManifest || pathMismatch);
|
|
202
|
+
// Present but not a usable local entry (wrong source_type or empty source):
|
|
203
|
+
// not "stale" in the app-update sense, but it must NOT be reported as healthy.
|
|
204
|
+
const malformed = present && !isLocal;
|
|
205
|
+
|
|
206
|
+
const bundledPlugins = COMMON_BUNDLED_PLUGINS.map(id => ({
|
|
207
|
+
id,
|
|
208
|
+
configured: new RegExp(`\\[plugins\\.(?:"${escapeRegExp(`${id}@${OPENAI_BUNDLED_MARKETPLACE_NAME}`)}")\\]`).test(configText),
|
|
209
|
+
}));
|
|
210
|
+
|
|
211
|
+
const repairTarget = currentBundledPath ?? `<current ${OPENAI_BUNDLED_MARKETPLACE_NAME} path under the installed Codex app>`;
|
|
212
|
+
const suggestedRepair = (stale || pathMismatch)
|
|
213
|
+
? `codex plugin marketplace add ${currentBundledPath ? redactUserPath(currentBundledPath) : repairTarget}`
|
|
214
|
+
: null;
|
|
215
|
+
|
|
216
|
+
const summary = !present
|
|
217
|
+
? `no [marketplaces.${OPENAI_BUNDLED_MARKETPLACE_NAME}] entry in Codex config`
|
|
218
|
+
: malformed
|
|
219
|
+
? `[marketplaces.${OPENAI_BUNDLED_MARKETPLACE_NAME}] is present but not a usable local source (source_type/source missing)`
|
|
220
|
+
: !resolvesToManifest
|
|
221
|
+
? `stale: registered ${OPENAI_BUNDLED_MARKETPLACE_NAME} source no longer resolves to a marketplace manifest`
|
|
222
|
+
: pathMismatch
|
|
223
|
+
? `stale: registered ${OPENAI_BUNDLED_MARKETPLACE_NAME} path differs from the installed Codex app's bundled path`
|
|
224
|
+
: `ok: ${OPENAI_BUNDLED_MARKETPLACE_NAME} marketplace resolves`;
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
applicable: true,
|
|
228
|
+
stale,
|
|
229
|
+
marketplace: {
|
|
230
|
+
name: OPENAI_BUNDLED_MARKETPLACE_NAME,
|
|
231
|
+
present,
|
|
232
|
+
sourceType,
|
|
233
|
+
source: source ? redactUserPath(source) : null,
|
|
234
|
+
resolvesToManifest,
|
|
235
|
+
currentBundledPath: currentBundledPath ? redactUserPath(currentBundledPath) : null,
|
|
236
|
+
pathMismatch,
|
|
237
|
+
},
|
|
238
|
+
bundledPlugins,
|
|
239
|
+
suggestedRepair,
|
|
240
|
+
summary,
|
|
241
|
+
};
|
|
242
|
+
}
|