@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,557 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Environment-independent identity and namespace resolution for Codex writes.
|
|
3
|
+
*
|
|
4
|
+
* Bun 1.3.14 made the obvious implementation unsafe: both `os.homedir()` and
|
|
5
|
+
* `os.userInfo().homedir` follow HOME. A service and CLI for the same account
|
|
6
|
+
* could therefore coordinate through different databases. The namespace is
|
|
7
|
+
* keyed only by the effective uid/SID and the canonical CODEX_HOME.
|
|
8
|
+
*
|
|
9
|
+
* Design record: devlog/_fin/260804_codex_write_substrate/005_contract.md §7.
|
|
10
|
+
*/
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
12
|
+
import {
|
|
13
|
+
lstatSync,
|
|
14
|
+
mkdirSync,
|
|
15
|
+
realpathSync,
|
|
16
|
+
statSync,
|
|
17
|
+
} from "node:fs";
|
|
18
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
19
|
+
|
|
20
|
+
import { resolveTrustedWindowsPowerShellExe } from "../lib/windows-elevation";
|
|
21
|
+
|
|
22
|
+
import type {
|
|
23
|
+
ResolveCodexCoordinatorDatabasePath,
|
|
24
|
+
ResolveCodexCatalogSerializationDatabasePath,
|
|
25
|
+
ResolveCodexHistorySerializationDatabasePath,
|
|
26
|
+
ResolveEffectiveUserIdentity,
|
|
27
|
+
UserIdentity,
|
|
28
|
+
} from "./convergence-types";
|
|
29
|
+
|
|
30
|
+
const POSIX_PRIVATE_MODE = 0o700;
|
|
31
|
+
const POSIX_TMP_REQUIRED_MODE = 0o1003;
|
|
32
|
+
const POSIX_TMP_PATH = "/tmp";
|
|
33
|
+
const SID_PATTERN = /^S-1-(?:\d+-)+\d+$/i;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Hard budget for the Windows identity-lookup PowerShell child. These lookups
|
|
37
|
+
* run at startup and on config writes; a hung child must fail the lookup
|
|
38
|
+
* (recoverable — the caller refuses) rather than wedge the proxy indefinitely.
|
|
39
|
+
*/
|
|
40
|
+
const WINDOWS_POWERSHELL_LOOKUP_TIMEOUT_MS = 8_000;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The same budget, widened for a contended CI runner.
|
|
44
|
+
*
|
|
45
|
+
* 8s is a generous ceiling for `powershell.exe -Command` on a real desktop and is not one
|
|
46
|
+
* on a GitHub Windows runner executing a quarter of this suite: the composed-acceptance
|
|
47
|
+
* cases fail there with "Windows effective-account lookup timed out" while the child is
|
|
48
|
+
* still starting. That is runner contention, not a hung lookup, and the budget exists to
|
|
49
|
+
* bound the latter.
|
|
50
|
+
*
|
|
51
|
+
* Gated on `CI` alone. A user's machine keeps the 8s ceiling exactly as before, so the
|
|
52
|
+
* recoverable-refusal contract this budget protects is unchanged where it matters.
|
|
53
|
+
*/
|
|
54
|
+
const WINDOWS_POWERSHELL_LOOKUP_TIMEOUT_CI_MS = 30_000;
|
|
55
|
+
|
|
56
|
+
function windowsIdentityLookupTimeoutMs(): number {
|
|
57
|
+
return process.env.CI === "true"
|
|
58
|
+
? WINDOWS_POWERSHELL_LOOKUP_TIMEOUT_CI_MS
|
|
59
|
+
: WINDOWS_POWERSHELL_LOOKUP_TIMEOUT_MS;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* FOLDERID_LocalAppData, and the flag that makes the lookup ignore the caller's
|
|
64
|
+
* environment.
|
|
65
|
+
*
|
|
66
|
+
* The obvious spelling, .NET's
|
|
67
|
+
* `GetFolderPath(SpecialFolder.LocalApplicationData)`, is unusable here: on
|
|
68
|
+
* Windows it resolves through `USERPROFILE`, and when the profile named there has
|
|
69
|
+
* no local AppData directory on disk it returns an EMPTY STRING rather than an
|
|
70
|
+
* error. Any
|
|
71
|
+
* caller that redirected `USERPROFILE` (the test sandbox does, and so does a
|
|
72
|
+
* service account whose profile has not been materialized) therefore refused every
|
|
73
|
+
* coordinator lookup with "returned an empty value", which is the exact
|
|
74
|
+
* environment dependence this module exists to eliminate.
|
|
75
|
+
*
|
|
76
|
+
* `SHGetKnownFolderPath` with a null token and `KF_FLAG_DEFAULT_PATH` reads the
|
|
77
|
+
* known-folder registration for the effective token instead: it returns the real
|
|
78
|
+
* per-user path whether or not the directory exists, and it is unaffected by
|
|
79
|
+
* `USERPROFILE`, `LOCALAPPDATA`, `HOMEDRIVE`, or `HOMEPATH`. A non-null token argument
|
|
80
|
+
* is NOT equivalent: passing (HANDLE)-1 resolves the DEFAULT USER profile
|
|
81
|
+
* (the built-in "Default" profile), which would key coordination to a namespace
|
|
82
|
+
* no real account writes to.
|
|
83
|
+
*/
|
|
84
|
+
const WINDOWS_LOCAL_APPDATA_FOLDER_ID = "F1B32785-6FBA-4FCF-9D55-7B8E7F157091";
|
|
85
|
+
const WINDOWS_KF_FLAG_DEFAULT_PATH = "0x00000400";
|
|
86
|
+
|
|
87
|
+
export class CodexUserIdentityRefusal extends Error {
|
|
88
|
+
readonly code = "CODEX_USER_IDENTITY_REFUSED";
|
|
89
|
+
|
|
90
|
+
constructor(message: string, options?: ErrorOptions) {
|
|
91
|
+
super(message, options);
|
|
92
|
+
this.name = "CodexUserIdentityRefusal";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function refuse(message: string, cause?: unknown): never {
|
|
97
|
+
throw new CodexUserIdentityRefusal(message, cause === undefined ? undefined : { cause });
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function windowsIdentityPowerShellCommand(expression: string): string[] {
|
|
101
|
+
// PowerShell 5.1 can encode redirected native/host output with the active
|
|
102
|
+
// Windows code page. Base64 contains ASCII only, while the payload is
|
|
103
|
+
// explicitly UTF-16LE, so Korean and Western profile paths arrive unchanged.
|
|
104
|
+
const deterministicOutput = [
|
|
105
|
+
"$ErrorActionPreference = 'Stop'",
|
|
106
|
+
`$ocxValue = [string](${expression})`,
|
|
107
|
+
"$ocxBytes = [System.Text.Encoding]::Unicode.GetBytes($ocxValue)",
|
|
108
|
+
"[Console]::Out.Write([Convert]::ToBase64String($ocxBytes))",
|
|
109
|
+
].join("; ");
|
|
110
|
+
return [
|
|
111
|
+
resolveTrustedWindowsPowerShellExe(),
|
|
112
|
+
"-NoLogo",
|
|
113
|
+
"-NoProfile",
|
|
114
|
+
"-NonInteractive",
|
|
115
|
+
"-Command",
|
|
116
|
+
deterministicOutput,
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function windowsIdentityPowerShellSpawnOptions(): {
|
|
121
|
+
stdin: "ignore";
|
|
122
|
+
stdout: "pipe";
|
|
123
|
+
stderr: "pipe";
|
|
124
|
+
timeout: number;
|
|
125
|
+
windowsHide: boolean;
|
|
126
|
+
} {
|
|
127
|
+
return {
|
|
128
|
+
stdin: "ignore",
|
|
129
|
+
stdout: "pipe",
|
|
130
|
+
stderr: "pipe",
|
|
131
|
+
timeout: windowsIdentityLookupTimeoutMs(),
|
|
132
|
+
windowsHide: true,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Test-only readback of the trusted executable and static arguments (#1278). */
|
|
137
|
+
export function windowsIdentityPowerShellCommandForTests(expression: string): string[] {
|
|
138
|
+
return windowsIdentityPowerShellCommand(expression);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* PowerShell expression yielding the effective account's local AppData path.
|
|
143
|
+
*
|
|
144
|
+
* P/Invoke rather than a .NET convenience wrapper, for the reason recorded on
|
|
145
|
+
* WINDOWS_LOCAL_APPDATA_FOLDER_ID: the wrapper follows `USERPROFILE` and answers
|
|
146
|
+
* an empty string for a profile whose directory is absent, which is precisely
|
|
147
|
+
* the environment dependence this module refuses to inherit. The type is added
|
|
148
|
+
* under a unique name per process because `Add-Type` cannot redefine one.
|
|
149
|
+
*
|
|
150
|
+
* The whole sequence is wrapped in one `$(...)` subexpression because the caller
|
|
151
|
+
* substitutes this text into `[string](<expression>)`; several statements
|
|
152
|
+
* spliced in bare would close that cast's parenthesis early and fail to parse.
|
|
153
|
+
*/
|
|
154
|
+
function windowsLocalAppDataExpression(): string {
|
|
155
|
+
const signature =
|
|
156
|
+
'[DllImport("shell32.dll", CharSet = CharSet.Unicode)] public static extern int '
|
|
157
|
+
+ 'SHGetKnownFolderPath(ref System.Guid id, uint flags, System.IntPtr token, out System.IntPtr path);';
|
|
158
|
+
const statements = [
|
|
159
|
+
`$ocxShell = Add-Type -MemberDefinition '${signature}'`
|
|
160
|
+
+ " -Name OcxKnownFolder -Namespace OcxIdentity -PassThru",
|
|
161
|
+
`$ocxFolderId = [System.Guid]'${WINDOWS_LOCAL_APPDATA_FOLDER_ID}'`,
|
|
162
|
+
"$ocxPathPtr = [System.IntPtr]::Zero",
|
|
163
|
+
"$ocxHr = $ocxShell::SHGetKnownFolderPath([ref]$ocxFolderId, "
|
|
164
|
+
+ `${WINDOWS_KF_FLAG_DEFAULT_PATH}, [System.IntPtr]::Zero, [ref]$ocxPathPtr)`,
|
|
165
|
+
"if ($ocxHr -ne 0) { throw 'SHGetKnownFolderPath failed' }",
|
|
166
|
+
"try { [System.Runtime.InteropServices.Marshal]::PtrToStringUni($ocxPathPtr) }"
|
|
167
|
+
+ " finally { [System.Runtime.InteropServices.Marshal]::FreeCoTaskMem($ocxPathPtr) }",
|
|
168
|
+
];
|
|
169
|
+
return `$(${statements.join("; ")})`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Test-only readback of the environment-independent known-folder expression. */
|
|
173
|
+
export function windowsLocalAppDataExpressionForTests(): string {
|
|
174
|
+
return windowsLocalAppDataExpression();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** Test-only readback of the spawn options shared by the identity lookups (#1278). */
|
|
178
|
+
export function windowsIdentityPowerShellSpawnOptionsForTests(): ReturnType<
|
|
179
|
+
typeof windowsIdentityPowerShellSpawnOptions
|
|
180
|
+
> {
|
|
181
|
+
return windowsIdentityPowerShellSpawnOptions();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function decodeWindowsIdentityPowerShellOutput(output: Uint8Array): string {
|
|
185
|
+
let encoded: string;
|
|
186
|
+
try {
|
|
187
|
+
encoded = new TextDecoder("utf-8", { fatal: true }).decode(output).trim();
|
|
188
|
+
} catch (cause) {
|
|
189
|
+
refuse("Windows effective-account lookup returned a malformed value.", cause);
|
|
190
|
+
}
|
|
191
|
+
if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(encoded)) {
|
|
192
|
+
refuse("Windows effective-account lookup returned a malformed value.");
|
|
193
|
+
}
|
|
194
|
+
const bytes = Buffer.from(encoded, "base64");
|
|
195
|
+
if (bytes.length % 2 !== 0 || bytes.toString("base64") !== encoded) {
|
|
196
|
+
refuse("Windows effective-account lookup returned a malformed value.");
|
|
197
|
+
}
|
|
198
|
+
return bytes.toString("utf16le").trim();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Test-only decode seam for the deterministic PowerShell output contract. */
|
|
202
|
+
export function decodeWindowsIdentityPowerShellOutputForTests(output: Uint8Array): string {
|
|
203
|
+
return decodeWindowsIdentityPowerShellOutput(output);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Per-process memo for the Windows lookups.
|
|
208
|
+
*
|
|
209
|
+
* Both values -- the effective token's SID and its known-folder local AppData --
|
|
210
|
+
* are fixed for the lifetime of a process: neither can change without a new logon
|
|
211
|
+
* token, and the lookups deliberately ignore the environment, so nothing a caller
|
|
212
|
+
* does between two calls can alter the answer. Each call otherwise spawns a fresh
|
|
213
|
+
* PowerShell, roughly 150ms for the SID and 310ms for the folder, and the
|
|
214
|
+
* coordinator asks for both on every config write and lock acquisition. That cost
|
|
215
|
+
* pushed real multi-process injection tests past their budget while proving
|
|
216
|
+
* nothing: the second spawn re-derives what the first already established.
|
|
217
|
+
*
|
|
218
|
+
* Only successful lookups are memoized, so a transient failure cannot pin the
|
|
219
|
+
* process into a permanently refusing state.
|
|
220
|
+
*/
|
|
221
|
+
const windowsIdentityValueCache = new Map<string, string>();
|
|
222
|
+
|
|
223
|
+
/** Test-only reset so a suite can force a fresh lookup. */
|
|
224
|
+
export function resetWindowsIdentityValueCacheForTests(): void {
|
|
225
|
+
windowsIdentityValueCache.clear();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function powershellValue(expression: string): string {
|
|
229
|
+
const memoized = windowsIdentityValueCache.get(expression);
|
|
230
|
+
if (memoized !== undefined) return memoized;
|
|
231
|
+
let command: string[];
|
|
232
|
+
try {
|
|
233
|
+
command = windowsIdentityPowerShellCommand(expression);
|
|
234
|
+
} catch (cause) {
|
|
235
|
+
refuse("Windows effective-account lookup could not start.", cause);
|
|
236
|
+
}
|
|
237
|
+
let result: ReturnType<typeof Bun.spawnSync>;
|
|
238
|
+
try {
|
|
239
|
+
// `windowsHide` is the popup fix (#1278): the desktop proxy parent runs
|
|
240
|
+
// without a console, so a console-subsystem child spawned without
|
|
241
|
+
// CREATE_NO_WINDOW gets a fresh visible console window at startup and on
|
|
242
|
+
// every config write. Do not add PowerShell's `-WindowStyle Hidden` here:
|
|
243
|
+
// Bun 1.3.14 can fail that direct CLI combination before the SID command
|
|
244
|
+
// executes (#1589); the process-level `windowsHide` flag is sufficient.
|
|
245
|
+
result = Bun.spawnSync(command, windowsIdentityPowerShellSpawnOptions());
|
|
246
|
+
} catch (cause) {
|
|
247
|
+
refuse("Windows effective-account lookup could not start.", cause);
|
|
248
|
+
}
|
|
249
|
+
if (result.exitedDueToTimeout) refuse("Windows effective-account lookup timed out.");
|
|
250
|
+
if (result.exitCode !== 0) refuse("Windows effective-account lookup failed.");
|
|
251
|
+
const value = decodeWindowsIdentityPowerShellOutput(result.stdout ?? Buffer.alloc(0));
|
|
252
|
+
if (!value) refuse("Windows effective-account lookup returned an empty value.");
|
|
253
|
+
windowsIdentityValueCache.set(expression, value);
|
|
254
|
+
return value;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function resolveWindowsSid(): string {
|
|
258
|
+
const sid = powershellValue(
|
|
259
|
+
"[System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value",
|
|
260
|
+
);
|
|
261
|
+
if (!SID_PATTERN.test(sid)) refuse("Windows effective-account lookup returned an invalid SID.");
|
|
262
|
+
return sid.toUpperCase();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export const resolveEffectiveUserIdentity: ResolveEffectiveUserIdentity = () => {
|
|
266
|
+
if (process.platform === "win32") {
|
|
267
|
+
return { platform: "win32", sid: resolveWindowsSid() };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const getuid = process.getuid;
|
|
271
|
+
if (typeof getuid !== "function") {
|
|
272
|
+
refuse("The runtime does not expose the effective POSIX uid.");
|
|
273
|
+
}
|
|
274
|
+
let uid: number;
|
|
275
|
+
try {
|
|
276
|
+
uid = getuid.call(process);
|
|
277
|
+
} catch (cause) {
|
|
278
|
+
refuse("The effective POSIX uid lookup failed.", cause);
|
|
279
|
+
}
|
|
280
|
+
if (!Number.isSafeInteger(uid) || uid < 0) {
|
|
281
|
+
refuse("The runtime returned an invalid effective POSIX uid.");
|
|
282
|
+
}
|
|
283
|
+
return { platform: "posix", uid };
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
function assertPrivatePosixDirectory(path: string, uid: number): void {
|
|
287
|
+
let entry;
|
|
288
|
+
try {
|
|
289
|
+
entry = lstatSync(path);
|
|
290
|
+
} catch (cause) {
|
|
291
|
+
refuse("The Codex coordinator namespace cannot be inspected.", cause);
|
|
292
|
+
}
|
|
293
|
+
if (entry.isSymbolicLink() || !entry.isDirectory()) {
|
|
294
|
+
refuse("The Codex coordinator namespace is not a real directory.");
|
|
295
|
+
}
|
|
296
|
+
if (entry.uid !== uid || (entry.mode & 0o777) !== POSIX_PRIVATE_MODE) {
|
|
297
|
+
refuse("The Codex coordinator namespace has unsafe ownership or permissions.");
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function ensurePrivatePosixDirectory(path: string, uid: number): void {
|
|
302
|
+
try {
|
|
303
|
+
mkdirSync(path, { mode: POSIX_PRIVATE_MODE });
|
|
304
|
+
} catch (cause) {
|
|
305
|
+
const code = cause && typeof cause === "object" && "code" in cause
|
|
306
|
+
? String((cause as { code?: unknown }).code)
|
|
307
|
+
: "";
|
|
308
|
+
if (code !== "EEXIST") refuse("The Codex coordinator namespace cannot be created.", cause);
|
|
309
|
+
}
|
|
310
|
+
assertPrivatePosixDirectory(path, uid);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function resolveTrustedPosixTmp(): string {
|
|
314
|
+
let realTmp: string;
|
|
315
|
+
try {
|
|
316
|
+
realTmp = realpathSync.native(POSIX_TMP_PATH);
|
|
317
|
+
const entry = statSync(realTmp);
|
|
318
|
+
if (!entry.isDirectory() || entry.uid !== 0) {
|
|
319
|
+
refuse("The system temporary directory has unsafe ownership.");
|
|
320
|
+
}
|
|
321
|
+
if ((entry.mode & POSIX_TMP_REQUIRED_MODE) !== POSIX_TMP_REQUIRED_MODE) {
|
|
322
|
+
refuse("The system temporary directory lacks sticky world write/search permissions.");
|
|
323
|
+
}
|
|
324
|
+
} catch (cause) {
|
|
325
|
+
if (cause instanceof CodexUserIdentityRefusal) throw cause;
|
|
326
|
+
refuse("The system temporary directory cannot be trusted.", cause);
|
|
327
|
+
}
|
|
328
|
+
return realTmp;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function resolvePosixRuntimeRoot(uid: number): string {
|
|
332
|
+
const realTmp = resolveTrustedPosixTmp();
|
|
333
|
+
const root = join(realTmp, `opencodex-runtime-v1-${uid}`);
|
|
334
|
+
ensurePrivatePosixDirectory(root, uid);
|
|
335
|
+
return root;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export type CoordinatorNamespaceProbe =
|
|
339
|
+
| { readonly status: "ok"; readonly root: string }
|
|
340
|
+
| { readonly status: "missing" };
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Read-only namespace probe for diagnostics (`ocx doctor`).
|
|
344
|
+
*
|
|
345
|
+
* Unlike the runtime resolvers, this never creates the root or the lock
|
|
346
|
+
* directories: a doctor run must observe the namespace, not initialize it.
|
|
347
|
+
* A missing namespace is reported as `missing` instead of refused, so a fresh
|
|
348
|
+
* machine does not read as a broken one; an existing but unsafe namespace is
|
|
349
|
+
* refused exactly like the creating path would refuse it.
|
|
350
|
+
*/
|
|
351
|
+
export function probeCodexCoordinatorNamespace(identity: UserIdentity): CoordinatorNamespaceProbe {
|
|
352
|
+
if (identity.platform === "posix") {
|
|
353
|
+
const root = join(resolveTrustedPosixTmp(), `opencodex-runtime-v1-${identity.uid}`);
|
|
354
|
+
let entry;
|
|
355
|
+
try {
|
|
356
|
+
entry = lstatSync(root);
|
|
357
|
+
} catch (cause) {
|
|
358
|
+
const code = cause && typeof cause === "object" && "code" in cause
|
|
359
|
+
? String((cause as { code?: unknown }).code)
|
|
360
|
+
: "";
|
|
361
|
+
if (code === "ENOENT") return { status: "missing" };
|
|
362
|
+
refuse("The Codex coordinator namespace cannot be inspected.", cause);
|
|
363
|
+
}
|
|
364
|
+
if (entry.isSymbolicLink() || !entry.isDirectory()) {
|
|
365
|
+
refuse("The Codex coordinator namespace is not a real directory.");
|
|
366
|
+
}
|
|
367
|
+
if (entry.uid !== identity.uid || (entry.mode & 0o777) !== POSIX_PRIVATE_MODE) {
|
|
368
|
+
refuse("The Codex coordinator namespace has unsafe ownership or permissions.");
|
|
369
|
+
}
|
|
370
|
+
return { status: "ok", root };
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (!SID_PATTERN.test(identity.sid)) refuse("The coordinator identity contains an invalid SID.");
|
|
374
|
+
const localAppData = powershellValue(windowsLocalAppDataExpression());
|
|
375
|
+
if (!isAbsolute(localAppData)) refuse("Windows LocalAppData resolution returned a relative path.");
|
|
376
|
+
const root = resolve(localAppData, "OpenCodex", "Runtime", "v1", identity.sid.toUpperCase());
|
|
377
|
+
let entry;
|
|
378
|
+
try {
|
|
379
|
+
entry = lstatSync(root);
|
|
380
|
+
} catch (cause) {
|
|
381
|
+
const code = cause && typeof cause === "object" && "code" in cause
|
|
382
|
+
? String((cause as { code?: unknown }).code)
|
|
383
|
+
: "";
|
|
384
|
+
if (code === "ENOENT") return { status: "missing" };
|
|
385
|
+
refuse("The Windows coordinator namespace cannot be inspected.", cause);
|
|
386
|
+
}
|
|
387
|
+
if (entry.isSymbolicLink() || !entry.isDirectory()) {
|
|
388
|
+
refuse("The Windows coordinator namespace is not a real directory.");
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
const real = realpathSync.native(root);
|
|
392
|
+
if (!samePathIdentity(real, root, "win32")) {
|
|
393
|
+
refuse("The Windows coordinator namespace is redirected by a junction or reparse point.");
|
|
394
|
+
}
|
|
395
|
+
return { status: "ok", root: real };
|
|
396
|
+
} catch (cause) {
|
|
397
|
+
if (cause instanceof CodexUserIdentityRefusal) throw cause;
|
|
398
|
+
refuse("The Windows coordinator namespace cannot be resolved.", cause);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function resolveWindowsRuntimeRoot(identity: Extract<UserIdentity, { platform: "win32" }>): string {
|
|
403
|
+
if (!SID_PATTERN.test(identity.sid)) refuse("The coordinator identity contains an invalid SID.");
|
|
404
|
+
const localAppData = powershellValue(windowsLocalAppDataExpression());
|
|
405
|
+
if (!isAbsolute(localAppData)) refuse("Windows LocalAppData resolution returned a relative path.");
|
|
406
|
+
|
|
407
|
+
// The SID and known-folder values come from the effective token/.NET OS APIs,
|
|
408
|
+
// never USERPROFILE or LOCALAPPDATA. WP11 adds descriptor/reparse/ACL checks at
|
|
409
|
+
// the stable-database open boundary where those checks can cover SQLite too.
|
|
410
|
+
const root = resolve(localAppData, "OpenCodex", "Runtime", "v1", identity.sid.toUpperCase());
|
|
411
|
+
try {
|
|
412
|
+
mkdirSync(root, { recursive: true });
|
|
413
|
+
} catch (cause) {
|
|
414
|
+
refuse("The Windows coordinator namespace cannot be created.", cause);
|
|
415
|
+
}
|
|
416
|
+
// Canonicalize before anything is keyed on the path: a junctioned or
|
|
417
|
+
// differently-cased LocalAppData must land on ONE namespace, or two processes
|
|
418
|
+
// that share the real directory would build different lock paths and never
|
|
419
|
+
// contend. The lock modules also compare this path against realpath, so a
|
|
420
|
+
// non-canonical spelling here would read as "unsafe" on every acquisition.
|
|
421
|
+
//
|
|
422
|
+
// Canonicalizing must only ever fold spelling (case, separators). If the
|
|
423
|
+
// realpath lands somewhere else entirely, a component of the namespace is a
|
|
424
|
+
// junction/reparse redirect; accepting the target would convert the old
|
|
425
|
+
// refusal into silently opening the redirected location, so refuse instead.
|
|
426
|
+
try {
|
|
427
|
+
const real = realpathSync.native(root);
|
|
428
|
+
if (!samePathIdentity(real, root, "win32")) {
|
|
429
|
+
refuse("The Windows coordinator namespace is redirected by a junction or reparse point.");
|
|
430
|
+
}
|
|
431
|
+
return real;
|
|
432
|
+
} catch (cause) {
|
|
433
|
+
if (cause instanceof CodexUserIdentityRefusal) throw cause;
|
|
434
|
+
refuse("The Windows coordinator namespace cannot be resolved.", cause);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Windows path identity is case-insensitive; everywhere else it is exact.
|
|
440
|
+
*
|
|
441
|
+
* The lock modules compare a requested lock path against its own realpath, and
|
|
442
|
+
* byte equality refuses legitimate Windows spellings (drive-letter case, mixed
|
|
443
|
+
* component casing) as "unsafe". This is the same semantics
|
|
444
|
+
* `history-provider.ts` already applies to manifest paths; the platform
|
|
445
|
+
* argument exists so both branches are testable on any host.
|
|
446
|
+
*/
|
|
447
|
+
export function samePathIdentity(
|
|
448
|
+
a: string,
|
|
449
|
+
b: string,
|
|
450
|
+
platform: NodeJS.Platform = process.platform,
|
|
451
|
+
): boolean {
|
|
452
|
+
const left = resolve(a);
|
|
453
|
+
const right = resolve(b);
|
|
454
|
+
return platform === "win32" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export const resolveCodexCoordinatorDatabasePath: ResolveCodexCoordinatorDatabasePath = (
|
|
458
|
+
identity,
|
|
459
|
+
canonicalCodexHome,
|
|
460
|
+
) => {
|
|
461
|
+
if (!isAbsolute(canonicalCodexHome)) {
|
|
462
|
+
refuse("The canonical CODEX_HOME must be an absolute path.");
|
|
463
|
+
}
|
|
464
|
+
const root = identity.platform === "posix"
|
|
465
|
+
? resolvePosixRuntimeRoot(identity.uid)
|
|
466
|
+
: resolveWindowsRuntimeRoot(identity);
|
|
467
|
+
const locks = join(root, "native-write-locks");
|
|
468
|
+
if (identity.platform === "posix") ensurePrivatePosixDirectory(locks, identity.uid);
|
|
469
|
+
else {
|
|
470
|
+
try {
|
|
471
|
+
mkdirSync(locks, { recursive: true });
|
|
472
|
+
} catch (cause) {
|
|
473
|
+
refuse("The Windows coordinator lock directory cannot be created.", cause);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const homeDigest = createHash("sha256").update(canonicalCodexHome).digest("hex");
|
|
478
|
+
return join(locks, `${homeDigest}.sqlite`);
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* K's FINAL database path. Never the native coordinator path.
|
|
483
|
+
*
|
|
484
|
+
* Catalog serialization is a different ownership surface from the native
|
|
485
|
+
* coordinator N: `K -> C` is a legal order and `N -> K` nests, so sharing one
|
|
486
|
+
* database would make the required nesting self-contend. The two live in
|
|
487
|
+
* sibling directories under the same per-user runtime root — same identity
|
|
488
|
+
* namespace, same environment-independent parent, distinct exclusion.
|
|
489
|
+
*
|
|
490
|
+
* Consumers use the returned path verbatim and append nothing
|
|
491
|
+
* (`005_contract.md:1256-1330`).
|
|
492
|
+
*/
|
|
493
|
+
export const resolveCodexCatalogSerializationDatabasePath:
|
|
494
|
+
ResolveCodexCatalogSerializationDatabasePath = (identity, canonicalCodexHome) => {
|
|
495
|
+
if (!isAbsolute(canonicalCodexHome)) {
|
|
496
|
+
refuse("The canonical CODEX_HOME must be an absolute path.");
|
|
497
|
+
}
|
|
498
|
+
const root = identity.platform === "posix"
|
|
499
|
+
? resolvePosixRuntimeRoot(identity.uid)
|
|
500
|
+
: resolveWindowsRuntimeRoot(identity);
|
|
501
|
+
const locks = join(root, "catalog-write-locks");
|
|
502
|
+
if (identity.platform === "posix") ensurePrivatePosixDirectory(locks, identity.uid);
|
|
503
|
+
else {
|
|
504
|
+
try {
|
|
505
|
+
mkdirSync(locks, { recursive: true });
|
|
506
|
+
} catch (cause) {
|
|
507
|
+
refuse("The Windows catalog serialization directory cannot be created.", cause);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const homeDigest = createHash("sha256").update(canonicalCodexHome).digest("hex");
|
|
512
|
+
return join(locks, `${homeDigest}.sqlite`);
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* H's FINAL database path.
|
|
517
|
+
*
|
|
518
|
+
* Keyed by the canonical state DB in addition to the canonical home, unlike N and
|
|
519
|
+
* K. One `CODEX_HOME` can name a different `state_5.sqlite` — `model_catalog_json`
|
|
520
|
+
* has the same shape of indirection for catalogs — and two operations against
|
|
521
|
+
* different history databases are not the same exclusion. Hashing only the home
|
|
522
|
+
* would serialize them together, and hashing the raw request path would let two
|
|
523
|
+
* spellings of one database take different locks.
|
|
524
|
+
*/
|
|
525
|
+
export const resolveCodexHistorySerializationDatabasePath:
|
|
526
|
+
ResolveCodexHistorySerializationDatabasePath = (
|
|
527
|
+
identity,
|
|
528
|
+
canonicalCodexHome,
|
|
529
|
+
canonicalStateDbPath,
|
|
530
|
+
) => {
|
|
531
|
+
if (!isAbsolute(canonicalCodexHome)) {
|
|
532
|
+
refuse("The canonical CODEX_HOME must be an absolute path.");
|
|
533
|
+
}
|
|
534
|
+
if (!isAbsolute(canonicalStateDbPath)) {
|
|
535
|
+
refuse("The canonical Codex state database must be an absolute path.");
|
|
536
|
+
}
|
|
537
|
+
const root = identity.platform === "posix"
|
|
538
|
+
? resolvePosixRuntimeRoot(identity.uid)
|
|
539
|
+
: resolveWindowsRuntimeRoot(identity);
|
|
540
|
+
const locks = join(root, "history-write-locks");
|
|
541
|
+
if (identity.platform === "posix") ensurePrivatePosixDirectory(locks, identity.uid);
|
|
542
|
+
else {
|
|
543
|
+
try {
|
|
544
|
+
mkdirSync(locks, { recursive: true });
|
|
545
|
+
} catch (cause) {
|
|
546
|
+
refuse("The Windows history serialization directory cannot be created.", cause);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Both components are length-prefixed so no pair of (home, stateDb) values can
|
|
551
|
+
// collide by concatenation.
|
|
552
|
+
const digest = createHash("sha256")
|
|
553
|
+
.update(`${canonicalCodexHome.length}:${canonicalCodexHome}`)
|
|
554
|
+
.update(`${canonicalStateDbPath.length}:${canonicalStateDbPath}`)
|
|
555
|
+
.digest("hex");
|
|
556
|
+
return join(locks, `${digest}.sqlite`);
|
|
557
|
+
};
|