@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,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Production host integration for CL-03 trusted exact-route execution.
|
|
3
|
+
*
|
|
4
|
+
* Issues a host-recognized `TrustedLabRouteExecutor` that routes provider traffic
|
|
5
|
+
* through the CL-03 credential lease, pinned transport, and observation normalization
|
|
6
|
+
* pipeline. Secret material stays outside Lab modules.
|
|
7
|
+
*
|
|
8
|
+
* @internal host integration only
|
|
9
|
+
*/
|
|
10
|
+
import { resolveEnvValue } from "../config";
|
|
11
|
+
import {
|
|
12
|
+
getValidAccessTokenSnapshot,
|
|
13
|
+
OAuthLoginRequiredError,
|
|
14
|
+
UnsupportedOAuthProviderError,
|
|
15
|
+
} from "../oauth";
|
|
16
|
+
import type { OcxConfig } from "../types";
|
|
17
|
+
import { createCredentialLease } from "../lab/live/credential-lease";
|
|
18
|
+
import {
|
|
19
|
+
liveUpstreamRequestPath,
|
|
20
|
+
normalizeLabLiveTransportObservation,
|
|
21
|
+
} from "../lab/live/executor";
|
|
22
|
+
import { createPinnedTransport } from "../lab/live/transport";
|
|
23
|
+
import { TransportError } from "../lab/live/transport";
|
|
24
|
+
import type { LabRouteContext } from "../lab/live/types";
|
|
25
|
+
import { createLabAuthorizedPinnedSender } from "./lab-live-pinned-sender";
|
|
26
|
+
import { createHostIssuedLabRouteExecutor } from "./lab-live-host";
|
|
27
|
+
import type { TrustedLabRouteExecutor } from "../lab/live/types";
|
|
28
|
+
|
|
29
|
+
const CREDENTIAL_HEADER = /(authorization|api[-_]?key|token|secret|credential|cookie)/i;
|
|
30
|
+
|
|
31
|
+
export interface ProductionLabRouteExecutorDeps {
|
|
32
|
+
configDir?: string;
|
|
33
|
+
loadConfig: () => OcxConfig;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function buildLabProviderAuthHeaders(
|
|
37
|
+
routeContext: LabRouteContext,
|
|
38
|
+
config: OcxConfig,
|
|
39
|
+
): Promise<Record<string, string>> {
|
|
40
|
+
const provider = config.providers?.[routeContext.providerId];
|
|
41
|
+
if (!provider || provider.disabled === true) {
|
|
42
|
+
throw new TransportError("auth_blocked", "provider unavailable");
|
|
43
|
+
}
|
|
44
|
+
if (provider.authMode === "forward") {
|
|
45
|
+
throw new TransportError("auth_blocked", "forward auth unsupported for lab probes");
|
|
46
|
+
}
|
|
47
|
+
if (provider.authMode === "local") {
|
|
48
|
+
throw new TransportError("auth_blocked", "local provider unsupported for lab probes");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const headers: Record<string, string> = {
|
|
52
|
+
Accept: "application/json",
|
|
53
|
+
"Content-Type": "application/json",
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (provider.authMode === "oauth") {
|
|
57
|
+
let protocol: string;
|
|
58
|
+
try {
|
|
59
|
+
protocol = new URL(routeContext.baseUrl).protocol;
|
|
60
|
+
} catch {
|
|
61
|
+
throw new TransportError("auth_blocked", "invalid OAuth provider destination");
|
|
62
|
+
}
|
|
63
|
+
if (protocol !== "https:") {
|
|
64
|
+
throw new TransportError("auth_blocked", "OAuth lab probes require HTTPS");
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const snapshot = await getValidAccessTokenSnapshot(routeContext.providerId);
|
|
68
|
+
headers.Authorization = `Bearer ${snapshot.accessToken}`;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (error instanceof OAuthLoginRequiredError || error instanceof UnsupportedOAuthProviderError) {
|
|
71
|
+
throw new TransportError("auth_blocked", "oauth unavailable");
|
|
72
|
+
}
|
|
73
|
+
// Non-terminal refresh failures (network, lock contention, provider transient errors)
|
|
74
|
+
// are harness/infrastructure failures rather than evidence that credentials are invalid.
|
|
75
|
+
throw new TransportError("harness_failure", "oauth refresh unavailable");
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
const apiKey = resolveEnvValue(provider.apiKey)?.trim();
|
|
79
|
+
if (!apiKey) throw new TransportError("auth_blocked", "missing api key");
|
|
80
|
+
if (provider.adapter === "anthropic" && provider.apiKeyTransport === "x-api-key") {
|
|
81
|
+
headers["x-api-key"] = apiKey;
|
|
82
|
+
} else {
|
|
83
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (provider.headers) {
|
|
88
|
+
for (const [name, value] of Object.entries(provider.headers)) {
|
|
89
|
+
if (CREDENTIAL_HEADER.test(name)) continue;
|
|
90
|
+
const resolved = resolveEnvValue(value);
|
|
91
|
+
headers[name] = typeof resolved === "string" ? resolved : value;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return headers;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Create the process-local trusted CL-03 route executor for Lab automation dispatch. */
|
|
99
|
+
export function createProductionLabRouteExecutor(
|
|
100
|
+
deps: ProductionLabRouteExecutorDeps,
|
|
101
|
+
): TrustedLabRouteExecutor {
|
|
102
|
+
return createHostIssuedLabRouteExecutor(async (input) => {
|
|
103
|
+
if (!input.initiatingRequest) {
|
|
104
|
+
throw new TransportError("harness_failure", "live scenario missing initiating request");
|
|
105
|
+
}
|
|
106
|
+
const config = deps.loadConfig();
|
|
107
|
+
const lease = createCredentialLease({
|
|
108
|
+
destination: input.destination,
|
|
109
|
+
transportId: "lab-automation",
|
|
110
|
+
budget: input.limits.maxRequests,
|
|
111
|
+
});
|
|
112
|
+
const authHeaders = await buildLabProviderAuthHeaders(input.routeContext, config);
|
|
113
|
+
const sender = createLabAuthorizedPinnedSender(async () => authHeaders);
|
|
114
|
+
const transport = createPinnedTransport({
|
|
115
|
+
destination: input.destination,
|
|
116
|
+
lease,
|
|
117
|
+
sender,
|
|
118
|
+
limits: input.limits,
|
|
119
|
+
transportId: "lab-automation",
|
|
120
|
+
});
|
|
121
|
+
const path = liveUpstreamRequestPath(input.routeContext.upstreamProtocol);
|
|
122
|
+
const response = await transport.request({
|
|
123
|
+
method: "POST",
|
|
124
|
+
path,
|
|
125
|
+
body: input.initiatingRequest,
|
|
126
|
+
signal: input.signal,
|
|
127
|
+
});
|
|
128
|
+
return normalizeLabLiveTransportObservation(input.routeContext, response);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers Compatibility Lab's passive route-subject linker into the core slot.
|
|
3
|
+
*
|
|
4
|
+
* Imported only from the Lab activation path, never from the request path. This module
|
|
5
|
+
* lives outside `src/lab/` for the same reason the other `src/lib/lab-*.ts` host
|
|
6
|
+
* integrations do: it is the seam between core and the subsystem, not the subsystem.
|
|
7
|
+
*
|
|
8
|
+
* @internal host integration only
|
|
9
|
+
*/
|
|
10
|
+
import { setPassiveRouteLinker } from "../server/passive-route-linker";
|
|
11
|
+
import { resolveProductionRouteSubject } from "../routing/compatibility/subject";
|
|
12
|
+
|
|
13
|
+
/** Install the Lab linker. Returns a detach function. */
|
|
14
|
+
export function registerLabPassiveRouteLinker(configDir?: string): () => void {
|
|
15
|
+
return setPassiveRouteLinker((config, providerName, modelId, routed, inboundWire) => {
|
|
16
|
+
const subject = resolveProductionRouteSubject(
|
|
17
|
+
config,
|
|
18
|
+
providerName,
|
|
19
|
+
modelId,
|
|
20
|
+
routed,
|
|
21
|
+
inboundWire,
|
|
22
|
+
configDir,
|
|
23
|
+
);
|
|
24
|
+
return subject ? subject.subjectId : null;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
export const LOCAL_ATTESTATION_CHALLENGE_HEADER = "x-opencodex-attestation-challenge";
|
|
4
|
+
export const LOCAL_ATTESTATION_PROOF_HEADER = "x-opencodex-attestation-proof";
|
|
5
|
+
|
|
6
|
+
const BASE64URL_256 = /^[A-Za-z0-9_-]{43}$/;
|
|
7
|
+
|
|
8
|
+
export function isLocalAttestationSecret(value: unknown): value is string {
|
|
9
|
+
return typeof value === "string" && BASE64URL_256.test(value);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function createLocalAttestationSecret(): string {
|
|
13
|
+
return randomBytes(32).toString("base64url");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function createLocalAttestationChallenge(): string {
|
|
17
|
+
return randomBytes(32).toString("base64url");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function attestationPayload(challenge: string, pid: number, port: number): string | null {
|
|
21
|
+
if (!BASE64URL_256.test(challenge)) return null;
|
|
22
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) return null;
|
|
23
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
|
|
24
|
+
return `opencodex-local-management-v1\n${challenge}\n${pid}\n${port}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function createLocalAttestationProof(
|
|
28
|
+
secret: string,
|
|
29
|
+
challenge: string,
|
|
30
|
+
pid: number,
|
|
31
|
+
port: number,
|
|
32
|
+
): string | null {
|
|
33
|
+
if (!isLocalAttestationSecret(secret)) return null;
|
|
34
|
+
const payload = attestationPayload(challenge, pid, port);
|
|
35
|
+
if (!payload) return null;
|
|
36
|
+
return createHmac("sha256", secret).update(payload).digest("base64url");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function verifyLocalAttestationProof(
|
|
40
|
+
secret: string,
|
|
41
|
+
challenge: string,
|
|
42
|
+
pid: number,
|
|
43
|
+
port: number,
|
|
44
|
+
proof: string | null,
|
|
45
|
+
): boolean {
|
|
46
|
+
const expected = createLocalAttestationProof(secret, challenge, pid, port);
|
|
47
|
+
if (!expected || !proof || !BASE64URL_256.test(proof)) return false;
|
|
48
|
+
const expectedBytes = Buffer.from(expected);
|
|
49
|
+
const actualBytes = Buffer.from(proof);
|
|
50
|
+
return expectedBytes.length === actualBytes.length && timingSafeEqual(expectedBytes, actualBytes);
|
|
51
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { isLocalAttestationSecret } from "./local-management-attestation";
|
|
3
|
+
|
|
4
|
+
export const LOCAL_MANAGEMENT_EXPECTED_PID_HEADER = "x-opencodex-local-expected-pid";
|
|
5
|
+
export const LOCAL_MANAGEMENT_NONCE_HEADER = "x-opencodex-local-nonce";
|
|
6
|
+
export const LOCAL_MANAGEMENT_CAPABILITY_EXPIRES_AT_HEADER = "x-opencodex-local-expires-at";
|
|
7
|
+
export const LOCAL_MANAGEMENT_CAPABILITY_HEADER = "x-opencodex-local-capability";
|
|
8
|
+
export const LOCAL_MANAGEMENT_CAPABILITY_TTL_MS = 10_000;
|
|
9
|
+
|
|
10
|
+
export const LOCAL_MANAGEMENT_READ_PATHS = {
|
|
11
|
+
codexAccounts: "/api/codex-auth/accounts",
|
|
12
|
+
systemMemory: "/api/system/memory",
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
export type LocalManagementReadPath =
|
|
16
|
+
typeof LOCAL_MANAGEMENT_READ_PATHS[keyof typeof LOCAL_MANAGEMENT_READ_PATHS];
|
|
17
|
+
|
|
18
|
+
const BASE64URL_256 = /^[A-Za-z0-9_-]{43}$/;
|
|
19
|
+
const LOCAL_READ_METHOD = "GET";
|
|
20
|
+
|
|
21
|
+
export type ExpectedLocalManagementPid =
|
|
22
|
+
| { kind: "absent" }
|
|
23
|
+
| { kind: "invalid" }
|
|
24
|
+
| { kind: "present"; pid: number };
|
|
25
|
+
|
|
26
|
+
export function parseExpectedLocalManagementPid(value: string | null): ExpectedLocalManagementPid {
|
|
27
|
+
if (value === null) return { kind: "absent" };
|
|
28
|
+
if (!/^[1-9]\d*$/.test(value)) return { kind: "invalid" };
|
|
29
|
+
const pid = Number(value);
|
|
30
|
+
return Number.isSafeInteger(pid) ? { kind: "present", pid } : { kind: "invalid" };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function isLocalManagementReadPath(path: string): path is LocalManagementReadPath {
|
|
34
|
+
return path === LOCAL_MANAGEMENT_READ_PATHS.codexAccounts
|
|
35
|
+
|| path === LOCAL_MANAGEMENT_READ_PATHS.systemMemory;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function localReadCapabilityPayload(
|
|
39
|
+
nonce: string,
|
|
40
|
+
method: string,
|
|
41
|
+
path: string,
|
|
42
|
+
pid: number,
|
|
43
|
+
port: number,
|
|
44
|
+
expiresAt: number,
|
|
45
|
+
): string | null {
|
|
46
|
+
if (!BASE64URL_256.test(nonce)) return null;
|
|
47
|
+
if (method !== LOCAL_READ_METHOD || !isLocalManagementReadPath(path)) return null;
|
|
48
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) return null;
|
|
49
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
|
|
50
|
+
if (!Number.isSafeInteger(expiresAt) || expiresAt <= 0) return null;
|
|
51
|
+
return `opencodex-local-management-read-v1\n${nonce}\n${method}\n${path}\n${pid}\n${port}\n${expiresAt}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Process-scoped authorization for one allowlisted local management GET. */
|
|
55
|
+
export function createLocalManagementReadCapability(
|
|
56
|
+
secret: string,
|
|
57
|
+
nonce: string,
|
|
58
|
+
method: string,
|
|
59
|
+
path: string,
|
|
60
|
+
pid: number,
|
|
61
|
+
port: number,
|
|
62
|
+
expiresAt: number,
|
|
63
|
+
): string | null {
|
|
64
|
+
if (!isLocalAttestationSecret(secret)) return null;
|
|
65
|
+
const payload = localReadCapabilityPayload(nonce, method, path, pid, port, expiresAt);
|
|
66
|
+
if (!payload) return null;
|
|
67
|
+
return createHmac("sha256", secret).update(payload).digest("base64url");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function verifyLocalManagementReadCapability(
|
|
71
|
+
secret: string,
|
|
72
|
+
nonce: string | null,
|
|
73
|
+
method: string,
|
|
74
|
+
path: string,
|
|
75
|
+
pid: number,
|
|
76
|
+
port: number,
|
|
77
|
+
expiresAt: number,
|
|
78
|
+
capability: string | null,
|
|
79
|
+
now = Date.now(),
|
|
80
|
+
): boolean {
|
|
81
|
+
if (!nonce || !capability || !BASE64URL_256.test(capability)) return false;
|
|
82
|
+
if (
|
|
83
|
+
!Number.isSafeInteger(now)
|
|
84
|
+
|| expiresAt <= now
|
|
85
|
+
|| expiresAt > now + LOCAL_MANAGEMENT_CAPABILITY_TTL_MS
|
|
86
|
+
) return false;
|
|
87
|
+
const expected = createLocalManagementReadCapability(
|
|
88
|
+
secret,
|
|
89
|
+
nonce,
|
|
90
|
+
method,
|
|
91
|
+
path,
|
|
92
|
+
pid,
|
|
93
|
+
port,
|
|
94
|
+
expiresAt,
|
|
95
|
+
);
|
|
96
|
+
if (!expected) return false;
|
|
97
|
+
const expectedBytes = Buffer.from(expected);
|
|
98
|
+
const actualBytes = Buffer.from(capability);
|
|
99
|
+
return expectedBytes.length === actualBytes.length && timingSafeEqual(expectedBytes, actualBytes);
|
|
100
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { isLocalAttestationSecret } from "./local-management-attestation";
|
|
3
|
+
|
|
4
|
+
export const LOCAL_PROVIDER_RELOAD_METHOD = "POST";
|
|
5
|
+
export const LOCAL_PROVIDER_RELOAD_PATH = "/api/providers/reload";
|
|
6
|
+
export const LOCAL_PROVIDER_RELOAD_CAPABILITY_VERSION = "v1";
|
|
7
|
+
export const LOCAL_PROVIDER_RELOAD_EXPECTED_PID_HEADER = "x-opencodex-provider-reload-expected-pid";
|
|
8
|
+
export const LOCAL_PROVIDER_RELOAD_NONCE_HEADER = "x-opencodex-provider-reload-nonce";
|
|
9
|
+
export const LOCAL_PROVIDER_RELOAD_EXPIRES_AT_HEADER = "x-opencodex-provider-reload-expires-at";
|
|
10
|
+
export const LOCAL_PROVIDER_RELOAD_NAME_HEADER = "x-opencodex-provider-reload-name";
|
|
11
|
+
export const LOCAL_PROVIDER_RELOAD_CAPABILITY_HEADER = "x-opencodex-provider-reload-capability";
|
|
12
|
+
export const LOCAL_PROVIDER_RELOAD_CAPABILITY_TTL_MS = 10_000;
|
|
13
|
+
|
|
14
|
+
const BASE64URL_256 = /^[A-Za-z0-9_-]{43}$/;
|
|
15
|
+
const PROVIDER_NAME = /^[A-Za-z0-9](?:[A-Za-z0-9._-]{0,62}[A-Za-z0-9])?$/;
|
|
16
|
+
|
|
17
|
+
export type ExpectedLocalProviderReloadPid =
|
|
18
|
+
| { kind: "absent" }
|
|
19
|
+
| { kind: "invalid" }
|
|
20
|
+
| { kind: "present"; pid: number };
|
|
21
|
+
|
|
22
|
+
export function parseExpectedLocalProviderReloadPid(value: string | null): ExpectedLocalProviderReloadPid {
|
|
23
|
+
if (value === null) return { kind: "absent" };
|
|
24
|
+
if (!/^[1-9]\d*$/.test(value)) return { kind: "invalid" };
|
|
25
|
+
const pid = Number(value);
|
|
26
|
+
return Number.isSafeInteger(pid) ? { kind: "present", pid } : { kind: "invalid" };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function isLocalProviderReloadName(value: unknown): value is string {
|
|
30
|
+
return typeof value === "string" && PROVIDER_NAME.test(value);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function capabilityPayload(
|
|
34
|
+
nonce: string,
|
|
35
|
+
method: string,
|
|
36
|
+
path: string,
|
|
37
|
+
name: string,
|
|
38
|
+
pid: number,
|
|
39
|
+
port: number,
|
|
40
|
+
expiresAt: number,
|
|
41
|
+
): string | null {
|
|
42
|
+
if (!BASE64URL_256.test(nonce)) return null;
|
|
43
|
+
if (method !== LOCAL_PROVIDER_RELOAD_METHOD || path !== LOCAL_PROVIDER_RELOAD_PATH) return null;
|
|
44
|
+
if (!isLocalProviderReloadName(name)) return null;
|
|
45
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) return null;
|
|
46
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
|
|
47
|
+
if (!Number.isSafeInteger(expiresAt) || expiresAt <= 0) return null;
|
|
48
|
+
return `opencodex-local-provider-reload-v1\n${nonce}\n${method}\n${path}\n${name}\n${pid}\n${port}\n${expiresAt}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Process-scoped authorization to reload one named provider from protected disk state. */
|
|
52
|
+
export function createLocalProviderReloadCapability(
|
|
53
|
+
secret: string,
|
|
54
|
+
nonce: string,
|
|
55
|
+
method: string,
|
|
56
|
+
path: string,
|
|
57
|
+
name: string,
|
|
58
|
+
pid: number,
|
|
59
|
+
port: number,
|
|
60
|
+
expiresAt: number,
|
|
61
|
+
): string | null {
|
|
62
|
+
if (!isLocalAttestationSecret(secret)) return null;
|
|
63
|
+
const payload = capabilityPayload(nonce, method, path, name, pid, port, expiresAt);
|
|
64
|
+
if (!payload) return null;
|
|
65
|
+
return createHmac("sha256", secret).update(payload).digest("base64url");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function verifyLocalProviderReloadCapability(
|
|
69
|
+
secret: string,
|
|
70
|
+
nonce: string | null,
|
|
71
|
+
method: string,
|
|
72
|
+
path: string,
|
|
73
|
+
name: string | null,
|
|
74
|
+
pid: number,
|
|
75
|
+
port: number,
|
|
76
|
+
expiresAt: number,
|
|
77
|
+
capability: string | null,
|
|
78
|
+
now = Date.now(),
|
|
79
|
+
): boolean {
|
|
80
|
+
if (!nonce || !name || !capability || !BASE64URL_256.test(capability)) return false;
|
|
81
|
+
if (
|
|
82
|
+
!Number.isSafeInteger(now)
|
|
83
|
+
|| expiresAt <= now
|
|
84
|
+
|| expiresAt > now + LOCAL_PROVIDER_RELOAD_CAPABILITY_TTL_MS
|
|
85
|
+
) return false;
|
|
86
|
+
const expected = createLocalProviderReloadCapability(
|
|
87
|
+
secret,
|
|
88
|
+
nonce,
|
|
89
|
+
method,
|
|
90
|
+
path,
|
|
91
|
+
name,
|
|
92
|
+
pid,
|
|
93
|
+
port,
|
|
94
|
+
expiresAt,
|
|
95
|
+
);
|
|
96
|
+
if (!expected) return false;
|
|
97
|
+
const expectedBytes = Buffer.from(expected);
|
|
98
|
+
const actualBytes = Buffer.from(capability);
|
|
99
|
+
return expectedBytes.length === actualBytes.length && timingSafeEqual(expectedBytes, actualBytes);
|
|
100
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core-owned registry for optional-subsystem shutdown work.
|
|
3
|
+
*
|
|
4
|
+
* The proxy core must not import an optional subsystem merely to be able to stop it.
|
|
5
|
+
* Compatibility Lab is the first case: `server/lifecycle.ts` imported
|
|
6
|
+
* `lab/automation/orchestrator` for two teardown calls, and that single edge closed an
|
|
7
|
+
* import cycle (`routing/compatibility/assemble` → `routing/quota` → `providers/quota` →
|
|
8
|
+
* `codex/auth-api` → `codex/native-main-admission` → `server/lifecycle` → Lab) that pulled
|
|
9
|
+
* ~69 `src/lab/` modules into the graph of every install, including installs with no
|
|
10
|
+
* routing profile at all.
|
|
11
|
+
*
|
|
12
|
+
* A subsystem registers its teardown when it activates. A process that never activates it
|
|
13
|
+
* registers nothing, so shutdown does no work and loads no module.
|
|
14
|
+
*
|
|
15
|
+
* Hooks are synchronous and best-effort by contract: `drainAndShutdown` runs under an
|
|
16
|
+
* absolute deadline, so a hook that throws must not prevent its siblings — or
|
|
17
|
+
* `server.stop` — from running.
|
|
18
|
+
*
|
|
19
|
+
* See devlog/_fin/260814_lab_core_decoupling/010_lifecycle_shutdown_registry.md
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
type ShutdownHook = () => void;
|
|
23
|
+
|
|
24
|
+
const hooks = new Map<string, ShutdownHook>();
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Register (or replace) the teardown for one optional subsystem.
|
|
28
|
+
*
|
|
29
|
+
* Keyed so repeated activation of the same subsystem cannot accumulate duplicate hooks.
|
|
30
|
+
* Returns a detach function so an owner-scoped lease can release its registration.
|
|
31
|
+
*/
|
|
32
|
+
export function registerOptionalShutdownHook(key: string, hook: ShutdownHook): () => void {
|
|
33
|
+
hooks.set(key, hook);
|
|
34
|
+
return () => {
|
|
35
|
+
// Only detach our own registration: a later activation may have replaced it.
|
|
36
|
+
if (hooks.get(key) === hook) hooks.delete(key);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Run every registered teardown. Never throws. */
|
|
41
|
+
export function runOptionalShutdownHooks(): void {
|
|
42
|
+
for (const [key, hook] of [...hooks]) {
|
|
43
|
+
try {
|
|
44
|
+
hook();
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.warn(
|
|
47
|
+
`[shutdown] optional subsystem "${key}" teardown failed:`,
|
|
48
|
+
err instanceof Error ? err.message : err,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Test-only reset so an isolated lifecycle test does not inherit registrations. */
|
|
55
|
+
export function resetOptionalShutdownHooksForTests(): void {
|
|
56
|
+
hooks.clear();
|
|
57
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { statSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
export interface PackageTreeObservation {
|
|
4
|
+
readonly device: bigint;
|
|
5
|
+
readonly inode: bigint;
|
|
6
|
+
readonly contentTimeNs: bigint;
|
|
7
|
+
readonly size: bigint;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type PackageTreeIntegrityStatus =
|
|
11
|
+
| { readonly ok: true }
|
|
12
|
+
| { readonly ok: false; readonly reason: "package_tree_replaced" | "package_tree_unreadable" };
|
|
13
|
+
|
|
14
|
+
export interface PackageTreeIntegrityGuard {
|
|
15
|
+
status(): PackageTreeIntegrityStatus;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type ObservePackageTree = () => PackageTreeObservation | null;
|
|
19
|
+
type PackageTreeRuntimeInstall = "bun" | "npm" | "source";
|
|
20
|
+
|
|
21
|
+
const packageManifestUrl = new URL("../../package.json", import.meta.url);
|
|
22
|
+
|
|
23
|
+
function observePackageManifest(): PackageTreeObservation | null {
|
|
24
|
+
try {
|
|
25
|
+
const stat = statSync(packageManifestUrl, { bigint: true });
|
|
26
|
+
return {
|
|
27
|
+
device: stat.dev,
|
|
28
|
+
inode: stat.ino,
|
|
29
|
+
// mtimeNs, NOT ctimeNs. An inode-change time moves for METADATA writes that
|
|
30
|
+
// replace nothing: chmod, chown, touch, an editor normalizing permissions, a
|
|
31
|
+
// backup tool restoring modes. Each of those left device, inode and size
|
|
32
|
+
// identical, so the comparison below called the manifest "replaced" and every
|
|
33
|
+
// /v1/* request answered 503 until the process was restarted. Measured on
|
|
34
|
+
// macOS: chmod alone moved ctimeNs and left mtimeNs untouched.
|
|
35
|
+
//
|
|
36
|
+
// mtimeNs still catches every real replacement. An in-place rewrite of the
|
|
37
|
+
// same byte length moves mtimeNs while inode and size hold; an atomic
|
|
38
|
+
// install (write-then-rename, which is what a package manager does) changes
|
|
39
|
+
// the inode as well. Both were measured before this change was made.
|
|
40
|
+
contentTimeNs: stat.mtimeNs,
|
|
41
|
+
size: stat.size,
|
|
42
|
+
};
|
|
43
|
+
} catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function sameObservation(left: PackageTreeObservation, right: PackageTreeObservation): boolean {
|
|
49
|
+
return left.device === right.device
|
|
50
|
+
&& left.inode === right.inode
|
|
51
|
+
&& left.contentTimeNs === right.contentTimeNs
|
|
52
|
+
&& left.size === right.size;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* How long an `ok` observation is reused before the manifest is stat'd again.
|
|
57
|
+
*
|
|
58
|
+
* `status()` runs on `/healthz`, `/readyz` and every `/v1/*` request, so an unthrottled guard
|
|
59
|
+
* adds a filesystem syscall to the proxy's hot path to detect an event that happens at most
|
|
60
|
+
* once per install. A replaced tree is not time-critical either: the process is already
|
|
61
|
+
* serving broken imports, and one more second of that is not worse than a syscall per turn
|
|
62
|
+
* forever.
|
|
63
|
+
*
|
|
64
|
+
* A NEGATIVE result is never cached — once the tree looks wrong, every later request re-checks,
|
|
65
|
+
* so a repaired install recovers on its own instead of staying refused for a window.
|
|
66
|
+
*/
|
|
67
|
+
const PACKAGE_TREE_RECHECK_MS = 1_000;
|
|
68
|
+
|
|
69
|
+
export function createPackageTreeIntegrityGuard(
|
|
70
|
+
observe: ObservePackageTree = observePackageManifest,
|
|
71
|
+
now: () => number = Date.now,
|
|
72
|
+
): PackageTreeIntegrityGuard {
|
|
73
|
+
const boot = observe();
|
|
74
|
+
let lastOkAt: number | null = null;
|
|
75
|
+
return {
|
|
76
|
+
status(): PackageTreeIntegrityStatus {
|
|
77
|
+
const at = now();
|
|
78
|
+
if (lastOkAt !== null && at - lastOkAt < PACKAGE_TREE_RECHECK_MS) return { ok: true };
|
|
79
|
+
const current = observe();
|
|
80
|
+
if (boot === null || current === null) return { ok: false, reason: "package_tree_unreadable" };
|
|
81
|
+
if (!sameObservation(boot, current)) return { ok: false, reason: "package_tree_replaced" };
|
|
82
|
+
lastOkAt = at;
|
|
83
|
+
return { ok: true };
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Installed packages fail closed when their manifest is replaced under a live process.
|
|
90
|
+
* A source checkout is different: editing package.json is ordinary development work, and
|
|
91
|
+
* Bun keeps serving the module snapshot already loaded by this process until the operator
|
|
92
|
+
* chooses to restart. Fencing every request there makes running dev directly impossible.
|
|
93
|
+
*/
|
|
94
|
+
export function createRuntimePackageTreeIntegrityGuard(
|
|
95
|
+
installer: PackageTreeRuntimeInstall,
|
|
96
|
+
observe: ObservePackageTree = observePackageManifest,
|
|
97
|
+
now: () => number = Date.now,
|
|
98
|
+
): PackageTreeIntegrityGuard {
|
|
99
|
+
if (installer === "source") return { status: () => ({ ok: true }) };
|
|
100
|
+
return createPackageTreeIntegrityGuard(observe, now);
|
|
101
|
+
}
|