@yansigit/opencodex 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS_INSTALL.md +109 -0
- package/LICENSE +21 -0
- package/README.md +303 -0
- package/assets/architecture.png +0 -0
- package/assets/banner.png +0 -0
- package/assets/claude-code-models.gif +0 -0
- package/assets/codex-app-picker.png +0 -0
- package/bin/ocx.mjs +587 -0
- package/bin/package-main.mjs +9 -0
- package/gui/dist/assets/index-BNJ7r4Gd.js +102 -0
- package/gui/dist/assets/index-CGoDO3uO.css +1 -0
- package/gui/dist/favicon.png +0 -0
- package/gui/dist/icons.svg +24 -0
- package/gui/dist/index.html +25 -0
- package/gui/dist/logo.png +0 -0
- package/gui/dist/provider-icons/alibaba-color.svg +1 -0
- package/gui/dist/provider-icons/antigravity-color.svg +1 -0
- package/gui/dist/provider-icons/claude-color.svg +1 -0
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -0
- package/gui/dist/provider-icons/cursor-color.svg +2 -0
- package/gui/dist/provider-icons/deepseek-color.svg +1 -0
- package/gui/dist/provider-icons/discord.svg +1 -0
- package/gui/dist/provider-icons/firepass-color.svg +1 -0
- package/gui/dist/provider-icons/fireworks-color.svg +1 -0
- package/gui/dist/provider-icons/gemini-color.svg +1 -0
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
- package/gui/dist/provider-icons/grok.svg +1 -0
- package/gui/dist/provider-icons/groq-color.svg +1 -0
- package/gui/dist/provider-icons/huggingface-color.svg +1 -0
- package/gui/dist/provider-icons/kimi-color.svg +1 -0
- package/gui/dist/provider-icons/kiro-color.svg +15 -0
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
- package/gui/dist/provider-icons/mistral-color.svg +1 -0
- package/gui/dist/provider-icons/moonshot-color.svg +1 -0
- package/gui/dist/provider-icons/nvidia-color.svg +1 -0
- package/gui/dist/provider-icons/ollama-color.svg +1 -0
- package/gui/dist/provider-icons/openai.svg +1 -0
- package/gui/dist/provider-icons/opencode.svg +2 -0
- package/gui/dist/provider-icons/openrouter-color.svg +1 -0
- package/gui/dist/provider-icons/pi.svg +21 -0
- package/gui/dist/provider-icons/qianfan-color.svg +1 -0
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
- package/gui/dist/provider-icons/telegram.svg +1 -0
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/vllm-color.svg +1 -0
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
- package/package.json +108 -0
- package/src/AGENTS.md +28 -0
- package/src/adapters/anthropic-image-guard.ts +251 -0
- package/src/adapters/anthropic-image-normalize.ts +518 -0
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +1327 -0
- package/src/adapters/azure.ts +36 -0
- package/src/adapters/base.ts +121 -0
- package/src/adapters/client-fingerprint.ts +65 -0
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +601 -0
- package/src/adapters/cursor/arg-codec.ts +38 -0
- package/src/adapters/cursor/arg-normalize.ts +104 -0
- package/src/adapters/cursor/checkpoint-store.ts +303 -0
- package/src/adapters/cursor/cursor-errors.ts +288 -0
- package/src/adapters/cursor/discovery.ts +333 -0
- package/src/adapters/cursor/effort-map.ts +151 -0
- package/src/adapters/cursor/exec-policy.ts +88 -0
- package/src/adapters/cursor/framing.ts +250 -0
- package/src/adapters/cursor/gen/agent_pb.ts +15274 -0
- package/src/adapters/cursor/h2-pool.ts +123 -0
- package/src/adapters/cursor/http1-bidi.ts +361 -0
- package/src/adapters/cursor/images.ts +704 -0
- package/src/adapters/cursor/kv-store.ts +52 -0
- package/src/adapters/cursor/live-models.ts +269 -0
- package/src/adapters/cursor/live-smoke-gate.ts +41 -0
- package/src/adapters/cursor/live-transport.ts +1653 -0
- package/src/adapters/cursor/mcp-config.ts +42 -0
- package/src/adapters/cursor/mcp-manager.ts +333 -0
- package/src/adapters/cursor/message-mapper.ts +49 -0
- package/src/adapters/cursor/native-exec-common.ts +76 -0
- package/src/adapters/cursor/native-exec-desktop.ts +184 -0
- package/src/adapters/cursor/native-exec-fs.ts +332 -0
- package/src/adapters/cursor/native-exec-mcp.ts +153 -0
- package/src/adapters/cursor/native-exec-network.ts +43 -0
- package/src/adapters/cursor/native-exec-shell.ts +547 -0
- package/src/adapters/cursor/native-exec-tools.ts +118 -0
- package/src/adapters/cursor/native-exec.ts +663 -0
- package/src/adapters/cursor/protobuf-events.ts +1381 -0
- package/src/adapters/cursor/protobuf-request.ts +1032 -0
- package/src/adapters/cursor/request-builder.ts +461 -0
- package/src/adapters/cursor/thread-continuity.ts +67 -0
- package/src/adapters/cursor/tool-definitions.ts +735 -0
- package/src/adapters/cursor/tool-result-normalize.ts +92 -0
- package/src/adapters/cursor/transport-retry.ts +132 -0
- package/src/adapters/cursor/transport.ts +79 -0
- package/src/adapters/cursor/types.ts +79 -0
- package/src/adapters/cursor.ts +322 -0
- package/src/adapters/google-antigravity-hosts.ts +48 -0
- package/src/adapters/google-antigravity-replay.ts +827 -0
- package/src/adapters/google-antigravity-tools.ts +105 -0
- package/src/adapters/google-antigravity-wire.ts +141 -0
- package/src/adapters/google-errors.ts +92 -0
- package/src/adapters/google-http.ts +460 -0
- package/src/adapters/google-tool-schema.ts +238 -0
- package/src/adapters/google-truncation.ts +24 -0
- package/src/adapters/google-wire-compiler.ts +232 -0
- package/src/adapters/google.ts +1377 -0
- package/src/adapters/identity.ts +77 -0
- package/src/adapters/image.ts +23 -0
- package/src/adapters/kiro-constants.ts +16 -0
- package/src/adapters/kiro-errors.ts +208 -0
- package/src/adapters/kiro-events.ts +197 -0
- package/src/adapters/kiro-images.ts +129 -0
- package/src/adapters/kiro-retry.ts +312 -0
- package/src/adapters/kiro-thinking.ts +112 -0
- package/src/adapters/kiro-tool-fallback.ts +36 -0
- package/src/adapters/kiro-tools.ts +224 -0
- package/src/adapters/kiro-truncation.ts +33 -0
- package/src/adapters/kiro-wire.ts +129 -0
- package/src/adapters/kiro.ts +1936 -0
- package/src/adapters/mimo-free.ts +280 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1980 -0
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +1911 -0
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/run-turn-queue.ts +114 -0
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +154 -0
- package/src/adapters/upstream-http-error.ts +48 -0
- package/src/adapters/xai-web-search.ts +185 -0
- package/src/bridge.ts +1986 -0
- package/src/chat/inbound.ts +319 -0
- package/src/chat/outbound.ts +821 -0
- package/src/claude/agents-inject.ts +266 -0
- package/src/claude/alias.ts +149 -0
- package/src/claude/auth-detect.ts +229 -0
- package/src/claude/auth-mode-migration.ts +32 -0
- package/src/claude/auth-mode.ts +62 -0
- package/src/claude/context-windows.ts +205 -0
- package/src/claude/desktop-3p-guard.ts +35 -0
- package/src/claude/desktop-3p-paths.ts +84 -0
- package/src/claude/desktop-3p.ts +615 -0
- package/src/claude/desktop-health.ts +26 -0
- package/src/claude/desktop-profile.ts +263 -0
- package/src/claude/gateway-cache.ts +107 -0
- package/src/claude/inbound-debug.ts +163 -0
- package/src/claude/inbound.ts +578 -0
- package/src/claude/model-info.ts +174 -0
- package/src/claude/outbound.ts +926 -0
- package/src/cli/access.ts +108 -0
- package/src/cli/account-api.ts +302 -0
- package/src/cli/account-auth.ts +250 -0
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +737 -0
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +299 -0
- package/src/cli/agent-driven.ts +70 -0
- package/src/cli/agent.ts +290 -0
- package/src/cli/catalog-prewarm.ts +27 -0
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +213 -0
- package/src/cli/claude.ts +355 -0
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +47 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +127 -0
- package/src/cli/config-command.ts +209 -0
- package/src/cli/debug.ts +228 -0
- package/src/cli/dispatch.ts +585 -0
- package/src/cli/doctor.ts +1202 -0
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +213 -0
- package/src/cli/help.ts +101 -0
- package/src/cli/index.ts +973 -0
- package/src/cli/init.ts +211 -0
- package/src/cli/integrations.ts +260 -0
- package/src/cli/interactive-confirm.ts +133 -0
- package/src/cli/lab.ts +607 -0
- package/src/cli/launcher-context.ts +77 -0
- package/src/cli/minimax.ts +497 -0
- package/src/cli/models-runtime.ts +245 -0
- package/src/cli/models.ts +422 -0
- package/src/cli/observe.ts +206 -0
- package/src/cli/opencode.ts +588 -0
- package/src/cli/provider-replit.ts +232 -0
- package/src/cli/provider-runtime.ts +179 -0
- package/src/cli/provider.ts +492 -0
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +422 -0
- package/src/cli/replit-gateway-key-input.ts +138 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +328 -0
- package/src/cli/star-prompt.ts +211 -0
- package/src/cli/status-oauth.ts +78 -0
- package/src/cli/status.ts +328 -0
- package/src/cli/system-command.ts +112 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +199 -0
- package/src/cli/v2.ts +268 -0
- package/src/cli.ts +10 -0
- package/src/clients/config-export.ts +1704 -0
- package/src/codex/account-id.ts +34 -0
- package/src/codex/account-label.ts +47 -0
- package/src/codex/account-lifecycle.ts +172 -0
- package/src/codex/account-namespace-match.ts +63 -0
- package/src/codex/account-namespaces.ts +195 -0
- package/src/codex/account-pause.ts +20 -0
- package/src/codex/account-priority.ts +83 -0
- package/src/codex/account-runtime-state.ts +31 -0
- package/src/codex/account-store.ts +544 -0
- package/src/codex/account-usability.ts +43 -0
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/agent-roles-sync.ts +225 -0
- package/src/codex/agent-roles.ts +238 -0
- package/src/codex/app-server-processes.ts +1143 -0
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +2147 -0
- package/src/codex/auth-collision.ts +109 -0
- package/src/codex/auth-context.ts +665 -0
- package/src/codex/autostart-health.ts +156 -0
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +436 -0
- package/src/codex/catalog/bundled.ts +549 -0
- package/src/codex/catalog/effort.ts +446 -0
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +664 -0
- package/src/codex/catalog/native-models.ts +72 -0
- package/src/codex/catalog/parsing.ts +650 -0
- package/src/codex/catalog/provider-fetch.ts +2064 -0
- package/src/codex/catalog/sync.ts +1883 -0
- package/src/codex/catalog-admission.ts +199 -0
- package/src/codex/catalog-refresh-status.ts +105 -0
- package/src/codex/catalog-write-serialization.ts +242 -0
- package/src/codex/catalog.ts +14 -0
- package/src/codex/codex-write-lock.ts +384 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +651 -0
- package/src/codex/coordinator-doctor.ts +332 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/data/upstream-models.json +830 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/exec-invocation.ts +22 -0
- package/src/codex/features.ts +1566 -0
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +407 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-migration-guardian.ts +108 -0
- package/src/codex/history-provider.ts +979 -0
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +220 -0
- package/src/codex/home.ts +206 -0
- package/src/codex/inject-coordination.ts +290 -0
- package/src/codex/inject.ts +1733 -0
- package/src/codex/injected-marker.ts +106 -0
- package/src/codex/integration-record.ts +266 -0
- package/src/codex/internal/catalog-writer.ts +203 -0
- package/src/codex/internal/history-writer.ts +80 -0
- package/src/codex/journal.ts +225 -0
- package/src/codex/log-guard/inspect.ts +506 -0
- package/src/codex/log-guard/lock.ts +150 -0
- package/src/codex/log-guard/maintenance.ts +403 -0
- package/src/codex/log-guard/path-safety.ts +88 -0
- package/src/codex/log-guard/policy.ts +44 -0
- package/src/codex/log-guard/processes.ts +205 -0
- package/src/codex/log-guard/protection.ts +489 -0
- package/src/codex/log-guard/sqlite-errors.ts +9 -0
- package/src/codex/main-account-cache.ts +56 -0
- package/src/codex/main-account.ts +68 -0
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +273 -0
- package/src/codex/model-entitlements.ts +353 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +178 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +492 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +682 -0
- package/src/codex/paths.ts +144 -0
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +242 -0
- package/src/codex/pool-rotation.ts +295 -0
- package/src/codex/project-config-warnings.ts +425 -0
- package/src/codex/prompt-journal.ts +352 -0
- package/src/codex/prompt-layers.ts +967 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +573 -0
- package/src/codex/refresh.ts +62 -0
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +1888 -0
- package/src/codex/runtime.ts +659 -0
- package/src/codex/shim.ts +2170 -0
- package/src/codex/subagent-defaults.ts +550 -0
- package/src/codex/subagent-model-fallback.ts +784 -0
- package/src/codex/sync.ts +319 -0
- package/src/codex/transition-state.ts +612 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +557 -0
- package/src/codex/warmup.ts +298 -0
- package/src/codex/websocket-registry.ts +100 -0
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +160 -0
- package/src/combos/index.ts +45 -0
- package/src/combos/request.ts +94 -0
- package/src/combos/resolve.ts +232 -0
- package/src/combos/types.ts +398 -0
- package/src/config/provider-name.ts +24 -0
- package/src/config.ts +4041 -0
- package/src/fork/register.ts +3 -0
- package/src/generated/compatibility-version.json +3116 -0
- package/src/generated/model-metadata.ts +106 -0
- package/src/github/star-state.ts +203 -0
- package/src/grok/inject.ts +530 -0
- package/src/grok/inspect.ts +45 -0
- package/src/grok/status.ts +121 -0
- package/src/grok/sync.ts +66 -0
- package/src/images/artifacts.ts +516 -0
- package/src/images/fulfill-video.ts +163 -0
- package/src/images/fulfill.ts +149 -0
- package/src/images/index.ts +4 -0
- package/src/images/loop.ts +955 -0
- package/src/images/plan.ts +143 -0
- package/src/images/synthetic-tool.ts +133 -0
- package/src/images/types.ts +41 -0
- package/src/images/xai-client.ts +141 -0
- package/src/images/xai-video-client.ts +163 -0
- package/src/index.ts +22 -0
- package/src/integrations/config-io.ts +269 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/mutation-flight.ts +71 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/omp-yaml-source.ts +358 -0
- package/src/integrations/owned-refresh.ts +74 -0
- package/src/integrations/ownership.ts +111 -0
- package/src/integrations/registry.ts +159 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +361 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +691 -0
- package/src/lab/artifacts/sanitize.ts +586 -0
- package/src/lab/artifacts/secure-fs.ts +475 -0
- package/src/lab/artifacts/store.ts +310 -0
- package/src/lab/automation/budgets.ts +78 -0
- package/src/lab/automation/config-persistence.ts +256 -0
- package/src/lab/automation/constants.ts +39 -0
- package/src/lab/automation/cooldown.ts +103 -0
- package/src/lab/automation/dispatch.ts +211 -0
- package/src/lab/automation/index.ts +13 -0
- package/src/lab/automation/orchestrator.ts +499 -0
- package/src/lab/automation/persistence.ts +512 -0
- package/src/lab/automation/planner.ts +371 -0
- package/src/lab/automation/policy.ts +136 -0
- package/src/lab/automation/queue.ts +191 -0
- package/src/lab/automation/recovery.ts +24 -0
- package/src/lab/automation/route-context.ts +21 -0
- package/src/lab/automation/run-key.ts +44 -0
- package/src/lab/automation/runs-query.ts +34 -0
- package/src/lab/automation/types.ts +160 -0
- package/src/lab/conformance/assertion.ts +325 -0
- package/src/lab/conformance/digest.ts +22 -0
- package/src/lab/conformance/executor.ts +741 -0
- package/src/lab/conformance/fixture-provider.ts +27 -0
- package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
- package/src/lab/conformance/harness-budget.ts +47 -0
- package/src/lab/conformance/index.ts +5 -0
- package/src/lab/conformance/jcs.ts +64 -0
- package/src/lab/conformance/json-pointer.ts +39 -0
- package/src/lab/conformance/manifest.ts +180 -0
- package/src/lab/conformance/mcp-stub.ts +179 -0
- package/src/lab/conformance/negative-controls.ts +164 -0
- package/src/lab/conformance/observation.ts +355 -0
- package/src/lab/conformance/runner.ts +68 -0
- package/src/lab/conformance/sse-normalize.ts +59 -0
- package/src/lab/conformance/suite-manifest.ts +78 -0
- package/src/lab/conformance/types.ts +214 -0
- package/src/lab/constants.ts +126 -0
- package/src/lab/digest.ts +64 -0
- package/src/lab/events/errors.ts +9 -0
- package/src/lab/events/limits.ts +117 -0
- package/src/lab/events/types.ts +229 -0
- package/src/lab/events/validate.ts +781 -0
- package/src/lab/fabric/constants.ts +40 -0
- package/src/lab/fabric/executor.ts +492 -0
- package/src/lab/fabric/index.ts +80 -0
- package/src/lab/fabric/manifest.ts +222 -0
- package/src/lab/fabric/observe.ts +489 -0
- package/src/lab/fabric/patch.ts +79 -0
- package/src/lab/fabric/producer-child.ts +139 -0
- package/src/lab/fabric/producer-isolate.ts +276 -0
- package/src/lab/fabric/producer-protocol.ts +61 -0
- package/src/lab/fabric/scratch.ts +439 -0
- package/src/lab/fabric/subject.ts +106 -0
- package/src/lab/fabric/types.ts +134 -0
- package/src/lab/fabric/verifier.ts +98 -0
- package/src/lab/index.ts +54 -0
- package/src/lab/ledger/artifact-refs.ts +127 -0
- package/src/lab/ledger/invalidation.ts +136 -0
- package/src/lab/ledger/purge.ts +310 -0
- package/src/lab/ledger/store.ts +532 -0
- package/src/lab/live/credential-lease.ts +53 -0
- package/src/lab/live/destination.ts +155 -0
- package/src/lab/live/executor.ts +336 -0
- package/src/lab/live/inert-tools.ts +56 -0
- package/src/lab/live/manifest.ts +85 -0
- package/src/lab/live/mcp-loopback.ts +57 -0
- package/src/lab/live/runner.ts +19 -0
- package/src/lab/live/sandbox.ts +61 -0
- package/src/lab/live/suite-manifest.ts +41 -0
- package/src/lab/live/transport.ts +118 -0
- package/src/lab/live/types.ts +197 -0
- package/src/lab/observe/from-conformance.ts +301 -0
- package/src/lab/observe/from-live.ts +117 -0
- package/src/lab/paths.ts +153 -0
- package/src/lab/projection/rebuild.ts +495 -0
- package/src/lab/projection/schema.ts +135 -0
- package/src/lab/projection/verdicts.ts +474 -0
- package/src/lab/projection/verification.ts +412 -0
- package/src/lab/public/bundle.ts +217 -0
- package/src/lab/public/community-authority.ts +175 -0
- package/src/lab/public/community-files.ts +29 -0
- package/src/lab/public/community.ts +479 -0
- package/src/lab/public/file-safety.ts +155 -0
- package/src/lab/public/ids.ts +26 -0
- package/src/lab/public/index.ts +16 -0
- package/src/lab/public/mutation-lock.ts +424 -0
- package/src/lab/public/operator.ts +353 -0
- package/src/lab/public/origin-purge.ts +79 -0
- package/src/lab/public/origin.ts +203 -0
- package/src/lab/public/privacy.ts +143 -0
- package/src/lab/public/private-file.ts +261 -0
- package/src/lab/public/project.ts +124 -0
- package/src/lab/public/purge-test-fault.ts +21 -0
- package/src/lab/public/purge.ts +223 -0
- package/src/lab/public/registry.ts +44 -0
- package/src/lab/public/revocation.ts +252 -0
- package/src/lab/public/signature.ts +243 -0
- package/src/lab/public/storage.ts +105 -0
- package/src/lab/public/strict-json.ts +206 -0
- package/src/lab/public/time.ts +26 -0
- package/src/lab/public/types.ts +172 -0
- package/src/lab/public/validate.ts +391 -0
- package/src/lab/query/catalog.ts +101 -0
- package/src/lab/query/connection.ts +107 -0
- package/src/lab/query/constants.ts +4 -0
- package/src/lab/query/cursor.ts +132 -0
- package/src/lab/query/dto-map.ts +277 -0
- package/src/lab/query/errors.ts +22 -0
- package/src/lab/query/freshness.ts +53 -0
- package/src/lab/query/index.ts +45 -0
- package/src/lab/query/latest-observation.ts +59 -0
- package/src/lab/query/passive-production.ts +159 -0
- package/src/lab/query/queries.ts +444 -0
- package/src/lab/query/types.ts +266 -0
- package/src/lab/subject/behavior-fingerprint.ts +77 -0
- package/src/lab/subject/installation-salt.ts +112 -0
- package/src/lab/subject/protocol-subject.ts +80 -0
- package/src/lab/subject/route-subject.ts +74 -0
- package/src/lib/abort.ts +146 -0
- package/src/lib/admin-secrets.ts +25 -0
- package/src/lib/admission.ts +83 -0
- package/src/lib/app-owned-memory-stores.ts +195 -0
- package/src/lib/app-owned-memory.ts +265 -0
- package/src/lib/bounded-body.ts +346 -0
- package/src/lib/bun-binary-validator.d.mts +3 -0
- package/src/lib/bun-binary-validator.mjs +18 -0
- package/src/lib/bun-runtime.ts +184 -0
- package/src/lib/bun-stream-caps.ts +130 -0
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +364 -0
- package/src/lib/crash-guard.ts +344 -0
- package/src/lib/debug-log-buffer.ts +83 -0
- package/src/lib/debug-settings.ts +108 -0
- package/src/lib/debug.ts +31 -0
- package/src/lib/destination-policy.ts +380 -0
- package/src/lib/errors.ts +406 -0
- package/src/lib/eventstream-decoder.ts +253 -0
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/gcp-adc.ts +341 -0
- package/src/lib/injection-debug-log.ts +58 -0
- package/src/lib/lab-activation.ts +223 -0
- package/src/lib/lab-live-execution-authority.ts +13 -0
- package/src/lib/lab-live-host.ts +30 -0
- package/src/lib/lab-live-pinned-sender.ts +56 -0
- package/src/lib/lab-live-route-production.ts +130 -0
- package/src/lib/lab-passive-linker-registration.ts +26 -0
- package/src/lib/local-management-attestation.ts +51 -0
- package/src/lib/local-management-capability.ts +100 -0
- package/src/lib/local-provider-reload-contract.ts +100 -0
- package/src/lib/open-url.ts +25 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/pinned-http.ts +270 -0
- package/src/lib/privacy.ts +20 -0
- package/src/lib/process-control.ts +168 -0
- package/src/lib/provider-outbound.ts +210 -0
- package/src/lib/provider-url.ts +14 -0
- package/src/lib/proxy-env.ts +18 -0
- package/src/lib/redact.ts +521 -0
- package/src/lib/retry-after.ts +55 -0
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/service-secrets.ts +25 -0
- package/src/lib/shadow-call.ts +61 -0
- package/src/lib/sidecar-tracker.ts +52 -0
- package/src/lib/sse-decoder.ts +364 -0
- package/src/lib/state-store-registrations.ts +119 -0
- package/src/lib/state-store-sweeper.ts +184 -0
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/test-home-guard.ts +90 -0
- package/src/lib/token-estimate.ts +86 -0
- package/src/lib/tool-argument-integers.ts +202 -0
- package/src/lib/translator-budget.ts +400 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +392 -0
- package/src/lib/win-exec.ts +115 -0
- package/src/lib/win-paths.ts +68 -0
- package/src/lib/windows-atomic-replace.ts +156 -0
- package/src/lib/windows-elevation.ts +773 -0
- package/src/lib/windows-secret-acl.ts +854 -0
- package/src/lib/windows-service-wrappers.ts +72 -0
- package/src/lib/windows-text.ts +106 -0
- package/src/lib/windows-user-principal.ts +341 -0
- package/src/lib/winsw.ts +403 -0
- package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
- package/src/oauth/account-import/index.ts +15 -0
- package/src/oauth/account-import/parser.ts +83 -0
- package/src/oauth/account-import/registry.ts +18 -0
- package/src/oauth/account-import/service.ts +75 -0
- package/src/oauth/account-import/types.ts +91 -0
- package/src/oauth/anthropic-routing.ts +594 -0
- package/src/oauth/anthropic.ts +188 -0
- package/src/oauth/antigravity-routing.ts +151 -0
- package/src/oauth/callback-server.ts +300 -0
- package/src/oauth/chatgpt.ts +161 -0
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +252 -0
- package/src/oauth/github-copilot.ts +428 -0
- package/src/oauth/google-antigravity.ts +262 -0
- package/src/oauth/health.ts +407 -0
- package/src/oauth/index.ts +1504 -0
- package/src/oauth/key-providers.ts +124 -0
- package/src/oauth/kimi.ts +227 -0
- package/src/oauth/kiro-credentials.ts +726 -0
- package/src/oauth/kiro.ts +621 -0
- package/src/oauth/local-token-detect.ts +130 -0
- package/src/oauth/log.ts +50 -0
- package/src/oauth/login-cli.ts +223 -0
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/pkce.ts +15 -0
- package/src/oauth/store.ts +728 -0
- package/src/oauth/token-guardian.ts +309 -0
- package/src/oauth/types.ts +62 -0
- package/src/oauth/xai.ts +241 -0
- package/src/providers/alibaba-region-backup.ts +75 -0
- package/src/providers/alibaba-region-migration.ts +156 -0
- package/src/providers/alibaba-region-startup.ts +36 -0
- package/src/providers/antigravity-models.ts +695 -0
- package/src/providers/antigravity-quota.ts +216 -0
- package/src/providers/api-keys.ts +140 -0
- package/src/providers/base-url-choices.ts +74 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +144 -0
- package/src/providers/context-cap.ts +82 -0
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/derive.ts +586 -0
- package/src/providers/fastwire.ts +501 -0
- package/src/providers/free-directory.ts +187 -0
- package/src/providers/github-copilot-transport.ts +56 -0
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +271 -0
- package/src/providers/kiro-models.ts +67 -0
- package/src/providers/label.ts +19 -0
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +449 -0
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/openai-sidecar.ts +243 -0
- package/src/providers/openai-tier-startup.ts +56 -0
- package/src/providers/openai-tiers.ts +423 -0
- package/src/providers/openai-virtual-models.ts +83 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/openrouter-routing.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +185 -0
- package/src/providers/quota.ts +2345 -0
- package/src/providers/registry.ts +2918 -0
- package/src/providers/replit/constants.ts +27 -0
- package/src/providers/replit/derive.ts +85 -0
- package/src/providers/replit/headers.ts +28 -0
- package/src/providers/replit/origin.ts +55 -0
- package/src/providers/replit/pair-install-response.ts +72 -0
- package/src/providers/replit/probe.ts +199 -0
- package/src/providers/replit/setup.ts +350 -0
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +103 -0
- package/src/providers/static-model-discovery.ts +86 -0
- package/src/providers/xai-responses-opt-in.ts +15 -0
- package/src/providers/xai-transport.ts +148 -0
- package/src/reasoning-effort.ts +183 -0
- package/src/responses/compaction.ts +142 -0
- package/src/responses/custom-tool-compat.ts +266 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +355 -0
- package/src/responses/parser.ts +838 -0
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +60 -0
- package/src/responses/reasoning-replay-cache.ts +426 -0
- package/src/responses/schema.ts +165 -0
- package/src/responses/spill-store.ts +459 -0
- package/src/responses/state.ts +1433 -0
- package/src/responses/thought-signature-replay.ts +347 -0
- package/src/responses/tool-groups.ts +19 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/router.ts +761 -0
- package/src/routing/analytics.ts +378 -0
- package/src/routing/capability.ts +244 -0
- package/src/routing/compatibility/assemble.ts +73 -0
- package/src/routing/compatibility/behavior.ts +278 -0
- package/src/routing/compatibility/catalog.ts +99 -0
- package/src/routing/compatibility/endpoint.ts +52 -0
- package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
- package/src/routing/compatibility/policy.ts +181 -0
- package/src/routing/compatibility/provider-slot.ts +56 -0
- package/src/routing/compatibility/reader.ts +110 -0
- package/src/routing/compatibility/subject.ts +191 -0
- package/src/routing/compatibility/types.ts +64 -0
- package/src/routing/compatibility/version.ts +104 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +495 -0
- package/src/routing/health.ts +412 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +547 -0
- package/src/routing/quota.ts +145 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +776 -0
- package/src/server/adapter-resolve.ts +53 -0
- package/src/server/auth-cors.ts +751 -0
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +442 -0
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +426 -0
- package/src/server/claude-messages.ts +1030 -0
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +190 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +152 -0
- package/src/server/image-retry.ts +42 -0
- package/src/server/images.ts +568 -0
- package/src/server/index.ts +1813 -0
- package/src/server/lifecycle.ts +498 -0
- package/src/server/live.ts +717 -0
- package/src/server/local-management-read-client.ts +90 -0
- package/src/server/local-provider-reload-client.ts +137 -0
- package/src/server/management/agent-settings-routes.ts +1433 -0
- package/src/server/management/api-access.ts +141 -0
- package/src/server/management/api-key-usage.ts +193 -0
- package/src/server/management/body.ts +41 -0
- package/src/server/management/combo-routes.ts +263 -0
- package/src/server/management/config-routes.ts +835 -0
- package/src/server/management/context.ts +113 -0
- package/src/server/management/integration-routes.ts +498 -0
- package/src/server/management/lab-automation-routes.ts +206 -0
- package/src/server/management/lab-routes.ts +563 -0
- package/src/server/management/logs-usage-routes.ts +586 -0
- package/src/server/management/model-routes.ts +560 -0
- package/src/server/management/model-rows.ts +163 -0
- package/src/server/management/native-integration-routes.ts +769 -0
- package/src/server/management/oauth-account-routes.ts +637 -0
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +1033 -0
- package/src/server/management/replit-provider-routes.ts +86 -0
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +385 -0
- package/src/server/management/shared.ts +286 -0
- package/src/server/management/sidebar-routes.ts +106 -0
- package/src/server/management/storage-log-guard-routes.ts +186 -0
- package/src/server/management/sync-response.ts +69 -0
- package/src/server/management/system-restart.ts +435 -0
- package/src/server/management/system-routes.ts +194 -0
- package/src/server/management/usage-summary-cache.ts +94 -0
- package/src/server/management/vision-sidecar-options.ts +167 -0
- package/src/server/management/web-search-sidecar-options.ts +120 -0
- package/src/server/management-api.ts +314 -0
- package/src/server/management-auth.ts +482 -0
- package/src/server/memory-watchdog.ts +156 -0
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/port-reclaim.ts +307 -0
- package/src/server/ports.ts +156 -0
- package/src/server/proxy-liveness.ts +328 -0
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +353 -0
- package/src/server/relay.ts +1209 -0
- package/src/server/request-decompress.ts +239 -0
- package/src/server/request-log-conversation.ts +168 -0
- package/src/server/request-log.ts +1259 -0
- package/src/server/responses/agent-task-recovery-cache.ts +143 -0
- package/src/server/responses/agent-task-recovery.ts +465 -0
- package/src/server/responses/collaboration.ts +551 -0
- package/src/server/responses/compact.ts +771 -0
- package/src/server/responses/core.ts +5389 -0
- package/src/server/responses/empty-completion-guard.ts +276 -0
- package/src/server/responses/encrypted-payload.ts +331 -0
- package/src/server/responses/fetch-helpers.ts +232 -0
- package/src/server/responses/input-admission.ts +185 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/passthrough-error.ts +78 -0
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +251 -0
- package/src/server/responses/terminal-guard.ts +251 -0
- package/src/server/responses/upstream-error.ts +53 -0
- package/src/server/responses/ws-upstream.ts +308 -0
- package/src/server/responses-custom-tool-repair.ts +282 -0
- package/src/server/responses-image-gen-repair.ts +132 -0
- package/src/server/responses-item-id-repair.ts +272 -0
- package/src/server/responses-json-events.ts +90 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses-terminal-repair.ts +342 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +153 -0
- package/src/server/responses.ts +25 -0
- package/src/server/search.ts +201 -0
- package/src/server/sse-frame-buffer.ts +292 -0
- package/src/server/sse-payload-rewrite.ts +263 -0
- package/src/server/startup-action-control.ts +315 -0
- package/src/server/startup-health-cache.ts +131 -0
- package/src/server/system-env.ts +484 -0
- package/src/server/windows-tcp-drop.ts +184 -0
- package/src/server/windows-tray-control.ts +41 -0
- package/src/server/ws-bridge.ts +472 -0
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +3575 -0
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/stall-timeout.ts +20 -0
- package/src/storage/cleanup-job.ts +57 -0
- package/src/storage/cleanup.ts +3085 -0
- package/src/storage/policy-job.ts +457 -0
- package/src/storage/policy-scheduler.ts +40 -0
- package/src/storage/policy-worker.ts +59 -0
- package/src/storage/policy.ts +527 -0
- package/src/storage/restore-job.ts +299 -0
- package/src/storage/restore-worker.ts +58 -0
- package/src/storage/scanner.ts +238 -0
- package/src/storage/storage-mutation-coordinator.ts +139 -0
- package/src/storage/worker-lifecycle.ts +215 -0
- package/src/tray/assets/opencodex-tray-offline.ico +0 -0
- package/src/tray/assets/opencodex-tray-online.ico +0 -0
- package/src/tray/assets/opencodex-tray-warning.ico +0 -0
- package/src/tray/assets/opencodex-tray.png +0 -0
- package/src/tray/windows-tray.ps1 +364 -0
- package/src/tray/windows.ts +757 -0
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +876 -0
- package/src/types/provider.ts +545 -0
- package/src/types/request.ts +384 -0
- package/src/types/tools.ts +131 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +106 -0
- package/src/update/badge.ts +72 -0
- package/src/update/index.ts +415 -0
- package/src/update/job.ts +1887 -0
- package/src/update/notify.ts +263 -0
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/npm-invocation.d.mts +23 -0
- package/src/update/npm-invocation.mjs +94 -0
- package/src/update/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +259 -0
- package/src/update/tray-update-plan.d.mts +18 -0
- package/src/update/tray-update-plan.mjs +38 -0
- package/src/usage/cost.ts +625 -0
- package/src/usage/debug.ts +97 -0
- package/src/usage/expected-prices.ts +416 -0
- package/src/usage/log.ts +1223 -0
- package/src/usage/summary.ts +753 -0
- package/src/usage/totals.ts +14 -0
- package/src/usage/user-cost-overlay-reconciler.ts +313 -0
- package/src/usage/user-cost-overlays.ts +314 -0
- package/src/vision/anthropic-describe.ts +189 -0
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +131 -0
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +681 -0
- package/src/vision/reasoning.ts +55 -0
- package/src/vision/routed-describe.ts +175 -0
- package/src/vision/timeout-bounds.ts +9 -0
- package/src/web-search/anthropic-executor.ts +195 -0
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +88 -0
- package/src/web-search/executor.ts +113 -0
- package/src/web-search/format-result.ts +89 -0
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +331 -0
- package/src/web-search/loop.ts +896 -0
- package/src/web-search/parse.ts +315 -0
- package/src/web-search/progress-stream.ts +342 -0
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/synthetic-tool.ts +47 -0
- package/src/web-search/xai-executor.ts +219 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import type { TranslatorBudget } from "../lib/translator-budget";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared client-facing SSE payload rewrite shell.
|
|
5
|
+
*
|
|
6
|
+
* Multiple opt-in transforms (image-gen namespace restore, item-id repair, …) compose into one
|
|
7
|
+
* parse/stringify pass so a tee'd stream is not re-framed twice per event.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type SsePayloadRewrite = (payload: string) => string;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Block-level SSE rewrite: maps one complete SSE event block (without its
|
|
14
|
+
* blank-line delimiter) to zero or more replacement blocks. This is the
|
|
15
|
+
* contract lifecycle repair needs: injecting missing canonical events
|
|
16
|
+
* (#893) is impossible in the one-payload-in/one-payload-out model.
|
|
17
|
+
*
|
|
18
|
+
* `dispose` releases any retained state (budget-charged collectors) when the
|
|
19
|
+
* relay tears down — terminal, EOF, cancel, or error. Relays call it exactly
|
|
20
|
+
* once per teardown path.
|
|
21
|
+
*/
|
|
22
|
+
export type SseBlockRewrite = ((block: string) => readonly string[]) & {
|
|
23
|
+
dispose?: () => void;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/** Adapt a payload rewrite to the block contract (replace only on change). */
|
|
27
|
+
export function payloadRewriteAsBlockRewrite(rewrite: SsePayloadRewrite): SseBlockRewrite {
|
|
28
|
+
return (block) => {
|
|
29
|
+
const payload = sseDataPayload(block);
|
|
30
|
+
if (payload === null) return [block];
|
|
31
|
+
const rewritten = rewrite(payload);
|
|
32
|
+
return rewritten !== payload ? [replaceSseDataPayload(block, rewritten)] : [block];
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Chain block rewrites: every block stage N emits feeds stage N+1. */
|
|
37
|
+
export function composeSseBlockRewrites(...rewrites: SseBlockRewrite[]): SseBlockRewrite {
|
|
38
|
+
const active = rewrites.filter(Boolean);
|
|
39
|
+
if (active.length === 0) return Object.assign((block: string) => [block], {});
|
|
40
|
+
const composed: SseBlockRewrite = (block: string) => {
|
|
41
|
+
let blocks: readonly string[] = [block];
|
|
42
|
+
for (const rewrite of active) {
|
|
43
|
+
const next: string[] = [];
|
|
44
|
+
for (const current of blocks) next.push(...rewrite(current));
|
|
45
|
+
blocks = next;
|
|
46
|
+
}
|
|
47
|
+
return blocks;
|
|
48
|
+
};
|
|
49
|
+
// Child disposal is part of the contract: one idempotent disposer for the
|
|
50
|
+
// whole chain, so relay teardown never leaks a nested collector.
|
|
51
|
+
let disposed = false;
|
|
52
|
+
composed.dispose = () => {
|
|
53
|
+
if (disposed) return;
|
|
54
|
+
disposed = true;
|
|
55
|
+
for (const rewrite of active) {
|
|
56
|
+
try { rewrite.dispose?.(); } catch { /* teardown must not throw */ }
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return composed;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Split one complete SSE event block while retaining its original blank-line delimiter. */
|
|
63
|
+
export function nextSseBlock(buffer: string): { block: string; delimiter: string; rest: string } | null {
|
|
64
|
+
const match = buffer.match(/\r?\n\r?\n/);
|
|
65
|
+
if (!match || match.index === undefined) return null;
|
|
66
|
+
return {
|
|
67
|
+
block: buffer.slice(0, match.index),
|
|
68
|
+
delimiter: match[0],
|
|
69
|
+
rest: buffer.slice(match.index + match[0].length),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Join all data lines from one SSE event according to the event-stream field rules. */
|
|
74
|
+
export function sseDataPayload(block: string): string | null {
|
|
75
|
+
const data: string[] = [];
|
|
76
|
+
for (const line of block.split(/\r?\n/)) {
|
|
77
|
+
if (!line.startsWith("data:")) continue;
|
|
78
|
+
const value = line.slice(5);
|
|
79
|
+
data.push(value.startsWith(" ") ? value.slice(1) : value);
|
|
80
|
+
}
|
|
81
|
+
return data.length > 0 ? data.join("\n") : null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Replace an SSE event's data field while preserving non-data fields and newline style. */
|
|
85
|
+
export function replaceSseDataPayload(block: string, payload: string): string {
|
|
86
|
+
const newline = block.includes("\r\n") ? "\r\n" : "\n";
|
|
87
|
+
const lines = block.split(/\r?\n/);
|
|
88
|
+
const rewritten: string[] = [];
|
|
89
|
+
let replaced = false;
|
|
90
|
+
for (const line of lines) {
|
|
91
|
+
if (!line.startsWith("data:")) {
|
|
92
|
+
rewritten.push(line);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (!replaced) {
|
|
96
|
+
rewritten.push(`data: ${payload}`);
|
|
97
|
+
replaced = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return replaced ? rewritten.join(newline) : block;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Apply rewrites left-to-right; empty list is identity. */
|
|
104
|
+
export function composeSsePayloadRewrites(...rewrites: SsePayloadRewrite[]): SsePayloadRewrite {
|
|
105
|
+
if (rewrites.length === 0) return (payload) => payload;
|
|
106
|
+
if (rewrites.length === 1) return rewrites[0]!;
|
|
107
|
+
return (payload) => {
|
|
108
|
+
let next = payload;
|
|
109
|
+
for (const rewrite of rewrites) next = rewrite(next);
|
|
110
|
+
return next;
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Relay an SSE body through a single JS pull wrapper, rewriting each event's data payload in place.
|
|
116
|
+
* Non-data fields and framing are preserved; invalid JSON payloads are left to the rewrite callback.
|
|
117
|
+
*/
|
|
118
|
+
export function relaySseWithPayloadRewrite(
|
|
119
|
+
body: ReadableStream<Uint8Array>,
|
|
120
|
+
rewrite: SsePayloadRewrite,
|
|
121
|
+
translatorBudget: TranslatorBudget,
|
|
122
|
+
): ReadableStream<Uint8Array> {
|
|
123
|
+
return relaySseWithBlockRewrite(body, payloadRewriteAsBlockRewrite(rewrite), translatorBudget);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Relay an SSE body through a single JS pull wrapper, applying a block-level
|
|
128
|
+
* rewrite that may emit zero or more blocks per upstream event (lifecycle
|
|
129
|
+
* event injection, #893). The original stream's delimiter style is preserved
|
|
130
|
+
* for every emitted block.
|
|
131
|
+
*/
|
|
132
|
+
export function relaySseWithBlockRewrite(
|
|
133
|
+
body: ReadableStream<Uint8Array>,
|
|
134
|
+
rewrite: SseBlockRewrite,
|
|
135
|
+
translatorBudget: TranslatorBudget,
|
|
136
|
+
): ReadableStream<Uint8Array> {
|
|
137
|
+
const reader = body.getReader();
|
|
138
|
+
const decoder = new TextDecoder();
|
|
139
|
+
const encoder = new TextEncoder();
|
|
140
|
+
let buffer = "";
|
|
141
|
+
let bufferBytes = 0;
|
|
142
|
+
// Relays have several independent teardown paths; disposal is exactly once.
|
|
143
|
+
let disposed = false;
|
|
144
|
+
let cancelled = false;
|
|
145
|
+
const disposeRewrite = (): void => {
|
|
146
|
+
if (disposed) return;
|
|
147
|
+
disposed = true;
|
|
148
|
+
try { rewrite.dispose?.(); } catch { /* teardown must not throw */ }
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const appendBuffer = (fragment: string): void => {
|
|
152
|
+
if (!fragment) return;
|
|
153
|
+
const nextBytes = bufferBytes + encoder.encode(fragment).byteLength;
|
|
154
|
+
const reservation = translatorBudget.reserveTransient(nextBytes, { kind: "live_transient" });
|
|
155
|
+
try {
|
|
156
|
+
buffer += fragment;
|
|
157
|
+
reservation.commitRetained();
|
|
158
|
+
translatorBudget.releaseRetained(bufferBytes, { kind: "live_transient" });
|
|
159
|
+
bufferBytes = nextBytes;
|
|
160
|
+
} catch (error) {
|
|
161
|
+
reservation.release();
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const replaceBuffer = (next: string): void => {
|
|
167
|
+
const nextBytes = encoder.encode(next).byteLength;
|
|
168
|
+
const reservation = translatorBudget.reserveTransient(nextBytes, { kind: "live_transient" });
|
|
169
|
+
reservation.commitRetained();
|
|
170
|
+
buffer = next;
|
|
171
|
+
translatorBudget.releaseRetained(bufferBytes, { kind: "live_transient" });
|
|
172
|
+
bufferBytes = nextBytes;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const enqueueText = (
|
|
176
|
+
controller: ReadableStreamDefaultController<Uint8Array>,
|
|
177
|
+
text: string,
|
|
178
|
+
): void => {
|
|
179
|
+
const bytes = encoder.encode(text).byteLength;
|
|
180
|
+
const reservation = translatorBudget.reserveTransient(bytes, { kind: "live_transient" });
|
|
181
|
+
try {
|
|
182
|
+
const encoded = encoder.encode(text);
|
|
183
|
+
reservation.commitRetained();
|
|
184
|
+
controller.enqueue(encoded);
|
|
185
|
+
translatorBudget.releaseRetained(bytes, { kind: "live_transient" });
|
|
186
|
+
} catch (error) {
|
|
187
|
+
reservation.release();
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const releaseBuffer = (): void => {
|
|
193
|
+
translatorBudget.releaseRetained(bufferBytes, { kind: "live_transient" });
|
|
194
|
+
buffer = "";
|
|
195
|
+
bufferBytes = 0;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const emitProcessedBlocks = (
|
|
199
|
+
controller: ReadableStreamDefaultController<Uint8Array>,
|
|
200
|
+
flushFinal = false,
|
|
201
|
+
): number => {
|
|
202
|
+
let emitted = 0;
|
|
203
|
+
let next: { block: string; delimiter: string; rest: string } | null;
|
|
204
|
+
while ((next = nextSseBlock(buffer))) {
|
|
205
|
+
replaceBuffer(next.rest);
|
|
206
|
+
for (const outBlock of rewrite(next.block)) {
|
|
207
|
+
enqueueText(controller, outBlock + next.delimiter);
|
|
208
|
+
emitted += 1;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (flushFinal && buffer.length > 0) {
|
|
212
|
+
const tailBlocks = rewrite(buffer);
|
|
213
|
+
// A trailing fragment has no delimiter of its own; multiple emitted
|
|
214
|
+
// blocks must still be framed as separate events (#893 review).
|
|
215
|
+
const tailDelimiter = buffer.includes("\r\n") ? "\r\n\r\n" : "\n\n";
|
|
216
|
+
for (let i = 0; i < tailBlocks.length; i++) {
|
|
217
|
+
enqueueText(controller, tailBlocks[i]! + (i < tailBlocks.length - 1 ? tailDelimiter : ""));
|
|
218
|
+
emitted += 1;
|
|
219
|
+
}
|
|
220
|
+
releaseBuffer();
|
|
221
|
+
}
|
|
222
|
+
return emitted;
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
return new ReadableStream<Uint8Array>({
|
|
226
|
+
async pull(controller) {
|
|
227
|
+
try {
|
|
228
|
+
// A network chunk is not an SSE-event boundary. Bun may not issue a
|
|
229
|
+
// second pull after a fulfilled pull enqueues nothing, so keep reading
|
|
230
|
+
// until at least one complete rewritten block is available or EOF is
|
|
231
|
+
// reached. This also handles block rewrites that intentionally drop an
|
|
232
|
+
// event without parking the client stream.
|
|
233
|
+
for (;;) {
|
|
234
|
+
const { done, value } = await reader.read();
|
|
235
|
+
// A cancel raced this pending read: never feed the rewriter again
|
|
236
|
+
// after its disposal (#893 review).
|
|
237
|
+
if (cancelled) return;
|
|
238
|
+
if (done) {
|
|
239
|
+
appendBuffer(decoder.decode());
|
|
240
|
+
emitProcessedBlocks(controller, true);
|
|
241
|
+
releaseBuffer();
|
|
242
|
+
disposeRewrite();
|
|
243
|
+
controller.close();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
appendBuffer(decoder.decode(value, { stream: true }));
|
|
247
|
+
if (emitProcessedBlocks(controller) > 0) return;
|
|
248
|
+
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
releaseBuffer();
|
|
251
|
+
disposeRewrite();
|
|
252
|
+
try { await reader.cancel(error); } catch { /* already closed */ }
|
|
253
|
+
controller.error(error);
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
cancel(reason) {
|
|
257
|
+
cancelled = true;
|
|
258
|
+
releaseBuffer();
|
|
259
|
+
disposeRewrite();
|
|
260
|
+
reader.cancel(reason).catch(() => {});
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { durableBunPath } from "../lib/bun-runtime";
|
|
5
|
+
import {
|
|
6
|
+
WINDOWS_SCHTASKS_CREATE_ACCESS_DENIED_MARKER,
|
|
7
|
+
isWindowsSchtasksCreateAccessDenied,
|
|
8
|
+
} from "../lib/windows-elevation";
|
|
9
|
+
import {
|
|
10
|
+
finalizeWindowsSchedulerServiceRegistration,
|
|
11
|
+
type ElevatedReconciliationOutcome,
|
|
12
|
+
type FinalizeWindowsSchedulerOptions,
|
|
13
|
+
type FinalizeWindowsSchedulerResult,
|
|
14
|
+
type WindowsSchedulerTaskProbe,
|
|
15
|
+
} from "../service";
|
|
16
|
+
|
|
17
|
+
export type StartupInstallAction = "install-service" | "install-shim";
|
|
18
|
+
|
|
19
|
+
export type StartupInstallState =
|
|
20
|
+
| { status: "idle" }
|
|
21
|
+
| {
|
|
22
|
+
status: "running";
|
|
23
|
+
action: StartupInstallAction;
|
|
24
|
+
attemptId: string;
|
|
25
|
+
startedAt: number;
|
|
26
|
+
}
|
|
27
|
+
| {
|
|
28
|
+
status: "indeterminate";
|
|
29
|
+
action: "install-service";
|
|
30
|
+
attemptId: string;
|
|
31
|
+
startedAt: number;
|
|
32
|
+
timedOutAt: number;
|
|
33
|
+
reconciliation: Promise<ElevatedReconciliationOutcome>;
|
|
34
|
+
}
|
|
35
|
+
| {
|
|
36
|
+
status: "blocked";
|
|
37
|
+
reason: "partial-elevated-install";
|
|
38
|
+
action: "install-service";
|
|
39
|
+
attemptId: string;
|
|
40
|
+
detail: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const INSTALL_DETAIL_LIMIT = 2_000;
|
|
44
|
+
const INDETERMINATE_MESSAGE =
|
|
45
|
+
"Windows elevation timed out, but the elevated Task Scheduler transaction may still be running. New service installation attempts are temporarily blocked while OpenCodex reconciles its final state.";
|
|
46
|
+
const RECONCILING_MESSAGE =
|
|
47
|
+
"A previous elevated Windows service installation is still being reconciled. Wait for it to finish or inspect the Task Scheduler state before retrying.";
|
|
48
|
+
const BLOCKED_PARTIAL_MESSAGE =
|
|
49
|
+
"A previous elevated Windows service installation left a partial Task Scheduler state. Remove the OpenCodex scheduler task (or confirm it is absent), then clear the install block before retrying.";
|
|
50
|
+
|
|
51
|
+
let installState: StartupInstallState = { status: "idle" };
|
|
52
|
+
|
|
53
|
+
type FinalizeFn = (
|
|
54
|
+
script?: string,
|
|
55
|
+
options?: FinalizeWindowsSchedulerOptions,
|
|
56
|
+
) => Promise<FinalizeWindowsSchedulerResult>;
|
|
57
|
+
let finalizeImpl: FinalizeFn = finalizeWindowsSchedulerServiceRegistration;
|
|
58
|
+
|
|
59
|
+
/** Test-only seam so elevation retry tests do not mock.module the service package. */
|
|
60
|
+
export function setStartupInstallFinalizeForTests(next: FinalizeFn | null): void {
|
|
61
|
+
finalizeImpl = next ?? finalizeWindowsSchedulerServiceRegistration;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Snapshot of the install lock for diagnostics and tests. */
|
|
65
|
+
export function getStartupInstallState(): StartupInstallState {
|
|
66
|
+
return installState;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** True when this attempt still owns the active/indeterminate/blocked lock. */
|
|
70
|
+
export function ownsStartupInstallAttempt(attemptId: string): boolean {
|
|
71
|
+
return (installState.status === "running"
|
|
72
|
+
|| installState.status === "indeterminate"
|
|
73
|
+
|| installState.status === "blocked")
|
|
74
|
+
&& installState.attemptId === attemptId;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Clear a partial-install block after the operator has cleaned up Task Scheduler.
|
|
79
|
+
* Requires an observed probe and clears only when the task is proven absent.
|
|
80
|
+
* Does not itself delete the task.
|
|
81
|
+
*/
|
|
82
|
+
export function clearStartupInstallPartialBlock(options: {
|
|
83
|
+
probe: WindowsSchedulerTaskProbe;
|
|
84
|
+
}): { cleared: boolean; detail: string } {
|
|
85
|
+
if (installState.status !== "blocked") {
|
|
86
|
+
return { cleared: false, detail: `Install lock is ${installState.status}, not blocked.` };
|
|
87
|
+
}
|
|
88
|
+
if (options.probe.status === "present") {
|
|
89
|
+
return {
|
|
90
|
+
cleared: false,
|
|
91
|
+
detail: "OpenCodex Task Scheduler task is still present; remove it before clearing the block.",
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
if (options.probe.status === "unknown") {
|
|
95
|
+
return {
|
|
96
|
+
cleared: false,
|
|
97
|
+
detail: `Could not verify Task Scheduler absence (${options.probe.detail}); not clearing the block.`,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
installState = { status: "idle" };
|
|
101
|
+
return { cleared: true, detail: "Partial-install block cleared." };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Test-only reset of the install lock. */
|
|
105
|
+
export function resetStartupInstallStateForTests(): void {
|
|
106
|
+
installState = { status: "idle" };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function startupInstallArgv(
|
|
110
|
+
action: StartupInstallAction,
|
|
111
|
+
options?: { repair?: boolean },
|
|
112
|
+
): string[] {
|
|
113
|
+
if (action === "install-service") {
|
|
114
|
+
return options?.repair ? ["service", "repair"] : ["service", "install"];
|
|
115
|
+
}
|
|
116
|
+
return ["codex-shim", "install"];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface CliInstallFailure {
|
|
120
|
+
/** Machine marker such as OCX_ERROR_CODE=..., when present in any stream. */
|
|
121
|
+
code: string | null;
|
|
122
|
+
stdout: string;
|
|
123
|
+
stderr: string;
|
|
124
|
+
message: string;
|
|
125
|
+
/** Bounded user-facing diagnostic (may append the marker if truncated away). */
|
|
126
|
+
detail: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function extractOcxErrorCode(text: string): string | null {
|
|
130
|
+
const match = text.match(/OCX_ERROR_CODE=[A-Z0-9_]+/);
|
|
131
|
+
return match ? match[0] : null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Classify a CLI install failure, keeping the machine marker separate from the
|
|
136
|
+
* truncated user-facing diagnostic.
|
|
137
|
+
*/
|
|
138
|
+
export function classifyCliInstallFailure(stdout: string, stderr: string, error: Error): CliInstallFailure {
|
|
139
|
+
const stdoutText = stdout.trim();
|
|
140
|
+
const stderrText = stderr.trim();
|
|
141
|
+
const message = error.message.trim();
|
|
142
|
+
const combined = [stderrText, stdoutText, message].filter(Boolean).join("\n");
|
|
143
|
+
const code = extractOcxErrorCode(combined);
|
|
144
|
+
let detail = combined || message;
|
|
145
|
+
if (detail.length > INSTALL_DETAIL_LIMIT) {
|
|
146
|
+
const truncated = detail.slice(0, INSTALL_DETAIL_LIMIT);
|
|
147
|
+
detail = code && !truncated.includes(code)
|
|
148
|
+
? `${truncated}\n${code}… (truncated)`
|
|
149
|
+
: `${truncated}… (truncated)`;
|
|
150
|
+
}
|
|
151
|
+
return { code, stdout: stdoutText, stderr: stderrText, message, detail };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** @deprecated Prefer classifyCliInstallFailure; kept for existing tests. */
|
|
155
|
+
export function installFailureDetail(stdout: string, stderr: string, error: Error): string {
|
|
156
|
+
return classifyCliInstallFailure(stdout, stderr, error).detail;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function runCliInstall(
|
|
160
|
+
action: StartupInstallAction,
|
|
161
|
+
options?: { repair?: boolean },
|
|
162
|
+
): Promise<{ stdout: string; stderr: string }> {
|
|
163
|
+
const bun = durableBunPath();
|
|
164
|
+
const cli = join(import.meta.dir, "..", "cli", "index.ts");
|
|
165
|
+
const argv = [cli, ...startupInstallArgv(action, options)];
|
|
166
|
+
return new Promise((resolve, reject) => {
|
|
167
|
+
const timeout = process.platform === "win32" && action === "install-service"
|
|
168
|
+
? 0
|
|
169
|
+
: 60_000;
|
|
170
|
+
execFile(bun, argv, {
|
|
171
|
+
encoding: "utf8",
|
|
172
|
+
env: process.env,
|
|
173
|
+
// A fresh Windows scheduler install now owns its UAC prompt inside this CLI
|
|
174
|
+
// transaction. Killing only the CLI at 60s can orphan its elevated schtasks child,
|
|
175
|
+
// which may register the task after the Dashboard has reported failure. Keep the
|
|
176
|
+
// async request/attempt lock alive until Windows returns approval or cancellation.
|
|
177
|
+
timeout,
|
|
178
|
+
windowsHide: true,
|
|
179
|
+
maxBuffer: 256 * 1024,
|
|
180
|
+
}, (error, stdout, stderr) => {
|
|
181
|
+
if (error) {
|
|
182
|
+
const failure = classifyCliInstallFailure(stdout, stderr, error);
|
|
183
|
+
reject(Object.assign(new Error(failure.detail), { ocxInstallFailure: failure }));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
resolve({ stdout, stderr });
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function installFailureCode(error: unknown): string | null {
|
|
192
|
+
if (error && typeof error === "object" && "ocxInstallFailure" in error) {
|
|
193
|
+
const failure = (error as { ocxInstallFailure?: CliInstallFailure }).ocxInstallFailure;
|
|
194
|
+
if (failure?.code) return failure.code;
|
|
195
|
+
}
|
|
196
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
197
|
+
return extractOcxErrorCode(detail);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function rejectIfBusy(_action: StartupInstallAction): Error | null {
|
|
201
|
+
if (installState.status === "running") {
|
|
202
|
+
return new Error(`Another startup installation is already running: ${installState.action}`);
|
|
203
|
+
}
|
|
204
|
+
if (installState.status === "indeterminate") {
|
|
205
|
+
return new Error(RECONCILING_MESSAGE);
|
|
206
|
+
}
|
|
207
|
+
if (installState.status === "blocked") {
|
|
208
|
+
return new Error(BLOCKED_PARTIAL_MESSAGE);
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function applyReconciliationOutcome(
|
|
214
|
+
attemptId: string,
|
|
215
|
+
outcome: ElevatedReconciliationOutcome,
|
|
216
|
+
): void {
|
|
217
|
+
if (installState.status !== "indeterminate" || installState.attemptId !== attemptId) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (outcome === "blocked-partial") {
|
|
221
|
+
installState = {
|
|
222
|
+
status: "blocked",
|
|
223
|
+
reason: "partial-elevated-install",
|
|
224
|
+
action: "install-service",
|
|
225
|
+
attemptId,
|
|
226
|
+
detail: BLOCKED_PARTIAL_MESSAGE,
|
|
227
|
+
};
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
installState = { status: "idle" };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Execute the existing fixed CLI installer outside the proxy event loop.
|
|
235
|
+
*
|
|
236
|
+
* Repair mode (`options.repair`) runs `ocx service repair` — asset rewrite + restart
|
|
237
|
+
* without Task Scheduler re-registration, so it must not enter the UAC elevation path.
|
|
238
|
+
*
|
|
239
|
+
* After an elevation request timeout the lock becomes `indeterminate` until the
|
|
240
|
+
* original elevated transaction completes and is reconciled. A process restart
|
|
241
|
+
* clears this in-memory lock — callers must then inspect Task Scheduler reality
|
|
242
|
+
* (see evaluateSchedulerInstallRestartReconciliation) before installing again.
|
|
243
|
+
*/
|
|
244
|
+
export function runStartupInstallAction(
|
|
245
|
+
action: StartupInstallAction,
|
|
246
|
+
options?: { repair?: boolean },
|
|
247
|
+
): Promise<{ message: string }> {
|
|
248
|
+
const busy = rejectIfBusy(action);
|
|
249
|
+
if (busy) return Promise.reject(busy);
|
|
250
|
+
|
|
251
|
+
const repair = options?.repair === true;
|
|
252
|
+
const attemptId = randomUUID();
|
|
253
|
+
const startedAt = Date.now();
|
|
254
|
+
installState = { status: "running", action, attemptId, startedAt };
|
|
255
|
+
|
|
256
|
+
const operation = (async () => {
|
|
257
|
+
try {
|
|
258
|
+
await runCliInstall(action, { repair });
|
|
259
|
+
} catch (error) {
|
|
260
|
+
const code = installFailureCode(error);
|
|
261
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
262
|
+
// Elevate only for fresh install + structured Task Scheduler /create access denial —
|
|
263
|
+
// never for repair, WinSW removal, asset writes, or generic permission errors.
|
|
264
|
+
if (
|
|
265
|
+
!repair
|
|
266
|
+
&& action === "install-service"
|
|
267
|
+
&& process.platform === "win32"
|
|
268
|
+
&& (code === WINDOWS_SCHTASKS_CREATE_ACCESS_DENIED_MARKER
|
|
269
|
+
|| isWindowsSchtasksCreateAccessDenied(detail))
|
|
270
|
+
) {
|
|
271
|
+
const finalized = await finalizeImpl(undefined, {
|
|
272
|
+
attemptId,
|
|
273
|
+
stillOwnsAttempt: ownsStartupInstallAttempt,
|
|
274
|
+
});
|
|
275
|
+
if (finalized.kind === "indeterminate") {
|
|
276
|
+
const ownedAttemptId = finalized.attemptId;
|
|
277
|
+
installState = {
|
|
278
|
+
status: "indeterminate",
|
|
279
|
+
action: "install-service",
|
|
280
|
+
attemptId: ownedAttemptId,
|
|
281
|
+
startedAt,
|
|
282
|
+
timedOutAt: Date.now(),
|
|
283
|
+
reconciliation: finalized.reconciliation,
|
|
284
|
+
};
|
|
285
|
+
void finalized.reconciliation.then(
|
|
286
|
+
outcome => {
|
|
287
|
+
applyReconciliationOutcome(ownedAttemptId, outcome);
|
|
288
|
+
},
|
|
289
|
+
() => {
|
|
290
|
+
// Fail closed: a rejected reconciliation must not leave an unhandled rejection
|
|
291
|
+
// or silently idle the lock while Task Scheduler state may still be partial.
|
|
292
|
+
applyReconciliationOutcome(ownedAttemptId, "blocked-partial");
|
|
293
|
+
},
|
|
294
|
+
);
|
|
295
|
+
throw new Error(INDETERMINATE_MESSAGE);
|
|
296
|
+
}
|
|
297
|
+
} else {
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (action === "install-service") {
|
|
302
|
+
return { message: repair ? "Background service repaired." : "Background service installed." };
|
|
303
|
+
}
|
|
304
|
+
return {
|
|
305
|
+
message: repair ? "Codex launcher shim repaired." : "Codex launcher shim installed.",
|
|
306
|
+
};
|
|
307
|
+
})();
|
|
308
|
+
|
|
309
|
+
return operation.finally(() => {
|
|
310
|
+
// Do not clear an indeterminate or blocked lock from a timed-out elevation.
|
|
311
|
+
if (installState.status === "running" && installState.attemptId === attemptId) {
|
|
312
|
+
installState = { status: "idle" };
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
}
|