@iislee/opencodex 2.11.0 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS_INSTALL.md +109 -0
- package/README.md +114 -19
- package/bin/ocx.mjs +164 -36
- package/bin/package-main.mjs +1 -1
- package/gui/dist/assets/index-BF38heuV.js +104 -0
- package/gui/dist/assets/index-DMiI18Kv.css +1 -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 +19 -10
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +376 -52
- package/src/adapters/base.ts +54 -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 +601 -0
- package/src/adapters/cursor/checkpoint-store.ts +303 -0
- package/src/adapters/cursor/cursor-errors.ts +129 -6
- package/src/adapters/cursor/discovery.ts +61 -4
- package/src/adapters/cursor/effort-map.ts +27 -3
- 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 +174 -58
- package/src/adapters/cursor/live-transport.ts +609 -170
- package/src/adapters/cursor/native-exec-common.ts +23 -2
- 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 +0 -1
- package/src/adapters/cursor/native-exec.ts +101 -14
- package/src/adapters/cursor/protobuf-events.ts +829 -11
- package/src/adapters/cursor/protobuf-request.ts +383 -65
- package/src/adapters/cursor/request-builder.ts +237 -31
- package/src/adapters/cursor/tool-definitions.ts +242 -12
- package/src/adapters/cursor/tool-result-normalize.ts +92 -0
- package/src/adapters/cursor/transport.ts +22 -0
- package/src/adapters/cursor/types.ts +28 -1
- package/src/adapters/cursor.ts +133 -7
- package/src/adapters/google-antigravity-replay.ts +558 -34
- package/src/adapters/google-antigravity-wire.ts +43 -10
- 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 +618 -74
- package/src/adapters/identity.ts +39 -6
- 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 +10 -1
- package/src/adapters/kiro.ts +92 -54
- package/src/adapters/mimo-free.ts +17 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1311 -336
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +830 -56
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +104 -21
- package/src/adapters/xai-web-search.ts +185 -0
- package/src/bridge.ts +428 -61
- package/src/chat/inbound.ts +43 -19
- package/src/chat/outbound.ts +82 -26
- package/src/claude/agents-inject.ts +32 -9
- package/src/claude/context-windows.ts +21 -5
- 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 +70 -16
- package/src/cli/account-api.ts +35 -1
- package/src/cli/account-auth.ts +33 -6
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +389 -2
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +30 -6
- package/src/cli/agent.ts +45 -1
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +29 -4
- package/src/cli/claude.ts +103 -34
- 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 +593 -0
- package/src/cli/doctor.ts +315 -43
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +46 -20
- package/src/cli/help.ts +20 -271
- package/src/cli/index.ts +378 -519
- package/src/cli/init.ts +4 -17
- 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 +35 -2
- package/src/cli/models.ts +100 -14
- package/src/cli/observe.ts +92 -3
- package/src/cli/opencode.ts +4 -2
- package/src/cli/provider-runtime.ts +18 -1
- package/src/cli/provider.ts +24 -3
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +437 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +6 -3
- package/src/cli/star-prompt.ts +71 -15
- package/src/cli/status.ts +10 -3
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +153 -6
- package/src/cli/v2.ts +105 -10
- package/src/cli.ts +1 -1
- package/src/clients/config-export.ts +1358 -21
- package/src/codex/account-label.ts +14 -1
- package/src/codex/account-lifecycle.ts +130 -13
- package/src/codex/account-namespaces.ts +49 -3
- package/src/codex/account-priority.ts +83 -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 +493 -106
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +849 -242
- package/src/codex/auth-collision.ts +5 -3
- package/src/codex/auth-context.ts +345 -32
- package/src/codex/autostart-health.ts +8 -1
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +68 -10
- package/src/codex/catalog/bundled.ts +331 -33
- package/src/codex/catalog/effort.ts +121 -30
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +529 -45
- package/src/codex/catalog/native-models.ts +72 -0
- package/src/codex/catalog/parsing.ts +224 -30
- package/src/codex/catalog/provider-fetch.ts +1460 -134
- package/src/codex/catalog/sync.ts +1449 -186
- 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 +384 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +651 -0
- package/src/codex/coordinator-doctor.ts +332 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/features.ts +636 -39
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +407 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-migration-guardian.ts +26 -20
- package/src/codex/history-provider.ts +231 -28
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +220 -0
- package/src/codex/inject-coordination.ts +290 -0
- package/src/codex/inject.ts +1073 -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 +80 -0
- package/src/codex/journal.ts +66 -4
- package/src/codex/log-guard/inspect.ts +506 -0
- package/src/codex/log-guard/lock.ts +150 -0
- package/src/codex/log-guard/maintenance.ts +403 -0
- package/src/codex/log-guard/path-safety.ts +88 -0
- package/src/codex/log-guard/policy.ts +44 -0
- package/src/codex/log-guard/processes.ts +205 -0
- package/src/codex/log-guard/protection.ts +489 -0
- package/src/codex/log-guard/sqlite-errors.ts +9 -0
- package/src/codex/main-account-cache.ts +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 +353 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +178 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +492 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +682 -0
- package/src/codex/paths.ts +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 +967 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +175 -13
- package/src/codex/refresh.ts +11 -2
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +505 -94
- package/src/codex/runtime.ts +159 -38
- package/src/codex/shim.ts +1009 -28
- package/src/codex/subagent-model-fallback.ts +350 -35
- package/src/codex/sync.ts +191 -2
- package/src/codex/transition-state.ts +612 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +557 -0
- package/src/codex/warmup.ts +187 -81
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +20 -0
- package/src/combos/index.ts +4 -0
- package/src/combos/request.ts +32 -0
- package/src/combos/types.ts +81 -9
- package/src/config/provider-name.ts +24 -0
- package/src/config.ts +1762 -140
- package/src/generated/compatibility-version.json +3164 -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 +152 -29
- package/src/images/plan.ts +23 -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.ts +111 -0
- package/src/integrations/registry.ts +159 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +361 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +691 -0
- package/src/lab/artifacts/sanitize.ts +586 -0
- package/src/lab/artifacts/secure-fs.ts +475 -0
- package/src/lab/artifacts/store.ts +310 -0
- package/src/lab/automation/budgets.ts +78 -0
- package/src/lab/automation/config-persistence.ts +256 -0
- package/src/lab/automation/constants.ts +39 -0
- package/src/lab/automation/cooldown.ts +103 -0
- package/src/lab/automation/dispatch.ts +211 -0
- package/src/lab/automation/index.ts +13 -0
- package/src/lab/automation/orchestrator.ts +499 -0
- package/src/lab/automation/persistence.ts +512 -0
- package/src/lab/automation/planner.ts +371 -0
- package/src/lab/automation/policy.ts +136 -0
- package/src/lab/automation/queue.ts +191 -0
- package/src/lab/automation/recovery.ts +24 -0
- package/src/lab/automation/route-context.ts +21 -0
- package/src/lab/automation/run-key.ts +44 -0
- package/src/lab/automation/runs-query.ts +34 -0
- package/src/lab/automation/types.ts +160 -0
- package/src/lab/conformance/assertion.ts +325 -0
- package/src/lab/conformance/digest.ts +22 -0
- package/src/lab/conformance/executor.ts +741 -0
- package/src/lab/conformance/fixture-provider.ts +27 -0
- package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
- package/src/lab/conformance/harness-budget.ts +47 -0
- package/src/lab/conformance/index.ts +5 -0
- package/src/lab/conformance/jcs.ts +64 -0
- package/src/lab/conformance/json-pointer.ts +39 -0
- package/src/lab/conformance/manifest.ts +180 -0
- package/src/lab/conformance/mcp-stub.ts +179 -0
- package/src/lab/conformance/negative-controls.ts +164 -0
- package/src/lab/conformance/observation.ts +355 -0
- package/src/lab/conformance/runner.ts +68 -0
- package/src/lab/conformance/sse-normalize.ts +59 -0
- package/src/lab/conformance/suite-manifest.ts +78 -0
- package/src/lab/conformance/types.ts +214 -0
- package/src/lab/constants.ts +126 -0
- package/src/lab/digest.ts +64 -0
- package/src/lab/events/errors.ts +9 -0
- package/src/lab/events/limits.ts +117 -0
- package/src/lab/events/types.ts +229 -0
- package/src/lab/events/validate.ts +781 -0
- package/src/lab/fabric/constants.ts +40 -0
- package/src/lab/fabric/executor.ts +492 -0
- package/src/lab/fabric/index.ts +80 -0
- package/src/lab/fabric/manifest.ts +222 -0
- package/src/lab/fabric/observe.ts +489 -0
- package/src/lab/fabric/patch.ts +79 -0
- package/src/lab/fabric/producer-child.ts +139 -0
- package/src/lab/fabric/producer-isolate.ts +276 -0
- package/src/lab/fabric/producer-protocol.ts +61 -0
- package/src/lab/fabric/scratch.ts +439 -0
- package/src/lab/fabric/subject.ts +106 -0
- package/src/lab/fabric/types.ts +134 -0
- package/src/lab/fabric/verifier.ts +98 -0
- package/src/lab/index.ts +54 -0
- package/src/lab/ledger/artifact-refs.ts +127 -0
- package/src/lab/ledger/invalidation.ts +136 -0
- package/src/lab/ledger/purge.ts +310 -0
- package/src/lab/ledger/store.ts +532 -0
- package/src/lab/live/credential-lease.ts +53 -0
- package/src/lab/live/destination.ts +155 -0
- package/src/lab/live/executor.ts +336 -0
- package/src/lab/live/inert-tools.ts +56 -0
- package/src/lab/live/manifest.ts +85 -0
- package/src/lab/live/mcp-loopback.ts +57 -0
- package/src/lab/live/runner.ts +19 -0
- package/src/lab/live/sandbox.ts +61 -0
- package/src/lab/live/suite-manifest.ts +41 -0
- package/src/lab/live/transport.ts +118 -0
- package/src/lab/live/types.ts +197 -0
- package/src/lab/observe/from-conformance.ts +301 -0
- package/src/lab/observe/from-live.ts +117 -0
- package/src/lab/paths.ts +153 -0
- package/src/lab/projection/rebuild.ts +495 -0
- package/src/lab/projection/schema.ts +135 -0
- package/src/lab/projection/verdicts.ts +474 -0
- package/src/lab/projection/verification.ts +412 -0
- package/src/lab/public/bundle.ts +217 -0
- package/src/lab/public/community-authority.ts +175 -0
- package/src/lab/public/community-files.ts +29 -0
- package/src/lab/public/community.ts +479 -0
- package/src/lab/public/file-safety.ts +155 -0
- package/src/lab/public/ids.ts +26 -0
- package/src/lab/public/index.ts +16 -0
- package/src/lab/public/mutation-lock.ts +424 -0
- package/src/lab/public/operator.ts +353 -0
- package/src/lab/public/origin-purge.ts +79 -0
- package/src/lab/public/origin.ts +203 -0
- package/src/lab/public/privacy.ts +143 -0
- package/src/lab/public/private-file.ts +261 -0
- package/src/lab/public/project.ts +124 -0
- package/src/lab/public/purge-test-fault.ts +21 -0
- package/src/lab/public/purge.ts +223 -0
- package/src/lab/public/registry.ts +44 -0
- package/src/lab/public/revocation.ts +252 -0
- package/src/lab/public/signature.ts +243 -0
- package/src/lab/public/storage.ts +105 -0
- package/src/lab/public/strict-json.ts +206 -0
- package/src/lab/public/time.ts +26 -0
- package/src/lab/public/types.ts +172 -0
- package/src/lab/public/validate.ts +391 -0
- package/src/lab/query/catalog.ts +101 -0
- package/src/lab/query/connection.ts +107 -0
- package/src/lab/query/constants.ts +4 -0
- package/src/lab/query/cursor.ts +132 -0
- package/src/lab/query/dto-map.ts +277 -0
- package/src/lab/query/errors.ts +22 -0
- package/src/lab/query/freshness.ts +53 -0
- package/src/lab/query/index.ts +45 -0
- package/src/lab/query/latest-observation.ts +59 -0
- package/src/lab/query/passive-production.ts +159 -0
- package/src/lab/query/queries.ts +444 -0
- package/src/lab/query/types.ts +266 -0
- package/src/lab/subject/behavior-fingerprint.ts +77 -0
- package/src/lab/subject/installation-salt.ts +112 -0
- package/src/lab/subject/protocol-subject.ts +80 -0
- package/src/lab/subject/route-subject.ts +74 -0
- package/src/lib/app-owned-memory-stores.ts +22 -0
- package/src/lib/bounded-body.ts +153 -9
- 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 +6 -2
- package/src/lib/destination-policy.ts +65 -1
- package/src/lib/errors.ts +44 -2
- 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/pinned-http.ts +145 -26
- package/src/lib/process-control.ts +4 -1
- 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/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 +202 -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 +8 -2
- package/src/oauth/chatgpt.ts +12 -1
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +46 -5
- package/src/oauth/google-antigravity.ts +35 -3
- package/src/oauth/health.ts +20 -12
- package/src/oauth/index.ts +398 -66
- package/src/oauth/key-providers.ts +16 -0
- package/src/oauth/kimi.ts +16 -2
- package/src/oauth/kiro.ts +50 -6
- package/src/oauth/local-token-detect.ts +11 -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/store.ts +119 -21
- package/src/oauth/token-guardian.ts +9 -3
- 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/base-url-choices.ts +10 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +144 -0
- package/src/providers/context-cap.ts +22 -5
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/derive.ts +253 -6
- package/src/providers/fastwire.ts +501 -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 +1 -1
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +115 -22
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -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 +29 -0
- package/src/providers/quota.ts +1319 -38
- package/src/providers/registry.ts +1429 -111
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +42 -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 +11 -4
- package/src/reasoning-effort.ts +49 -1
- package/src/responses/compaction.ts +26 -1
- package/src/responses/custom-tool-compat.ts +266 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +355 -0
- package/src/responses/parser.ts +220 -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 +426 -0
- package/src/responses/schema.ts +7 -1
- package/src/responses/spill-store.ts +75 -10
- package/src/responses/state.ts +565 -27
- package/src/responses/thought-signature-replay.ts +347 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/router.ts +366 -30
- package/src/routing/analytics.ts +378 -0
- package/src/routing/capability.ts +244 -0
- package/src/routing/compatibility/assemble.ts +73 -0
- package/src/routing/compatibility/behavior.ts +278 -0
- package/src/routing/compatibility/catalog.ts +99 -0
- package/src/routing/compatibility/endpoint.ts +52 -0
- package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
- package/src/routing/compatibility/policy.ts +181 -0
- package/src/routing/compatibility/provider-slot.ts +56 -0
- package/src/routing/compatibility/reader.ts +110 -0
- package/src/routing/compatibility/subject.ts +191 -0
- package/src/routing/compatibility/types.ts +64 -0
- package/src/routing/compatibility/version.ts +104 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +495 -0
- package/src/routing/health.ts +412 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +547 -0
- package/src/routing/quota.ts +145 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +776 -0
- package/src/server/adapter-resolve.ts +2 -29
- package/src/server/auth-cors.ts +267 -46
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +130 -56
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +426 -0
- package/src/server/claude-messages.ts +159 -43
- 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 +865 -181
- package/src/server/lifecycle.ts +284 -13
- 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 +398 -103
- package/src/server/management/api-key-usage.ts +31 -5
- package/src/server/management/body.ts +6 -0
- package/src/server/management/combo-routes.ts +62 -24
- package/src/server/management/config-routes.ts +464 -51
- package/src/server/management/context.ts +80 -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 +101 -32
- package/src/server/management/model-routes.ts +189 -131
- package/src/server/management/model-rows.ts +163 -0
- package/src/server/management/native-integration-routes.ts +769 -0
- package/src/server/management/oauth-account-routes.ts +80 -4
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +764 -157
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +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 +288 -32
- 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 +115 -14
- package/src/server/management-auth.ts +220 -5
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/ports.ts +41 -1
- package/src/server/proxy-liveness.ts +132 -5
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +82 -42
- package/src/server/relay.ts +236 -76
- package/src/server/request-decompress.ts +113 -6
- package/src/server/request-log.ts +235 -22
- package/src/server/responses/agent-task-recovery-cache.ts +143 -0
- package/src/server/responses/agent-task-recovery.ts +465 -0
- package/src/server/responses/collaboration.ts +204 -35
- package/src/server/responses/compact.ts +442 -55
- package/src/server/responses/core.ts +2872 -331
- package/src/server/responses/empty-completion-guard.ts +276 -0
- package/src/server/responses/encrypted-payload.ts +62 -39
- package/src/server/responses/fetch-helpers.ts +79 -4
- package/src/server/responses/input-admission.ts +185 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +251 -0
- package/src/server/responses/terminal-guard.ts +26 -5
- package/src/server/responses/upstream-error.ts +5 -0
- package/src/server/responses/ws-upstream.ts +308 -0
- package/src/server/responses-custom-tool-repair.ts +282 -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 +342 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +153 -0
- package/src/server/responses.ts +18 -2
- package/src/server/search.ts +78 -13
- package/src/server/sse-frame-buffer.ts +292 -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 +39 -38
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +1111 -90
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/storage/cleanup.ts +2 -2
- 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 +845 -0
- package/src/types/provider.ts +545 -0
- package/src/types/request.ts +384 -0
- package/src/types/tools.ts +131 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +104 -1236
- package/src/update/index.ts +32 -19
- package/src/update/job.ts +442 -67
- 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 +259 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/expected-prices.ts +268 -16
- package/src/usage/log.ts +606 -41
- package/src/usage/summary.ts +177 -9
- 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 +9 -3
- 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 +88 -0
- package/src/web-search/executor.ts +11 -3
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +150 -15
- package/src/web-search/loop.ts +279 -50
- 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,492 @@
|
|
|
1
|
+
import { NativeProfileManager } from "./native-profile-manager";
|
|
2
|
+
import { clearAccountNeedsReauth } from "./account-runtime-state";
|
|
3
|
+
import { MAIN_CODEX_ACCOUNT_ID } from "./main-account";
|
|
4
|
+
import {
|
|
5
|
+
probeNativeProfileRecoveryState,
|
|
6
|
+
type NativeProfileRecoveryState,
|
|
7
|
+
} from "./native-profile-store";
|
|
8
|
+
import {
|
|
9
|
+
retainNativeMainOwner,
|
|
10
|
+
withNativeMainOwnerOperation,
|
|
11
|
+
type NativeMainOwnerOptions,
|
|
12
|
+
type NativeMainOwnerReference,
|
|
13
|
+
type NativeMainOwnerSnapshot,
|
|
14
|
+
} from "./native-main-owner";
|
|
15
|
+
import { withNativeMainExclusiveClaim } from "./native-main-claim";
|
|
16
|
+
import { scrubNativeMainAuthTempResidues } from "./native-main-auth-temp";
|
|
17
|
+
import { NATIVE_STAGE_SWEEP_INTERVAL_MS } from "./native-profile-stage-store";
|
|
18
|
+
import type { NativeCodexOwnership } from "../integrations/native/ownership-preflight";
|
|
19
|
+
|
|
20
|
+
export type NativeMainStartupGateSnapshot =
|
|
21
|
+
| { status: "ready"; homeId: string | null }
|
|
22
|
+
| {
|
|
23
|
+
status: "blocked";
|
|
24
|
+
homeId: string | null;
|
|
25
|
+
reason:
|
|
26
|
+
| "foreign-ownership"
|
|
27
|
+
| "ownership-unknown"
|
|
28
|
+
| "recovery-pending"
|
|
29
|
+
| "manual-recovery"
|
|
30
|
+
| "owner-conflict"
|
|
31
|
+
| "owner-unavailable"
|
|
32
|
+
| "stage-cleanup-required";
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** The settled reason a blocked gate carries, named so consumers can hold one without the union. */
|
|
36
|
+
export type NativeMainStartupBlockReason =
|
|
37
|
+
Extract<NativeMainStartupGateSnapshot, { status: "blocked" }>["reason"];
|
|
38
|
+
|
|
39
|
+
export interface NativeMainStartupGateDeps {
|
|
40
|
+
manager?: NativeProfileManager;
|
|
41
|
+
/** Test-only barrier used to prove admission stays closed while startup recovery is pending. */
|
|
42
|
+
beforeRecovery?: () => void | Promise<void>;
|
|
43
|
+
probeRecoveryState?: typeof probeNativeProfileRecoveryState;
|
|
44
|
+
owner?: NativeMainOwnerOptions;
|
|
45
|
+
stageSweepIntervalMs?: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface NativeMainStartupLifecycle {
|
|
49
|
+
readonly homeId: string | null;
|
|
50
|
+
readonly settled: Promise<NativeMainStartupGateSnapshot>;
|
|
51
|
+
release(): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let epoch = 0;
|
|
55
|
+
let snapshot: NativeMainStartupGateSnapshot = { status: "ready", homeId: null };
|
|
56
|
+
let settled: Promise<NativeMainStartupGateSnapshot> = Promise.resolve(snapshot);
|
|
57
|
+
export type NativeMainServiceOwnershipBlockReason =
|
|
58
|
+
| "foreign-ownership"
|
|
59
|
+
| "ownership-unknown";
|
|
60
|
+
const serviceOwnershipRefs = new Map<NativeMainServiceOwnershipBlockReason, number>();
|
|
61
|
+
interface StartupEntry {
|
|
62
|
+
homeId: string;
|
|
63
|
+
refs: number;
|
|
64
|
+
epoch: number;
|
|
65
|
+
owner: NativeMainOwnerReference;
|
|
66
|
+
unsubscribe: () => void;
|
|
67
|
+
recoveryStarted: boolean;
|
|
68
|
+
settled: Promise<NativeMainStartupGateSnapshot>;
|
|
69
|
+
resolveAcquisition?: (value: NativeMainStartupGateSnapshot) => void;
|
|
70
|
+
deps: NativeMainStartupGateDeps;
|
|
71
|
+
manager: NativeProfileManager;
|
|
72
|
+
sweepTimer?: ReturnType<typeof setTimeout>;
|
|
73
|
+
sweepInFlight?: Promise<void>;
|
|
74
|
+
sweepStopping: boolean;
|
|
75
|
+
}
|
|
76
|
+
const startupEntries = new Map<string, StartupEntry>();
|
|
77
|
+
const serverLifecycles = new WeakMap<object, NativeMainStartupLifecycle>();
|
|
78
|
+
|
|
79
|
+
function ready(homeId: string | null): NativeMainStartupGateSnapshot {
|
|
80
|
+
return { status: "ready", homeId };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Arm the native-main gate synchronously, then converge the encrypted journal in the background.
|
|
85
|
+
* No credential bytes are read here: journal/auth inspection remains inside NativeProfileManager.
|
|
86
|
+
*/
|
|
87
|
+
export function initializeNativeMainStartupGate(
|
|
88
|
+
deps: NativeMainStartupGateDeps = {},
|
|
89
|
+
): Promise<NativeMainStartupGateSnapshot> {
|
|
90
|
+
const currentEpoch = ++epoch;
|
|
91
|
+
let manager: NativeProfileManager;
|
|
92
|
+
try {
|
|
93
|
+
manager = deps.manager ?? new NativeProfileManager();
|
|
94
|
+
} catch {
|
|
95
|
+
// A missing/unresolvable Codex home cannot provide a usable native-main token either.
|
|
96
|
+
// Do not turn an unused opt-in feature into a process-wide startup outage.
|
|
97
|
+
snapshot = ready(null);
|
|
98
|
+
settled = Promise.resolve(snapshot);
|
|
99
|
+
return settled;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const homeId = manager.context.homeId;
|
|
103
|
+
const probe = deps.probeRecoveryState ?? probeNativeProfileRecoveryState;
|
|
104
|
+
let recoveryState: NativeProfileRecoveryState;
|
|
105
|
+
try {
|
|
106
|
+
recoveryState = probe(manager.context);
|
|
107
|
+
} catch {
|
|
108
|
+
snapshot = { status: "blocked", homeId, reason: "manual-recovery" };
|
|
109
|
+
settled = Promise.resolve(snapshot);
|
|
110
|
+
return settled;
|
|
111
|
+
}
|
|
112
|
+
if (recoveryState === "none") {
|
|
113
|
+
snapshot = ready(homeId);
|
|
114
|
+
settled = Promise.resolve(snapshot);
|
|
115
|
+
return settled;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (recoveryState !== "journal") {
|
|
119
|
+
snapshot = { status: "blocked", homeId, reason: "manual-recovery" };
|
|
120
|
+
settled = Promise.resolve(snapshot);
|
|
121
|
+
return settled;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
snapshot = { status: "blocked", homeId, reason: "recovery-pending" };
|
|
125
|
+
settled = (async () => {
|
|
126
|
+
try {
|
|
127
|
+
await deps.beforeRecovery?.();
|
|
128
|
+
await manager.recover(false);
|
|
129
|
+
if (epoch === currentEpoch && probe(manager.context) === "none") {
|
|
130
|
+
clearAccountNeedsReauth(MAIN_CODEX_ACCOUNT_ID);
|
|
131
|
+
snapshot = ready(homeId);
|
|
132
|
+
} else if (epoch === currentEpoch) {
|
|
133
|
+
snapshot = { status: "blocked", homeId, reason: "manual-recovery" };
|
|
134
|
+
}
|
|
135
|
+
} catch {
|
|
136
|
+
if (epoch === currentEpoch) snapshot = { status: "blocked", homeId, reason: "manual-recovery" };
|
|
137
|
+
}
|
|
138
|
+
return snapshot;
|
|
139
|
+
})();
|
|
140
|
+
return settled;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function ownerBlockedReason(owner: NativeMainOwnerSnapshot): "owner-conflict" | "owner-unavailable" {
|
|
144
|
+
return owner.status === "unavailable" ? "owner-unavailable" : "owner-conflict";
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function runOwnedStageSweep(entry: StartupEntry): Promise<boolean> {
|
|
148
|
+
if (typeof (entry.manager as Partial<NativeProfileManager>).sweepStages !== "function") return true;
|
|
149
|
+
// A fresh installation has no stage registry or staging tree. Avoid creating
|
|
150
|
+
// and contending on the profile transaction database for an inert subsystem.
|
|
151
|
+
// Real managers treat every present or uncertain artifact as sweep-required;
|
|
152
|
+
// partial test/library managers without the preflight keep the old behavior.
|
|
153
|
+
if (
|
|
154
|
+
typeof (entry.manager as Partial<NativeProfileManager>).stageSweepRequired === "function"
|
|
155
|
+
&& !entry.manager.stageSweepRequired()
|
|
156
|
+
) return true;
|
|
157
|
+
try {
|
|
158
|
+
const result = await withNativeMainOwnerOperation(entry.manager.context, () => entry.manager.sweepStages());
|
|
159
|
+
return !result.plaintextMayRemain;
|
|
160
|
+
} catch {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function scheduleStageSweep(entry: StartupEntry): void {
|
|
166
|
+
if (entry.sweepStopping || entry.sweepTimer || startupEntries.get(entry.homeId) !== entry) return;
|
|
167
|
+
const intervalMs = Math.max(10, entry.deps.stageSweepIntervalMs ?? NATIVE_STAGE_SWEEP_INTERVAL_MS);
|
|
168
|
+
entry.sweepTimer = setTimeout(() => {
|
|
169
|
+
entry.sweepTimer = undefined;
|
|
170
|
+
if (entry.sweepStopping || startupEntries.get(entry.homeId) !== entry) return;
|
|
171
|
+
entry.sweepInFlight = (async () => {
|
|
172
|
+
const safe = await runOwnedStageSweep(entry);
|
|
173
|
+
if (entry.sweepStopping || startupEntries.get(entry.homeId) !== entry) return;
|
|
174
|
+
if (!safe) snapshot = { status: "blocked", homeId: entry.homeId, reason: "stage-cleanup-required" };
|
|
175
|
+
else if (snapshot.homeId === entry.homeId && snapshot.status === "blocked" && snapshot.reason === "stage-cleanup-required") {
|
|
176
|
+
snapshot = ready(entry.homeId);
|
|
177
|
+
}
|
|
178
|
+
})().finally(() => {
|
|
179
|
+
entry.sweepInFlight = undefined;
|
|
180
|
+
scheduleStageSweep(entry);
|
|
181
|
+
});
|
|
182
|
+
}, intervalMs);
|
|
183
|
+
entry.sweepTimer.unref?.();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function convergeOwnedStartup(entry: StartupEntry): void {
|
|
187
|
+
if (entry.recoveryStarted) return;
|
|
188
|
+
entry.recoveryStarted = true;
|
|
189
|
+
const currentEpoch = entry.epoch;
|
|
190
|
+
snapshot = { status: "blocked", homeId: entry.homeId, reason: "recovery-pending" };
|
|
191
|
+
const acquisitionWaiter = entry.resolveAcquisition;
|
|
192
|
+
entry.resolveAcquisition = undefined;
|
|
193
|
+
entry.settled = settled = (async () => {
|
|
194
|
+
const probe = entry.deps.probeRecoveryState ?? probeNativeProfileRecoveryState;
|
|
195
|
+
try {
|
|
196
|
+
const recoveryState = await withNativeMainOwnerOperation(entry.manager.context, () => withNativeMainExclusiveClaim(
|
|
197
|
+
entry.manager.context,
|
|
198
|
+
async () => {
|
|
199
|
+
scrubNativeMainAuthTempResidues(entry.manager.context);
|
|
200
|
+
let state = probe(entry.manager.context);
|
|
201
|
+
if (state === "journal") {
|
|
202
|
+
await entry.deps.beforeRecovery?.();
|
|
203
|
+
await entry.manager.recover(false);
|
|
204
|
+
state = probe(entry.manager.context);
|
|
205
|
+
}
|
|
206
|
+
return state;
|
|
207
|
+
},
|
|
208
|
+
{ waitMs: 10_000 },
|
|
209
|
+
));
|
|
210
|
+
const stageSweepSafe = recoveryState === "none" ? await runOwnedStageSweep(entry) : false;
|
|
211
|
+
if (startupEntries.get(entry.homeId) === entry && entry.epoch === currentEpoch && recoveryState === "none" && stageSweepSafe) {
|
|
212
|
+
clearAccountNeedsReauth(MAIN_CODEX_ACCOUNT_ID);
|
|
213
|
+
snapshot = ready(entry.homeId);
|
|
214
|
+
} else if (startupEntries.get(entry.homeId) === entry && entry.epoch === currentEpoch && recoveryState === "none") {
|
|
215
|
+
snapshot = { status: "blocked", homeId: entry.homeId, reason: "stage-cleanup-required" };
|
|
216
|
+
} else if (startupEntries.get(entry.homeId) === entry && entry.epoch === currentEpoch) {
|
|
217
|
+
snapshot = { status: "blocked", homeId: entry.homeId, reason: "manual-recovery" };
|
|
218
|
+
}
|
|
219
|
+
} catch {
|
|
220
|
+
if (startupEntries.get(entry.homeId) === entry && entry.epoch === currentEpoch) {
|
|
221
|
+
snapshot = { status: "blocked", homeId: entry.homeId, reason: "manual-recovery" };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (startupEntries.get(entry.homeId) === entry && entry.epoch === currentEpoch) scheduleStageSweep(entry);
|
|
225
|
+
return snapshot;
|
|
226
|
+
})();
|
|
227
|
+
if (acquisitionWaiter) void entry.settled.then(acquisitionWaiter);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function observeOwner(entry: StartupEntry, owner: NativeMainOwnerSnapshot): void {
|
|
231
|
+
if (startupEntries.get(entry.homeId) !== entry) return;
|
|
232
|
+
if (owner.status === "acquiring") {
|
|
233
|
+
snapshot = { status: "blocked", homeId: entry.homeId, reason: "recovery-pending" };
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (owner.status === "held") {
|
|
237
|
+
convergeOwnedStartup(entry);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (owner.status === "closing" || owner.status === "released") return;
|
|
241
|
+
snapshot = { status: "blocked", homeId: entry.homeId, reason: ownerBlockedReason(owner) };
|
|
242
|
+
entry.settled = settled = Promise.resolve(snapshot);
|
|
243
|
+
entry.resolveAcquisition?.(snapshot);
|
|
244
|
+
entry.resolveAcquisition = undefined;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Retain process ownership for one live server. The first reference acquires the
|
|
249
|
+
* canonical-home SQLite lease and owns recovery; later same-process references share it.
|
|
250
|
+
*/
|
|
251
|
+
export function startNativeMainStartupLifecycle(
|
|
252
|
+
deps: NativeMainStartupGateDeps = {},
|
|
253
|
+
): NativeMainStartupLifecycle {
|
|
254
|
+
let manager: NativeProfileManager;
|
|
255
|
+
try {
|
|
256
|
+
manager = deps.manager ?? new NativeProfileManager();
|
|
257
|
+
} catch {
|
|
258
|
+
snapshot = ready(null);
|
|
259
|
+
settled = Promise.resolve(snapshot);
|
|
260
|
+
return { homeId: null, settled, release: async () => {} };
|
|
261
|
+
}
|
|
262
|
+
const homeId = manager.context.homeId;
|
|
263
|
+
let entry = startupEntries.get(homeId);
|
|
264
|
+
if (!entry) {
|
|
265
|
+
const owner = retainNativeMainOwner(manager.context, deps.owner);
|
|
266
|
+
snapshot = { status: "blocked", homeId, reason: "recovery-pending" };
|
|
267
|
+
let resolveAcquisition!: (value: NativeMainStartupGateSnapshot) => void;
|
|
268
|
+
const acquisition = new Promise<NativeMainStartupGateSnapshot>(resolve => { resolveAcquisition = resolve; });
|
|
269
|
+
settled = acquisition;
|
|
270
|
+
entry = {
|
|
271
|
+
homeId,
|
|
272
|
+
refs: 0,
|
|
273
|
+
epoch: ++epoch,
|
|
274
|
+
owner,
|
|
275
|
+
unsubscribe: () => {},
|
|
276
|
+
recoveryStarted: false,
|
|
277
|
+
settled: acquisition,
|
|
278
|
+
resolveAcquisition,
|
|
279
|
+
deps,
|
|
280
|
+
manager,
|
|
281
|
+
sweepStopping: false,
|
|
282
|
+
};
|
|
283
|
+
startupEntries.set(homeId, entry);
|
|
284
|
+
entry.unsubscribe = owner.subscribe(ownerState => observeOwner(entry!, ownerState));
|
|
285
|
+
}
|
|
286
|
+
entry.refs += 1;
|
|
287
|
+
let released = false;
|
|
288
|
+
return {
|
|
289
|
+
homeId,
|
|
290
|
+
get settled() { return entry!.settled; },
|
|
291
|
+
async release() {
|
|
292
|
+
if (released) return;
|
|
293
|
+
released = true;
|
|
294
|
+
entry!.refs = Math.max(0, entry!.refs - 1);
|
|
295
|
+
if (entry!.refs !== 0) return;
|
|
296
|
+
entry!.epoch += 1;
|
|
297
|
+
entry!.sweepStopping = true;
|
|
298
|
+
if (entry!.sweepTimer) clearTimeout(entry!.sweepTimer);
|
|
299
|
+
entry!.sweepTimer = undefined;
|
|
300
|
+
entry!.unsubscribe();
|
|
301
|
+
startupEntries.delete(homeId);
|
|
302
|
+
entry!.resolveAcquisition?.(snapshot);
|
|
303
|
+
entry!.resolveAcquisition = undefined;
|
|
304
|
+
// Startup convergence can transition from the exclusive recovery claim
|
|
305
|
+
// into a stage sweep. Keep the owner registered until that entire chain
|
|
306
|
+
// settles so no cleanup transaction starts untracked after owner detach.
|
|
307
|
+
await Promise.allSettled([entry!.settled]);
|
|
308
|
+
if (entry!.sweepInFlight) await Promise.allSettled([entry!.sweepInFlight]);
|
|
309
|
+
await entry!.owner.release();
|
|
310
|
+
},
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* How many times a service-ownership fence will re-ask before it stops asking (#2108).
|
|
316
|
+
*
|
|
317
|
+
* A host that is permanently unaskable must not re-probe on every request forever, and a
|
|
318
|
+
* host that recovers usually does so within the first few. The budget belongs to the
|
|
319
|
+
* REASON, not to an individual fence: raising a second fence deliberately does not hand
|
|
320
|
+
* out a fresh allowance, or a caller looping over fences could spin the probe forever.
|
|
321
|
+
* It is dropped when the last fence for that reason releases.
|
|
322
|
+
*/
|
|
323
|
+
export const NATIVE_MAIN_OWNERSHIP_RETRY_LIMIT = 5;
|
|
324
|
+
|
|
325
|
+
/** Reprobe hooks for the fences currently held, keyed by the reason they were raised for. */
|
|
326
|
+
const serviceOwnershipReprobes = new Map<NativeMainServiceOwnershipBlockReason, ServiceOwnershipReprobe>();
|
|
327
|
+
|
|
328
|
+
interface ServiceOwnershipReprobe {
|
|
329
|
+
readonly probe: () => NativeCodexOwnership;
|
|
330
|
+
attempts: number;
|
|
331
|
+
/** The fence that installed this hook; only its own release may drop the entry. */
|
|
332
|
+
readonly owner: NativeMainStartupLifecycle;
|
|
333
|
+
/** Releases the fence that installed this hook, exactly once. */
|
|
334
|
+
readonly spend: () => void;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** Test-only: the retry budget is module state and would otherwise leak across tests. */
|
|
338
|
+
export function __resetNativeMainOwnershipRetries(): void {
|
|
339
|
+
for (const entry of serviceOwnershipReprobes.values()) entry.attempts = 0;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Re-ask whether this host is still unownable, and drop the fence if it is not.
|
|
344
|
+
*
|
|
345
|
+
* `startServer` takes the ownership verdict once, at boot, and holds it for the process
|
|
346
|
+
* lifetime. For `foreign-ownership` that is correct — a foreign owner is a fact, and
|
|
347
|
+
* re-asking would only hand a determined caller a second chance. For `ownership-unknown`
|
|
348
|
+
* it is wrong: that verdict means the probe could not answer, so waiting cannot help,
|
|
349
|
+
* which is precisely why the #2108 reporter had to run `ocx restart` after every reboot.
|
|
350
|
+
*
|
|
351
|
+
* The re-probe is demand-driven rather than timed: it runs when something asks whether
|
|
352
|
+
* native-main is fenced, which is usually a request but is also the background token
|
|
353
|
+
* guardian's warmup. It is capped so a permanently unaskable host cannot spin.
|
|
354
|
+
*
|
|
355
|
+
* The probe is synchronous `spawnSync` with a bounded timeout, and this function is on a
|
|
356
|
+
* request path, so the cap is what keeps a wedged host from paying that cost repeatedly.
|
|
357
|
+
*/
|
|
358
|
+
function reprobeServiceOwnership(reason: NativeMainServiceOwnershipBlockReason): boolean {
|
|
359
|
+
if (reason !== "ownership-unknown") return false;
|
|
360
|
+
const entry = serviceOwnershipReprobes.get(reason);
|
|
361
|
+
if (!entry) return false;
|
|
362
|
+
if (entry.attempts >= NATIVE_MAIN_OWNERSHIP_RETRY_LIMIT) return false;
|
|
363
|
+
entry.attempts += 1;
|
|
364
|
+
let answer: NativeCodexOwnership;
|
|
365
|
+
try {
|
|
366
|
+
answer = entry.probe();
|
|
367
|
+
} catch {
|
|
368
|
+
// An inspection that throws is not evidence the host became ownable.
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
if (answer !== "owned") return false;
|
|
372
|
+
// Release through the fence that installed this hook, and only that one.
|
|
373
|
+
//
|
|
374
|
+
// Several servers can hold a fence for the same reason while only one carries a hook, so
|
|
375
|
+
// clearing the shared refcount here would unblock fences this probe never spoke for.
|
|
376
|
+
// Decrementing here directly is just as wrong the other way: that fence's own release()
|
|
377
|
+
// would then pay a second time for one fence, leaving the count short. Delegating to the
|
|
378
|
+
// fence's idempotent release keeps exactly one payment per fence.
|
|
379
|
+
entry.spend();
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function activeServiceOwnershipBlockReason(): NativeMainServiceOwnershipBlockReason | null {
|
|
384
|
+
if ((serviceOwnershipRefs.get("foreign-ownership") ?? 0) > 0) return "foreign-ownership";
|
|
385
|
+
if ((serviceOwnershipRefs.get("ownership-unknown") ?? 0) > 0) return "ownership-unknown";
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function serviceOwnershipSnapshot(
|
|
390
|
+
reason: NativeMainServiceOwnershipBlockReason,
|
|
391
|
+
): NativeMainStartupGateSnapshot {
|
|
392
|
+
return { status: "blocked", homeId: null, reason };
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** Close native-main admission without resolving or creating any CODEX_HOME artifacts. */
|
|
396
|
+
export function blockNativeMainStartupForUnownedServiceHome(
|
|
397
|
+
reason: NativeMainServiceOwnershipBlockReason,
|
|
398
|
+
options?: { reprobe?: () => NativeCodexOwnership },
|
|
399
|
+
): NativeMainStartupLifecycle {
|
|
400
|
+
serviceOwnershipRefs.set(reason, (serviceOwnershipRefs.get(reason) ?? 0) + 1);
|
|
401
|
+
let released = false;
|
|
402
|
+
const lifecycle: NativeMainStartupLifecycle = {
|
|
403
|
+
homeId: null,
|
|
404
|
+
settled: Promise.resolve(serviceOwnershipSnapshot(reason)),
|
|
405
|
+
async release() {
|
|
406
|
+
if (released) return;
|
|
407
|
+
released = true;
|
|
408
|
+
const remaining = Math.max(0, (serviceOwnershipRefs.get(reason) ?? 0) - 1);
|
|
409
|
+
if (remaining === 0) serviceOwnershipRefs.delete(reason);
|
|
410
|
+
else serviceOwnershipRefs.set(reason, remaining);
|
|
411
|
+
if (serviceOwnershipReprobes.get(reason)?.owner === lifecycle) {
|
|
412
|
+
serviceOwnershipReprobes.delete(reason);
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
};
|
|
416
|
+
// Do NOT reset an existing budget: keying the reprobe by reason means a caller raising
|
|
417
|
+
// fences in a loop would otherwise be handed a fresh allowance each time and could spin
|
|
418
|
+
// the probe forever. But once the holder is gone its entry is removed above, so a LATER
|
|
419
|
+
// fence installs its own hook — a server started after an earlier probe must not be left
|
|
420
|
+
// needing `ocx restart`, which is the very symptom this exists to remove.
|
|
421
|
+
if (options?.reprobe && reason === "ownership-unknown" && !serviceOwnershipReprobes.has(reason)) {
|
|
422
|
+
serviceOwnershipReprobes.set(reason, {
|
|
423
|
+
probe: options.reprobe,
|
|
424
|
+
attempts: 0,
|
|
425
|
+
owner: lifecycle,
|
|
426
|
+
spend: () => { void lifecycle.release(); },
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
return lifecycle;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
export function bindNativeMainStartupLifecycle(server: object, lifecycle: NativeMainStartupLifecycle): void {
|
|
433
|
+
serverLifecycles.set(server, lifecycle);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export async function releaseNativeMainStartupLifecycle(server: object): Promise<void> {
|
|
437
|
+
const lifecycle = serverLifecycles.get(server);
|
|
438
|
+
if (!lifecycle) return;
|
|
439
|
+
serverLifecycles.delete(server);
|
|
440
|
+
await lifecycle.release();
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export function isNativeMainTrafficBlocked(): boolean {
|
|
444
|
+
const reason = activeServiceOwnershipBlockReason();
|
|
445
|
+
if (reason !== null && reprobeServiceOwnership(reason)) {
|
|
446
|
+
// The host became ownable after boot (#2108): the fence lifts here rather than
|
|
447
|
+
// waiting for the restart the reporter had to perform by hand.
|
|
448
|
+
return activeServiceOwnershipBlockReason() !== null || snapshot.status === "blocked";
|
|
449
|
+
}
|
|
450
|
+
return reason !== null || snapshot.status === "blocked";
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Close the process-wide native-main admission gate after a live transaction
|
|
455
|
+
* leaves recovery state behind. A known different home owns a different
|
|
456
|
+
* native credential file, so it must not be fenced by this transition.
|
|
457
|
+
*/
|
|
458
|
+
export function blockNativeMainRecovery(
|
|
459
|
+
homeId: string,
|
|
460
|
+
recoveryState?: Exclude<NativeProfileRecoveryState, "none">,
|
|
461
|
+
): boolean {
|
|
462
|
+
if (snapshot.homeId !== null && snapshot.homeId !== homeId) return false;
|
|
463
|
+
epoch += 1;
|
|
464
|
+
snapshot = {
|
|
465
|
+
status: "blocked",
|
|
466
|
+
homeId,
|
|
467
|
+
reason: recoveryState === "journal" ? "recovery-pending" : "manual-recovery",
|
|
468
|
+
};
|
|
469
|
+
settled = Promise.resolve(snapshot);
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export function completeNativeMainRecovery(homeId: string): boolean {
|
|
474
|
+
if (snapshot.status !== "blocked" || snapshot.homeId !== homeId) return false;
|
|
475
|
+
epoch += 1;
|
|
476
|
+
clearAccountNeedsReauth(MAIN_CODEX_ACCOUNT_ID);
|
|
477
|
+
snapshot = ready(homeId);
|
|
478
|
+
settled = Promise.resolve(snapshot);
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export function nativeMainStartupGateSnapshot(): NativeMainStartupGateSnapshot {
|
|
483
|
+
const reason = activeServiceOwnershipBlockReason();
|
|
484
|
+
if (reason) return serviceOwnershipSnapshot(reason);
|
|
485
|
+
return { ...snapshot };
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export function waitForNativeMainStartupGate(): Promise<NativeMainStartupGateSnapshot> {
|
|
489
|
+
const reason = activeServiceOwnershipBlockReason();
|
|
490
|
+
if (reason) return Promise.resolve(serviceOwnershipSnapshot(reason));
|
|
491
|
+
return settled;
|
|
492
|
+
}
|