@iislee/opencodex 2.11.0 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS_INSTALL.md +109 -0
- package/README.md +117 -22
- package/bin/ocx.mjs +245 -88
- package/bin/package-main.mjs +1 -1
- package/gui/dist/assets/index-Be1sDpWw.css +1 -0
- package/gui/dist/assets/index-D4OKgUV4.js +114 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/alibaba-color.svg +1 -1
- package/gui/dist/provider-icons/antigravity-color.svg +1 -1
- package/gui/dist/provider-icons/claude-color.svg +1 -1
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -1
- package/gui/dist/provider-icons/cursor-color.svg +1 -1
- package/gui/dist/provider-icons/deepseek-color.svg +1 -1
- package/gui/dist/provider-icons/firepass-color.svg +1 -1
- package/gui/dist/provider-icons/fireworks-color.svg +1 -1
- package/gui/dist/provider-icons/gemini-color.svg +1 -1
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
- package/gui/dist/provider-icons/grok.svg +1 -1
- package/gui/dist/provider-icons/groq-color.svg +1 -1
- package/gui/dist/provider-icons/huggingface-color.svg +1 -1
- package/gui/dist/provider-icons/kimi-color.svg +1 -1
- package/gui/dist/provider-icons/kiro-color.svg +2 -2
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
- package/gui/dist/provider-icons/mistral-color.svg +1 -1
- package/gui/dist/provider-icons/moonshot-color.svg +1 -1
- package/gui/dist/provider-icons/nvidia-color.svg +1 -1
- package/gui/dist/provider-icons/ollama-color.svg +1 -1
- package/gui/dist/provider-icons/openai.svg +1 -1
- package/gui/dist/provider-icons/opencode.svg +2 -1
- package/gui/dist/provider-icons/openrouter-color.svg +1 -1
- package/gui/dist/provider-icons/pi.svg +2 -2
- package/gui/dist/provider-icons/qianfan-color.svg +1 -1
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/vllm-color.svg +1 -1
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
- package/package.json +21 -10
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +475 -62
- package/src/adapters/base.ts +82 -7
- package/src/adapters/client-fingerprint.ts +18 -12
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +637 -0
- package/src/adapters/cursor/call-id.ts +44 -0
- package/src/adapters/cursor/catalog.ts +541 -0
- package/src/adapters/cursor/checkpoint-store.ts +308 -0
- package/src/adapters/cursor/cursor-errors.ts +144 -6
- package/src/adapters/cursor/discovery.ts +122 -14
- package/src/adapters/cursor/effort-map.ts +106 -4
- package/src/adapters/cursor/envelope-echo.ts +290 -0
- package/src/adapters/cursor/framing.ts +39 -0
- package/src/adapters/cursor/h2-pool.ts +123 -0
- package/src/adapters/cursor/http1-bidi.ts +361 -0
- package/src/adapters/cursor/images.ts +704 -0
- package/src/adapters/cursor/live-models.ts +180 -59
- package/src/adapters/cursor/live-transport.ts +623 -170
- package/src/adapters/cursor/message-mapper.ts +4 -1
- package/src/adapters/cursor/native-exec-common.ts +23 -2
- package/src/adapters/cursor/native-exec-desktop.ts +23 -0
- package/src/adapters/cursor/native-exec-fs.ts +10 -7
- package/src/adapters/cursor/native-exec-network.ts +1 -1
- package/src/adapters/cursor/native-exec-shell.ts +5 -3
- package/src/adapters/cursor/native-exec.ts +121 -14
- package/src/adapters/cursor/protobuf-events.ts +829 -11
- package/src/adapters/cursor/protobuf-request.ts +447 -75
- package/src/adapters/cursor/request-builder.ts +271 -35
- package/src/adapters/cursor/tool-definitions.ts +252 -12
- package/src/adapters/cursor/tool-result-normalize.ts +115 -0
- package/src/adapters/cursor/transport.ts +22 -0
- package/src/adapters/cursor/types.ts +48 -1
- package/src/adapters/cursor.ts +336 -39
- package/src/adapters/exec-tool-result-normalize.ts +99 -0
- package/src/adapters/google-antigravity-replay.ts +713 -41
- package/src/adapters/google-antigravity-wire.ts +48 -10
- package/src/adapters/google-errors.ts +44 -12
- package/src/adapters/google-http.ts +38 -10
- package/src/adapters/google-tool-schema.ts +80 -15
- package/src/adapters/google-truncation.ts +11 -0
- package/src/adapters/google.ts +742 -86
- package/src/adapters/identity.ts +39 -6
- package/src/adapters/image.ts +1 -1
- package/src/adapters/kiro-constants.ts +27 -0
- package/src/adapters/kiro-errors.ts +11 -0
- package/src/adapters/kiro-events.ts +19 -1
- package/src/adapters/kiro-thinking.ts +18 -2
- package/src/adapters/kiro-tools.ts +65 -17
- package/src/adapters/kiro.ts +270 -73
- package/src/adapters/mimo-free.ts +17 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1377 -344
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +1164 -64
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/run-turn-queue.ts +36 -1
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +105 -21
- package/src/adapters/xai-tool-schema.ts +436 -0
- package/src/adapters/xai-web-search.ts +186 -0
- package/src/bridge.ts +512 -92
- package/src/chat/inbound.ts +57 -20
- package/src/chat/outbound.ts +97 -33
- package/src/claude/agents-inject.ts +40 -10
- package/src/claude/context-windows.ts +37 -14
- package/src/claude/desktop-3p.ts +243 -9
- package/src/claude/gateway-cache.ts +41 -4
- package/src/claude/inbound.ts +72 -3
- package/src/claude/model-info.ts +38 -15
- package/src/claude/outbound.ts +88 -21
- package/src/cli/access.ts +46 -3
- package/src/cli/account-api.ts +150 -19
- package/src/cli/account-auth.ts +33 -6
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +648 -28
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +97 -19
- package/src/cli/agent.ts +53 -2
- package/src/cli/alias.ts +66 -0
- package/src/cli/capabilities-command.ts +94 -0
- package/src/cli/capabilities.ts +496 -0
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +60 -15
- package/src/cli/claude.ts +129 -35
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +2 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +8 -0
- package/src/cli/config-command.ts +74 -10
- package/src/cli/dispatch.ts +821 -0
- package/src/cli/doctor.ts +440 -56
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +46 -20
- package/src/cli/help.ts +34 -274
- package/src/cli/index.ts +417 -528
- package/src/cli/init.ts +5 -17
- package/src/cli/inspect.ts +230 -0
- package/src/cli/integrations.ts +120 -2
- package/src/cli/lab.ts +607 -0
- package/src/cli/launcher-context.ts +77 -0
- package/src/cli/minimax.ts +497 -0
- package/src/cli/models-runtime.ts +130 -2
- package/src/cli/models.ts +118 -16
- package/src/cli/observe.ts +123 -11
- package/src/cli/opencode.ts +4 -2
- package/src/cli/provider-runtime.ts +34 -3
- package/src/cli/provider.ts +25 -3
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +476 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +57 -10
- package/src/cli/star-prompt.ts +71 -15
- package/src/cli/status.ts +51 -4
- package/src/cli/storage.ts +234 -0
- package/src/cli/system-command.ts +16 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +153 -6
- package/src/cli/usage-report.ts +184 -0
- package/src/cli/v2.ts +137 -18
- package/src/cli/version-skew.ts +46 -0
- package/src/cli.ts +1 -1
- package/src/clients/config-export.ts +1442 -23
- package/src/clients/effective-status.ts +30 -2
- package/src/clients/probes/cline.ts +81 -0
- package/src/codex/account-label.ts +35 -1
- package/src/codex/account-lifecycle.ts +130 -13
- package/src/codex/account-namespaces.ts +49 -3
- package/src/codex/account-pause.ts +2 -1
- package/src/codex/account-priority.ts +84 -0
- package/src/codex/account-store.ts +29 -2
- package/src/codex/account-usability.ts +25 -2
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/app-server-processes.ts +570 -107
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +893 -246
- package/src/codex/auth-collision.ts +5 -3
- package/src/codex/auth-context.ts +348 -32
- package/src/codex/autostart-health.ts +24 -1
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +86 -10
- package/src/codex/catalog/bundled.ts +331 -33
- package/src/codex/catalog/effort.ts +138 -32
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +555 -45
- package/src/codex/catalog/native-models.ts +75 -0
- package/src/codex/catalog/parsing.ts +269 -30
- package/src/codex/catalog/provider-fetch.ts +1626 -144
- package/src/codex/catalog/sync.ts +1576 -187
- package/src/codex/catalog-admission.ts +199 -0
- package/src/codex/catalog-refresh-status.ts +105 -0
- package/src/codex/catalog-write-serialization.ts +242 -0
- package/src/codex/catalog.ts +6 -3
- package/src/codex/codex-write-lock.ts +386 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +676 -0
- package/src/codex/coordinator-doctor.ts +332 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/desktop-app-restart.ts +355 -0
- package/src/codex/features.ts +636 -39
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +436 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-manifest.ts +112 -0
- package/src/codex/history-migration-guardian.ts +30 -24
- package/src/codex/history-provider.ts +1016 -235
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +223 -0
- package/src/codex/inject-coordination.ts +373 -0
- package/src/codex/inject.ts +1114 -152
- package/src/codex/injected-marker.ts +37 -3
- package/src/codex/integration-record.ts +266 -0
- package/src/codex/internal/catalog-writer.ts +203 -0
- package/src/codex/internal/history-writer.ts +81 -0
- package/src/codex/journal.ts +66 -4
- package/src/codex/log-guard/inspect.ts +524 -0
- package/src/codex/log-guard/lock.ts +150 -0
- package/src/codex/log-guard/maintenance.ts +403 -0
- package/src/codex/log-guard/path-safety.ts +88 -0
- package/src/codex/log-guard/policy.ts +44 -0
- package/src/codex/log-guard/processes.ts +205 -0
- package/src/codex/log-guard/protection.ts +489 -0
- package/src/codex/log-guard/sqlite-errors.ts +9 -0
- package/src/codex/main-account-cache.ts +24 -0
- package/src/codex/main-account.ts +29 -1
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +56 -10
- package/src/codex/model-entitlements.ts +360 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +178 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +622 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +675 -0
- package/src/codex/paths.ts +80 -1
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +1 -1
- package/src/codex/pool-rotation.ts +74 -4
- package/src/codex/project-config-warnings.ts +20 -6
- package/src/codex/prompt-journal.ts +352 -0
- package/src/codex/prompt-layers.ts +1313 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/prompt-text-probe.ts +238 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +264 -21
- package/src/codex/refresh.ts +11 -2
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +514 -94
- package/src/codex/runtime.ts +159 -38
- package/src/codex/shim.ts +1065 -31
- package/src/codex/subagent-model-fallback.ts +437 -43
- package/src/codex/sync.ts +191 -2
- package/src/codex/transition-state.ts +720 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +557 -0
- package/src/codex/warmup.ts +187 -81
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +47 -0
- package/src/combos/index.ts +4 -0
- package/src/combos/request.ts +32 -0
- package/src/combos/types.ts +91 -9
- package/src/compatibility/index.ts +26 -0
- package/src/compatibility/manifest.ts +253 -0
- package/src/compatibility/openai-responses.ts +121 -0
- package/src/config/atomic-write.ts +219 -0
- package/src/config/paths.ts +40 -0
- package/src/config/process-state.ts +309 -0
- package/src/config/provider-name.ts +24 -0
- package/src/config/provider-validation.ts +177 -0
- package/src/config/rebase-provenance.ts +68 -0
- package/src/config.ts +1713 -709
- package/src/generated/compatibility-version.json +3324 -0
- package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
- package/src/grok/inject.ts +16 -5
- package/src/grok/inspect.ts +45 -0
- package/src/grok/sync.ts +2 -2
- package/src/images/loop.ts +157 -33
- package/src/images/plan.ts +24 -13
- package/src/integrations/config-io.ts +269 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/mutation-flight.ts +71 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/omp-yaml-source.ts +358 -0
- package/src/integrations/owned-refresh.ts +74 -0
- package/src/integrations/ownership-policy.ts +160 -0
- package/src/integrations/ownership.ts +155 -0
- package/src/integrations/registry.ts +166 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +433 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +715 -0
- package/src/lab/artifacts/sanitize.ts +586 -0
- package/src/lab/artifacts/secure-fs.ts +475 -0
- package/src/lab/artifacts/store.ts +310 -0
- package/src/lab/automation/budgets.ts +78 -0
- package/src/lab/automation/config-persistence.ts +256 -0
- package/src/lab/automation/constants.ts +39 -0
- package/src/lab/automation/cooldown.ts +103 -0
- package/src/lab/automation/dispatch.ts +211 -0
- package/src/lab/automation/index.ts +13 -0
- package/src/lab/automation/orchestrator.ts +499 -0
- package/src/lab/automation/persistence.ts +512 -0
- package/src/lab/automation/planner.ts +371 -0
- package/src/lab/automation/policy.ts +136 -0
- package/src/lab/automation/queue.ts +191 -0
- package/src/lab/automation/recovery.ts +24 -0
- package/src/lab/automation/route-context.ts +21 -0
- package/src/lab/automation/run-key.ts +44 -0
- package/src/lab/automation/runs-query.ts +34 -0
- package/src/lab/automation/types.ts +160 -0
- package/src/lab/conformance/assertion.ts +325 -0
- package/src/lab/conformance/digest.ts +22 -0
- package/src/lab/conformance/executor.ts +741 -0
- package/src/lab/conformance/fixture-provider.ts +27 -0
- package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
- package/src/lab/conformance/harness-budget.ts +47 -0
- package/src/lab/conformance/index.ts +5 -0
- package/src/lab/conformance/jcs.ts +64 -0
- package/src/lab/conformance/json-pointer.ts +39 -0
- package/src/lab/conformance/manifest.ts +180 -0
- package/src/lab/conformance/mcp-stub.ts +179 -0
- package/src/lab/conformance/negative-controls.ts +164 -0
- package/src/lab/conformance/observation.ts +355 -0
- package/src/lab/conformance/runner.ts +68 -0
- package/src/lab/conformance/sse-normalize.ts +59 -0
- package/src/lab/conformance/suite-manifest.ts +78 -0
- package/src/lab/conformance/types.ts +214 -0
- package/src/lab/constants.ts +126 -0
- package/src/lab/digest.ts +64 -0
- package/src/lab/events/errors.ts +9 -0
- package/src/lab/events/limits.ts +117 -0
- package/src/lab/events/types.ts +229 -0
- package/src/lab/events/validate.ts +781 -0
- package/src/lab/fabric/constants.ts +40 -0
- package/src/lab/fabric/executor.ts +492 -0
- package/src/lab/fabric/index.ts +80 -0
- package/src/lab/fabric/manifest.ts +222 -0
- package/src/lab/fabric/observe.ts +489 -0
- package/src/lab/fabric/patch.ts +79 -0
- package/src/lab/fabric/producer-child.ts +139 -0
- package/src/lab/fabric/producer-isolate.ts +276 -0
- package/src/lab/fabric/producer-protocol.ts +61 -0
- package/src/lab/fabric/scratch.ts +439 -0
- package/src/lab/fabric/subject.ts +106 -0
- package/src/lab/fabric/types.ts +134 -0
- package/src/lab/fabric/verifier.ts +98 -0
- package/src/lab/index.ts +54 -0
- package/src/lab/ledger/artifact-refs.ts +127 -0
- package/src/lab/ledger/invalidation.ts +136 -0
- package/src/lab/ledger/purge.ts +310 -0
- package/src/lab/ledger/store.ts +532 -0
- package/src/lab/live/credential-lease.ts +53 -0
- package/src/lab/live/destination.ts +155 -0
- package/src/lab/live/executor.ts +336 -0
- package/src/lab/live/inert-tools.ts +56 -0
- package/src/lab/live/manifest.ts +85 -0
- package/src/lab/live/mcp-loopback.ts +57 -0
- package/src/lab/live/runner.ts +19 -0
- package/src/lab/live/sandbox.ts +61 -0
- package/src/lab/live/suite-manifest.ts +41 -0
- package/src/lab/live/transport.ts +118 -0
- package/src/lab/live/types.ts +197 -0
- package/src/lab/observe/from-conformance.ts +301 -0
- package/src/lab/observe/from-live.ts +117 -0
- package/src/lab/paths.ts +153 -0
- package/src/lab/projection/rebuild.ts +495 -0
- package/src/lab/projection/schema.ts +135 -0
- package/src/lab/projection/verdicts.ts +474 -0
- package/src/lab/projection/verification.ts +412 -0
- package/src/lab/public/bundle.ts +217 -0
- package/src/lab/public/community-authority.ts +175 -0
- package/src/lab/public/community-files.ts +29 -0
- package/src/lab/public/community.ts +479 -0
- package/src/lab/public/file-safety.ts +155 -0
- package/src/lab/public/ids.ts +26 -0
- package/src/lab/public/index.ts +16 -0
- package/src/lab/public/mutation-lock.ts +424 -0
- package/src/lab/public/operator.ts +353 -0
- package/src/lab/public/origin-purge.ts +79 -0
- package/src/lab/public/origin.ts +203 -0
- package/src/lab/public/privacy.ts +143 -0
- package/src/lab/public/private-file.ts +261 -0
- package/src/lab/public/project.ts +124 -0
- package/src/lab/public/purge-test-fault.ts +21 -0
- package/src/lab/public/purge.ts +223 -0
- package/src/lab/public/registry.ts +44 -0
- package/src/lab/public/revocation.ts +252 -0
- package/src/lab/public/signature.ts +243 -0
- package/src/lab/public/storage.ts +105 -0
- package/src/lab/public/strict-json.ts +206 -0
- package/src/lab/public/time.ts +26 -0
- package/src/lab/public/types.ts +172 -0
- package/src/lab/public/validate.ts +391 -0
- package/src/lab/query/catalog.ts +101 -0
- package/src/lab/query/connection.ts +107 -0
- package/src/lab/query/constants.ts +4 -0
- package/src/lab/query/cursor.ts +132 -0
- package/src/lab/query/dto-map.ts +277 -0
- package/src/lab/query/errors.ts +22 -0
- package/src/lab/query/freshness.ts +53 -0
- package/src/lab/query/index.ts +45 -0
- package/src/lab/query/latest-observation.ts +59 -0
- package/src/lab/query/passive-production.ts +159 -0
- package/src/lab/query/queries.ts +444 -0
- package/src/lab/query/types.ts +266 -0
- package/src/lab/subject/behavior-fingerprint.ts +77 -0
- package/src/lab/subject/installation-salt.ts +112 -0
- package/src/lab/subject/protocol-subject.ts +80 -0
- package/src/lab/subject/route-subject.ts +74 -0
- package/src/lib/admin-secrets.ts +24 -0
- package/src/lib/app-owned-memory-stores.ts +22 -0
- package/src/lib/bounded-body.ts +167 -11
- package/src/lib/bun-runtime.ts +125 -12
- package/src/lib/bun-stream-caps.ts +13 -9
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +26 -2
- package/src/lib/destination-policy.ts +65 -1
- package/src/lib/errors.ts +80 -5
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/lab-activation.ts +223 -0
- package/src/lib/lab-live-execution-authority.ts +13 -0
- package/src/lib/lab-live-host.ts +30 -0
- package/src/lib/lab-live-pinned-sender.ts +56 -0
- package/src/lib/lab-live-route-production.ts +130 -0
- package/src/lib/lab-passive-linker-registration.ts +26 -0
- package/src/lib/local-management-attestation.ts +51 -0
- package/src/lib/local-management-capability.ts +100 -0
- package/src/lib/local-provider-reload-contract.ts +100 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/package-tree-integrity.ts +101 -0
- package/src/lib/pinned-http.ts +145 -26
- package/src/lib/process-control.ts +6 -2
- package/src/lib/provider-outbound.ts +49 -9
- package/src/lib/redact.ts +419 -3
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/service-secrets.ts +15 -0
- package/src/lib/shadow-call.ts +35 -4
- package/src/lib/sse-decoder.ts +41 -0
- package/src/lib/state-store-registrations.ts +10 -2
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/token-estimate.ts +19 -2
- package/src/lib/tool-argument-integers.ts +253 -0
- package/src/lib/translator-budget.ts +44 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +156 -3
- package/src/lib/windows-atomic-replace.ts +155 -0
- package/src/lib/windows-elevation.ts +70 -2
- package/src/lib/windows-secret-acl.ts +409 -69
- package/src/lib/windows-service-wrappers.ts +72 -0
- package/src/lib/windows-text.ts +106 -0
- package/src/lib/windows-user-principal.ts +341 -0
- package/src/lib/winsw.ts +33 -5
- package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
- package/src/oauth/account-import/index.ts +15 -0
- package/src/oauth/account-import/parser.ts +83 -0
- package/src/oauth/account-import/registry.ts +18 -0
- package/src/oauth/account-import/service.ts +75 -0
- package/src/oauth/account-import/types.ts +91 -0
- package/src/oauth/anthropic.ts +12 -1
- package/src/oauth/callback-server.ts +30 -4
- package/src/oauth/chatgpt.ts +12 -1
- package/src/oauth/cline.ts +203 -0
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +46 -5
- package/src/oauth/generic-account-failover.ts +231 -0
- package/src/oauth/google-antigravity.ts +35 -3
- package/src/oauth/health.ts +20 -12
- package/src/oauth/index.ts +462 -71
- package/src/oauth/key-providers.ts +25 -0
- package/src/oauth/kimi.ts +25 -3
- package/src/oauth/kiro.ts +95 -6
- package/src/oauth/local-token-detect.ts +13 -2
- package/src/oauth/log.ts +3 -1
- package/src/oauth/login-cli.ts +88 -28
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/open-browser-choice.ts +26 -0
- package/src/oauth/store.ts +133 -26
- package/src/oauth/token-guardian.ts +9 -3
- package/src/oauth/types.ts +15 -0
- package/src/pi/models.ts +2 -2
- package/src/providers/alibaba-region-migration.ts +1 -1
- package/src/providers/antigravity-models.ts +521 -31
- package/src/providers/auto-compact-budget.ts +65 -0
- package/src/providers/base-url-choices.ts +10 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +176 -0
- package/src/providers/context-cap.ts +26 -8
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/default-aliases.ts +65 -0
- package/src/providers/derive.ts +281 -6
- package/src/providers/fastwire.ts +507 -0
- package/src/providers/free-directory.ts +10 -7
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +71 -3
- package/src/providers/label.ts +35 -2
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +115 -22
- package/src/providers/model-presets.ts +119 -0
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/new-model-policy.ts +146 -0
- package/src/providers/openai-sidecar.ts +72 -4
- package/src/providers/openai-tier-startup.ts +31 -2
- package/src/providers/openai-tiers.ts +119 -4
- package/src/providers/openai-virtual-models.ts +1 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +30 -0
- package/src/providers/quota.ts +1379 -40
- package/src/providers/registry.ts +1545 -112
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +94 -6
- package/src/providers/static-model-discovery.ts +86 -0
- package/src/providers/xai-responses-opt-in.ts +15 -0
- package/src/providers/xai-transport.ts +32 -4
- package/src/reasoning-effort.ts +68 -3
- package/src/responses/apply-patch-envelope.ts +63 -0
- package/src/responses/code-mode-helper-compat.ts +50 -0
- package/src/responses/compaction.ts +26 -1
- package/src/responses/custom-tool-compat.ts +384 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +435 -0
- package/src/responses/parser.ts +225 -38
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +9 -1
- package/src/responses/reasoning-replay-cache.ts +504 -0
- package/src/responses/schema.ts +12 -2
- package/src/responses/spill-store.ts +75 -10
- package/src/responses/state.ts +659 -31
- package/src/responses/thought-signature-replay.ts +364 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/responses/turn-termination.ts +107 -0
- package/src/router.ts +405 -31
- package/src/routing/analytics.ts +379 -0
- package/src/routing/capability.ts +244 -0
- package/src/routing/compatibility/assemble.ts +73 -0
- package/src/routing/compatibility/behavior.ts +278 -0
- package/src/routing/compatibility/catalog.ts +99 -0
- package/src/routing/compatibility/endpoint.ts +52 -0
- package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
- package/src/routing/compatibility/policy.ts +181 -0
- package/src/routing/compatibility/provider-slot.ts +56 -0
- package/src/routing/compatibility/reader.ts +110 -0
- package/src/routing/compatibility/subject.ts +191 -0
- package/src/routing/compatibility/types.ts +64 -0
- package/src/routing/compatibility/version.ts +104 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +495 -0
- package/src/routing/health.ts +412 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +547 -0
- package/src/routing/quota.ts +155 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +776 -0
- package/src/server/adapter-resolve.ts +2 -29
- package/src/server/auth-cors.ts +289 -48
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +154 -72
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +445 -0
- package/src/server/claude-messages.ts +160 -44
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +18 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +39 -10
- package/src/server/images.ts +94 -12
- package/src/server/index.ts +1021 -190
- package/src/server/lifecycle.ts +336 -14
- package/src/server/live.ts +136 -17
- package/src/server/local-management-read-client.ts +90 -0
- package/src/server/local-provider-reload-client.ts +137 -0
- package/src/server/management/agent-settings-routes.ts +433 -116
- package/src/server/management/api-key-usage.ts +31 -5
- package/src/server/management/body.ts +6 -0
- package/src/server/management/codex-prompt-routes.ts +570 -0
- package/src/server/management/combo-routes.ts +64 -25
- package/src/server/management/config-routes.ts +511 -51
- package/src/server/management/context.ts +89 -2
- package/src/server/management/integration-routes.ts +498 -0
- package/src/server/management/lab-automation-routes.ts +206 -0
- package/src/server/management/lab-routes.ts +563 -0
- package/src/server/management/logs-usage-routes.ts +127 -52
- package/src/server/management/model-routes.ts +461 -133
- package/src/server/management/model-rows.ts +167 -0
- package/src/server/management/native-integration-routes.ts +770 -0
- package/src/server/management/oauth-account-routes.ts +90 -8
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +836 -159
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/route-registry.ts +332 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +380 -0
- package/src/server/management/shared.ts +27 -11
- package/src/server/management/sidebar-routes.ts +47 -31
- package/src/server/management/storage-log-guard-routes.ts +186 -0
- package/src/server/management/sync-response.ts +69 -0
- package/src/server/management/system-restart.ts +289 -33
- package/src/server/management/system-routes.ts +77 -0
- package/src/server/management/usage-summary-cache.ts +9 -1
- package/src/server/management/vision-sidecar-options.ts +167 -0
- package/src/server/management/web-search-sidecar-options.ts +120 -0
- package/src/server/management-api.ts +126 -23
- package/src/server/management-auth.ts +220 -5
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/port-reclaim.ts +1 -1
- package/src/server/ports.ts +41 -1
- package/src/server/proxy-liveness.ts +161 -10
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +221 -54
- package/src/server/relay.ts +479 -87
- package/src/server/request-decompress.ts +113 -6
- package/src/server/request-log-conversation.ts +51 -0
- package/src/server/request-log.ts +298 -31
- package/src/server/responses/agent-task-recovery-cache.ts +143 -0
- package/src/server/responses/agent-task-recovery.ts +465 -0
- package/src/server/responses/codex-auth-error.ts +55 -0
- package/src/server/responses/collaboration.ts +239 -36
- package/src/server/responses/combo-stream-preflight.ts +178 -0
- package/src/server/responses/compact.ts +444 -72
- package/src/server/responses/core.ts +3579 -436
- package/src/server/responses/empty-completion-guard.ts +333 -0
- package/src/server/responses/encrypted-payload.ts +62 -39
- package/src/server/responses/fetch-helpers.ts +89 -99
- package/src/server/responses/input-admission.ts +187 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/passthrough-error.ts +33 -9
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +343 -0
- package/src/server/responses/terminal-guard.ts +26 -5
- package/src/server/responses/upstream-error.ts +5 -0
- package/src/server/responses/ws-upstream.ts +381 -0
- package/src/server/responses-custom-tool-repair.ts +363 -0
- package/src/server/responses-item-id-repair.ts +54 -6
- package/src/server/responses-json-events.ts +90 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses-terminal-repair.ts +363 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +376 -0
- package/src/server/responses.ts +18 -2
- package/src/server/search.ts +78 -13
- package/src/server/sse-frame-buffer.ts +319 -0
- package/src/server/sse-payload-rewrite.ts +110 -22
- package/src/server/startup-action-control.ts +8 -1
- package/src/server/startup-health-cache.ts +19 -1
- package/src/server/system-env.ts +80 -9
- package/src/server/ws-bridge.ts +53 -40
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +1153 -94
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/storage/cleanup.ts +2 -2
- package/src/storage/policy-job.ts +14 -4
- package/src/storage/policy.ts +88 -23
- package/src/storage/scanner.ts +1 -1
- package/src/storage/worker-lifecycle.ts +14 -14
- package/src/tray/windows-tray.ps1 +83 -9
- package/src/tray/windows.ts +43 -16
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +911 -0
- package/src/types/provider.ts +614 -0
- package/src/types/request.ts +397 -0
- package/src/types/tools.ts +236 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +107 -1237
- package/src/update/index.ts +37 -23
- package/src/update/job.ts +445 -68
- package/src/update/notify.ts +12 -6
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +266 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/expected-prices.ts +287 -16
- package/src/usage/log.ts +666 -50
- package/src/usage/summary.ts +388 -17
- package/src/usage/user-cost-overlay-reconciler.ts +313 -0
- package/src/usage/user-cost-overlays.ts +314 -0
- package/src/vision/anthropic-describe.ts +10 -6
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +27 -16
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +238 -24
- package/src/vision/reasoning.ts +55 -0
- package/src/vision/routed-describe.ts +175 -0
- package/src/vision/timeout-bounds.ts +9 -0
- package/src/web-search/anthropic-executor.ts +13 -7
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +119 -0
- package/src/web-search/executor.ts +21 -6
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +150 -15
- package/src/web-search/loop.ts +284 -54
- package/src/web-search/parse.ts +125 -30
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/xai-executor.ts +219 -0
- package/gui/dist/assets/index-DTpMHS4F.js +0 -67
- package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
- package/gui/dist/provider-icons/antigravity.svg +0 -1
- package/gui/dist/provider-icons/claude.svg +0 -1
- package/gui/dist/provider-icons/copilot.svg +0 -1
- package/gui/dist/provider-icons/cursor.svg +0 -2
- package/gui/dist/provider-icons/gemini.svg +0 -1
- package/gui/dist/provider-icons/grok-color.svg +0 -1
- package/gui/dist/provider-icons/kiro.svg +0 -14
- package/src/cli/internal-dispatch.ts +0 -20
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* N — one bounded writer per canonical `CODEX_HOME`.
|
|
3
|
+
*
|
|
4
|
+
* The failure this closes is lock SPLITTING plus event-loop denial, not a
|
|
5
|
+
* missing mutex. Two spellings of one Codex home can reach different textual
|
|
6
|
+
* paths, and a lock held across provider discovery or history walking recreates
|
|
7
|
+
* the 10.5-second listener stall that killed the previous design.
|
|
8
|
+
*
|
|
9
|
+
* Three decisions are load-bearing and each was forced by a defect:
|
|
10
|
+
*
|
|
11
|
+
* - The namespace keys on the EFFECTIVE USER (uid/SID), never on a home path.
|
|
12
|
+
* Under Bun 1.3.14 both `os.homedir()` and `os.userInfo().homedir` follow the
|
|
13
|
+
* environment, so a service and a CLI for one account can see different homes
|
|
14
|
+
* and coordinate through different databases — exclusion defeated, silently.
|
|
15
|
+
* `resolveCodexCoordinatorDatabasePath` owns that; this module consumes its
|
|
16
|
+
* result verbatim and appends nothing.
|
|
17
|
+
*
|
|
18
|
+
* - The commit callback is SYNCHRONOUS. Provider I/O, subprocesses, history
|
|
19
|
+
* walking and retry sleeps are forbidden beneath it; a thenable that slips
|
|
20
|
+
* through the type is detected, rolled back, and rejected.
|
|
21
|
+
*
|
|
22
|
+
* - Acquisition is finite and typed. `busy` means try again; `refused` means
|
|
23
|
+
* never. Collapsing them is how a permanent denial becomes an endless retry
|
|
24
|
+
* loop wearing the costume of contention.
|
|
25
|
+
*
|
|
26
|
+
* Lock order is `N -> C`. C is `withConfigMutationLockSync`, entered while N is
|
|
27
|
+
* held and released before N commits. There is no `C -> N`.
|
|
28
|
+
*
|
|
29
|
+
* Design record: devlog/_fin/260804_codex_write_substrate/030_lock_protocol.md.
|
|
30
|
+
*/
|
|
31
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
32
|
+
import { createHash } from "node:crypto";
|
|
33
|
+
import { lstatSync, realpathSync } from "node:fs";
|
|
34
|
+
import { isAbsolute, resolve } from "node:path";
|
|
35
|
+
import { homedir } from "node:os";
|
|
36
|
+
|
|
37
|
+
import { withConfigMutationLockSync } from "../config";
|
|
38
|
+
import type {
|
|
39
|
+
CodexCoordinatorTransaction,
|
|
40
|
+
CommitExpectation,
|
|
41
|
+
} from "./convergence-types";
|
|
42
|
+
import { getCodexHome } from "./paths";
|
|
43
|
+
import { nativeMainOwnerFilesystemSupported } from "./native-main-owner";
|
|
44
|
+
import { openCodexCoordinatorTransaction } from "./transition-state";
|
|
45
|
+
import {
|
|
46
|
+
CodexUserIdentityRefusal,
|
|
47
|
+
resolveCodexCoordinatorDatabasePath,
|
|
48
|
+
resolveEffectiveUserIdentity,
|
|
49
|
+
} from "./user-identity";
|
|
50
|
+
|
|
51
|
+
export const CODEX_WRITE_LOCK_MAX_TIMEOUT_MS = 30_000;
|
|
52
|
+
|
|
53
|
+
/** Uniform, small, and jittered: a fixed interval makes contenders resonate. */
|
|
54
|
+
const RETRY_MIN_MS = 25;
|
|
55
|
+
const RETRY_MAX_MS = 75;
|
|
56
|
+
|
|
57
|
+
export type CodexWriteLockRefusalReason =
|
|
58
|
+
| "codex_home_missing"
|
|
59
|
+
| "codex_home_unsafe"
|
|
60
|
+
| "authority_not_proven"
|
|
61
|
+
| "namespace_unsafe"
|
|
62
|
+
| "lock_path_unsafe"
|
|
63
|
+
| "unsupported_filesystem"
|
|
64
|
+
| "reentrant"
|
|
65
|
+
| "lock_unavailable";
|
|
66
|
+
|
|
67
|
+
export type CodexWriteLockResult<T> =
|
|
68
|
+
| { status: "acquired"; value: T; waitedMs: number; lockId: string }
|
|
69
|
+
| { status: "skipped"; reason: "desired_disabled" | "desired_enabled"; waitedMs: number }
|
|
70
|
+
| { status: "busy"; reason: "deadline" | "cancelled"; retryable: true; waitedMs: number; lockId: string }
|
|
71
|
+
| {
|
|
72
|
+
status: "refused";
|
|
73
|
+
reason: CodexWriteLockRefusalReason;
|
|
74
|
+
retryable: false;
|
|
75
|
+
message: string;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export interface CodexWriteLockOptions {
|
|
79
|
+
/** Defaults to the ambient home. An explicit value must MATCH it — see below. */
|
|
80
|
+
codexHome?: string;
|
|
81
|
+
timeoutMs: number;
|
|
82
|
+
signal?: AbortSignal;
|
|
83
|
+
/**
|
|
84
|
+
* Read-only witness obtained before any namespace creation.
|
|
85
|
+
*
|
|
86
|
+
* Typed by what the lock actually uses — one comparable id — rather than by
|
|
87
|
+
* `AdmissionSnapshot`, so a caller that coordinates a write WITHOUT gating on
|
|
88
|
+
* admission can hold the lock honestly. `AdmissionSnapshot` satisfies this
|
|
89
|
+
* structurally through its `authoritySnapshotId`, so existing callers are
|
|
90
|
+
* unchanged; see `write-coordination.ts` for why the two are not the same
|
|
91
|
+
* claim.
|
|
92
|
+
*/
|
|
93
|
+
admitted: CodexWriteWitness;
|
|
94
|
+
/** Authoritative synchronous re-read while N and C are both held. */
|
|
95
|
+
readAdmissionUnderLock(): CodexWriteWitness;
|
|
96
|
+
/** Positively authorized migration of an already-routed pre-substrate home. */
|
|
97
|
+
adoption?: { readonly direction: "apply" | "remove" };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The only thing the lock compares.
|
|
102
|
+
*
|
|
103
|
+
* Kept deliberately minimal: widening it would let the lock depend on evidence
|
|
104
|
+
* a caller cannot re-read under N and C, which is how a comparison starts
|
|
105
|
+
* matching itself instead of detecting drift.
|
|
106
|
+
*/
|
|
107
|
+
export interface CodexWriteWitness {
|
|
108
|
+
readonly authoritySnapshotId: string;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface CodexWriteCommitContext {
|
|
112
|
+
readonly canonicalCodexHome: string;
|
|
113
|
+
readonly lockId: string;
|
|
114
|
+
readonly admission: CodexWriteWitness;
|
|
115
|
+
readonly expectation: CommitExpectation;
|
|
116
|
+
/**
|
|
117
|
+
* The `currentTxId` the coordinator row holds RIGHT NOW.
|
|
118
|
+
*
|
|
119
|
+
* `CommitExpectation` carries the generation pair and the NEW txId, but the
|
|
120
|
+
* conditional row update also matches on the existing one. Without this the
|
|
121
|
+
* caller has to guess it — and guessing `null` works only on a row nobody has
|
|
122
|
+
* ever transitioned, so the guess passes on a fresh machine and fails on a
|
|
123
|
+
* real one.
|
|
124
|
+
*/
|
|
125
|
+
readonly currentTxId: string | null;
|
|
126
|
+
/** Opaque authority over the ALREADY-OPEN transaction. Not SQLite. */
|
|
127
|
+
readonly coordinator: CodexCoordinatorTransaction;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** A synchronous under-lock policy re-read proved the requested apply stale. */
|
|
131
|
+
export class CodexWriteLockSkipped extends Error {
|
|
132
|
+
constructor(readonly reason: "desired_disabled" | "desired_enabled") {
|
|
133
|
+
super(reason);
|
|
134
|
+
this.name = "CodexWriteLockSkipped";
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Rejects an `async` callback at typecheck; a cast thenable is caught at runtime. */
|
|
139
|
+
type Synchronous<T> = T extends PromiseLike<unknown> ? never : T;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Same-task reentrancy detection.
|
|
143
|
+
*
|
|
144
|
+
* NOT the exclusion mechanism — `busy_timeout = 0` before `BEGIN IMMEDIATE`
|
|
145
|
+
* already makes a second open in this process fail with SQLITE_BUSY. This exists
|
|
146
|
+
* only to turn that indistinguishable `busy` into a typed `refused/reentrant`,
|
|
147
|
+
* so a caller is told "you already hold this" rather than "try again forever".
|
|
148
|
+
*/
|
|
149
|
+
const heldHomes = new AsyncLocalStorage<ReadonlySet<string>>();
|
|
150
|
+
|
|
151
|
+
function refuse<T>(reason: CodexWriteLockRefusalReason, message: string): CodexWriteLockResult<T> {
|
|
152
|
+
return { status: "refused", reason, retryable: false, message };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function isBusyError(error: unknown): boolean {
|
|
156
|
+
const code = error && typeof error === "object" && "code" in error
|
|
157
|
+
? String((error as { code?: unknown }).code)
|
|
158
|
+
: "";
|
|
159
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
160
|
+
return code === "SQLITE_BUSY" || code === "SQLITE_LOCKED"
|
|
161
|
+
|| /database (?:is|table is) locked/i.test(message);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function expandLeadingTilde(path: string): string {
|
|
165
|
+
if (path === "~") return homedir();
|
|
166
|
+
if (path.startsWith("~/") || path.startsWith("~\\")) return resolve(homedir(), path.slice(2));
|
|
167
|
+
return path;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface CanonicalCodexHome {
|
|
171
|
+
readonly path: string;
|
|
172
|
+
/** Stable id for one home, independent of which spelling reached us. */
|
|
173
|
+
readonly lockId: string;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Canonicalize a `CODEX_HOME` so every spelling of one directory takes one lock.
|
|
178
|
+
*
|
|
179
|
+
* Default, explicit, absolute, tilde and symlinked spellings must contend; two
|
|
180
|
+
* genuinely different directories must not. A MISSING home is refused rather
|
|
181
|
+
* than resolved optimistically: keeping an unresolved suffix would either split
|
|
182
|
+
* one future home on a case-insensitive filesystem or alias two on a
|
|
183
|
+
* case-sensitive one.
|
|
184
|
+
*/
|
|
185
|
+
export function canonicalizeCodexHome(
|
|
186
|
+
candidate: string,
|
|
187
|
+
): { ok: true; home: CanonicalCodexHome } | { ok: false; reason: CodexWriteLockRefusalReason; message: string } {
|
|
188
|
+
const expanded = resolve(expandLeadingTilde(candidate));
|
|
189
|
+
if (!isAbsolute(expanded)) {
|
|
190
|
+
return { ok: false, reason: "codex_home_unsafe", message: "CODEX_HOME did not resolve to an absolute path." };
|
|
191
|
+
}
|
|
192
|
+
let entry;
|
|
193
|
+
try {
|
|
194
|
+
entry = lstatSync(expanded);
|
|
195
|
+
} catch {
|
|
196
|
+
return { ok: false, reason: "codex_home_missing", message: `CODEX_HOME does not exist: ${expanded}` };
|
|
197
|
+
}
|
|
198
|
+
// A symlinked home is fine — realpath collapses it below, which is how two
|
|
199
|
+
// spellings end up on one lock. A home that is a FILE is not.
|
|
200
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) {
|
|
201
|
+
return { ok: false, reason: "codex_home_unsafe", message: `CODEX_HOME is not a directory: ${expanded}` };
|
|
202
|
+
}
|
|
203
|
+
let canonical: string;
|
|
204
|
+
try {
|
|
205
|
+
canonical = realpathSync.native(expanded);
|
|
206
|
+
if (!lstatSync(canonical).isDirectory()) {
|
|
207
|
+
return { ok: false, reason: "codex_home_unsafe", message: `CODEX_HOME is not a directory: ${canonical}` };
|
|
208
|
+
}
|
|
209
|
+
} catch {
|
|
210
|
+
return { ok: false, reason: "codex_home_missing", message: `CODEX_HOME does not exist: ${expanded}` };
|
|
211
|
+
}
|
|
212
|
+
if (!nativeMainOwnerFilesystemSupported(canonical)) {
|
|
213
|
+
return {
|
|
214
|
+
ok: false,
|
|
215
|
+
reason: "unsupported_filesystem",
|
|
216
|
+
message: `CODEX_HOME is on a filesystem that cannot hold this lock: ${canonical}`,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
// Windows paths are case-insensitive, so two spellings of one directory must
|
|
220
|
+
// hash alike there; POSIX paths are not, so they must not be folded.
|
|
221
|
+
const normalized = process.platform === "win32" ? canonical.toLowerCase() : canonical;
|
|
222
|
+
const lockId = createHash("sha256")
|
|
223
|
+
.update("opencodex-codex-write-lock-v1\0")
|
|
224
|
+
.update(normalized)
|
|
225
|
+
.digest("hex");
|
|
226
|
+
return { ok: true, home: { path: canonical, lockId } };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function sleepJittered(remainingMs: number, signal?: AbortSignal): Promise<void> {
|
|
230
|
+
const span = RETRY_MAX_MS - RETRY_MIN_MS;
|
|
231
|
+
const wait = Math.min(remainingMs, RETRY_MIN_MS + Math.floor(Math.random() * (span + 1)));
|
|
232
|
+
return new Promise(done => {
|
|
233
|
+
const timer = setTimeout(finish, Math.max(1, wait));
|
|
234
|
+
function finish(): void {
|
|
235
|
+
clearTimeout(timer);
|
|
236
|
+
signal?.removeEventListener("abort", finish);
|
|
237
|
+
done();
|
|
238
|
+
}
|
|
239
|
+
signal?.addEventListener("abort", finish, { once: true });
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Hold N for one canonical `CODEX_HOME` and run `commit` while it is held.
|
|
245
|
+
*
|
|
246
|
+
* Returns `acquired` with the callback's value, `busy` when the deadline or the
|
|
247
|
+
* signal ended the wait, or `refused` when nothing about waiting would help. A
|
|
248
|
+
* caller exception is NOT converted into either: it propagates after rollback,
|
|
249
|
+
* because a failed commit is the caller's error and not a lock outcome.
|
|
250
|
+
*/
|
|
251
|
+
export async function withCodexWriteLock<T>(
|
|
252
|
+
options: CodexWriteLockOptions,
|
|
253
|
+
commit: (context: CodexWriteCommitContext) => Synchronous<T>,
|
|
254
|
+
): Promise<CodexWriteLockResult<T>> {
|
|
255
|
+
const { timeoutMs, signal } = options;
|
|
256
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 0 || timeoutMs > CODEX_WRITE_LOCK_MAX_TIMEOUT_MS) {
|
|
257
|
+
return refuse("authority_not_proven",
|
|
258
|
+
`timeoutMs must be an integer between 0 and ${CODEX_WRITE_LOCK_MAX_TIMEOUT_MS}.`);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/*
|
|
262
|
+
* The ambient home is resolved ONCE, and an explicit home must equal it.
|
|
263
|
+
*
|
|
264
|
+
* `classifyNativeRoutedResidue` — the guard that decides whether the
|
|
265
|
+
* coordinator row may be created — resolves its own home from the ambient
|
|
266
|
+
* environment, while the lock path keys on the home WE were given. Forwarding a
|
|
267
|
+
* different explicit home would lock one directory while a different one was
|
|
268
|
+
* safety-checked. Until that guard takes the target as a parameter (WP12), the
|
|
269
|
+
* only honest answer is to refuse the mismatch.
|
|
270
|
+
*/
|
|
271
|
+
const ambient = canonicalizeCodexHome(getCodexHome());
|
|
272
|
+
if (!ambient.ok) return refuse(ambient.reason, ambient.message);
|
|
273
|
+
|
|
274
|
+
let target = ambient.home;
|
|
275
|
+
if (options.codexHome !== undefined) {
|
|
276
|
+
const trimmed = options.codexHome.trim();
|
|
277
|
+
if (!trimmed) return refuse("codex_home_unsafe", "An explicit codexHome must not be blank.");
|
|
278
|
+
const explicit = canonicalizeCodexHome(trimmed);
|
|
279
|
+
if (!explicit.ok) return refuse(explicit.reason, explicit.message);
|
|
280
|
+
if (explicit.home.path !== ambient.home.path) {
|
|
281
|
+
return refuse("authority_not_proven",
|
|
282
|
+
"The requested CODEX_HOME is not the one this process would inspect for safety.");
|
|
283
|
+
}
|
|
284
|
+
target = explicit.home;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const held = heldHomes.getStore();
|
|
288
|
+
if (held?.has(target.lockId)) {
|
|
289
|
+
return refuse("reentrant", "This task already holds the Codex write lock for this CODEX_HOME.");
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
let databasePath: string;
|
|
293
|
+
try {
|
|
294
|
+
databasePath = resolveCodexCoordinatorDatabasePath(resolveEffectiveUserIdentity(), target.path);
|
|
295
|
+
} catch (error) {
|
|
296
|
+
return refuse("namespace_unsafe",
|
|
297
|
+
error instanceof CodexUserIdentityRefusal ? error.message : "The lock namespace could not be resolved.");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const started = performance.now();
|
|
301
|
+
const deadline = started + timeoutMs;
|
|
302
|
+
const waited = (): number => Math.round(performance.now() - started);
|
|
303
|
+
|
|
304
|
+
for (;;) {
|
|
305
|
+
if (signal?.aborted) return { status: "busy", reason: "cancelled", retryable: true, waitedMs: waited(), lockId: target.lockId };
|
|
306
|
+
|
|
307
|
+
let transaction: ReturnType<typeof openCodexCoordinatorTransaction> | undefined;
|
|
308
|
+
try {
|
|
309
|
+
transaction = openCodexCoordinatorTransaction(databasePath, options.adoption);
|
|
310
|
+
} catch (error) {
|
|
311
|
+
// Only contention retries. A malformed database, an unsafe path, or an
|
|
312
|
+
// identity failure will fail identically forever; telling a caller to retry
|
|
313
|
+
// that is how a UI spins on a problem only the user can fix.
|
|
314
|
+
if (!isBusyError(error)) {
|
|
315
|
+
if (error instanceof CodexUserIdentityRefusal) return refuse("lock_path_unsafe", error.message);
|
|
316
|
+
return refuse("lock_unavailable",
|
|
317
|
+
error instanceof Error ? error.message : "The Codex write lock could not be opened.");
|
|
318
|
+
}
|
|
319
|
+
if (performance.now() >= deadline) {
|
|
320
|
+
return { status: "busy", reason: "deadline", retryable: true, waitedMs: waited(), lockId: target.lockId };
|
|
321
|
+
}
|
|
322
|
+
await sleepJittered(deadline - performance.now(), signal);
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// N is held from here. Everything below is synchronous until commit/rollback.
|
|
327
|
+
try {
|
|
328
|
+
const expectation = transaction.expectation();
|
|
329
|
+
const version = transaction.version();
|
|
330
|
+
const nextHeld = new Set(held ?? []);
|
|
331
|
+
nextHeld.add(target.lockId);
|
|
332
|
+
|
|
333
|
+
const value = heldHomes.run(nextHeld, () => withConfigMutationLockSync(() => {
|
|
334
|
+
const current = options.readAdmissionUnderLock();
|
|
335
|
+
if (current.authoritySnapshotId !== options.admitted.authoritySnapshotId) {
|
|
336
|
+
throw new CodexWriteLockStaleAdmission();
|
|
337
|
+
}
|
|
338
|
+
const result = commit({
|
|
339
|
+
canonicalCodexHome: target.path,
|
|
340
|
+
lockId: target.lockId,
|
|
341
|
+
admission: current,
|
|
342
|
+
expectation,
|
|
343
|
+
currentTxId: version.currentTxId,
|
|
344
|
+
coordinator: transaction!.capability,
|
|
345
|
+
});
|
|
346
|
+
// A cast `async` callback would return a thenable here. Awaiting it is
|
|
347
|
+
// impossible — C is synchronous — so the only safe answer is to reject.
|
|
348
|
+
if (result && typeof (result as { then?: unknown }).then === "function") {
|
|
349
|
+
throw new TypeError("The Codex write-lock commit callback must be synchronous.");
|
|
350
|
+
}
|
|
351
|
+
return result;
|
|
352
|
+
}));
|
|
353
|
+
|
|
354
|
+
transaction.assertPublished(expectation);
|
|
355
|
+
transaction.commit();
|
|
356
|
+
return { status: "acquired", value: value as T, waitedMs: waited(), lockId: target.lockId };
|
|
357
|
+
} catch (error) {
|
|
358
|
+
transaction.rollback();
|
|
359
|
+
if (error instanceof CodexWriteLockSkipped) {
|
|
360
|
+
return { status: "skipped", reason: error.reason, waitedMs: waited() };
|
|
361
|
+
}
|
|
362
|
+
if (error instanceof CodexWriteLockStaleAdmission) {
|
|
363
|
+
return refuse("authority_not_proven",
|
|
364
|
+
"The admitted state changed before the commit could be made under the lock.");
|
|
365
|
+
}
|
|
366
|
+
if (isBusyError(error)) {
|
|
367
|
+
if (performance.now() >= deadline) {
|
|
368
|
+
return { status: "busy", reason: "deadline", retryable: true, waitedMs: waited(), lockId: target.lockId };
|
|
369
|
+
}
|
|
370
|
+
await sleepJittered(deadline - performance.now(), signal);
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
throw error;
|
|
374
|
+
} finally {
|
|
375
|
+
transaction.close();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/** Internal: the under-lock re-read disagreed with what was admitted. */
|
|
381
|
+
class CodexWriteLockStaleAdmission extends Error {
|
|
382
|
+
constructor() {
|
|
383
|
+
super("The admitted authority snapshot is stale.");
|
|
384
|
+
this.name = "CodexWriteLockStaleAdmission";
|
|
385
|
+
}
|
|
386
|
+
}
|