@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
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readSync, unlinkSync, writeSync } from "node:fs";
|
|
2
|
+
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readSync, statSync, unlinkSync, writeSync } from "node:fs";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
import { zstdDecompressSync } from "node:zlib";
|
|
5
5
|
import { Database } from "bun:sqlite";
|
|
6
|
-
import {
|
|
6
|
+
import { resolveCodexStateDbPath } from "./paths";
|
|
7
7
|
import { atomicWriteFile, getConfigDir } from "../config";
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -13,13 +13,18 @@ import { atomicWriteFile, getConfigDir } from "../config";
|
|
|
13
13
|
*/
|
|
14
14
|
export const MAX_ROLLOUT_ZST_DECOMPRESSED_BYTES = 64 * 1024 * 1024;
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
/**
|
|
17
|
+
* The manifest that shadows one state database.
|
|
18
|
+
*
|
|
19
|
+
* Exported because the history job must resolve it at CALL time for a Worker
|
|
20
|
+
* that does not inherit this module's load-time constants — and must resolve it
|
|
21
|
+
* the same way, since a manifest addressed differently is a different manifest.
|
|
22
|
+
*/
|
|
23
|
+
export function historyBackupPathFor(stateDbPath: string): string {
|
|
18
24
|
const normalized = process.platform === "win32" ? resolve(stateDbPath).toLowerCase() : resolve(stateDbPath);
|
|
19
25
|
const id = createHash("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
20
26
|
return join(getConfigDir(), `codex-history-backup-${id}.json`);
|
|
21
27
|
}
|
|
22
|
-
const HISTORY_BACKUP_PATH = historyBackupPathFor(STATE_DB_PATH);
|
|
23
28
|
const RESUMABLE_SOURCES = ["cli", "vscode"] as const;
|
|
24
29
|
|
|
25
30
|
/**
|
|
@@ -157,7 +162,9 @@ function patchFirstLineProviderInPlace(path: string, expectedId: string, provide
|
|
|
157
162
|
}
|
|
158
163
|
}
|
|
159
164
|
|
|
160
|
-
type CodexHistoryProvider = "openai" | "opencodex";
|
|
165
|
+
export type CodexHistoryProvider = "openai" | "opencodex";
|
|
166
|
+
|
|
167
|
+
export type CodexHistoryFailureReason = "busy" | "permission";
|
|
161
168
|
|
|
162
169
|
export interface CodexHistorySyncResult {
|
|
163
170
|
rows: number;
|
|
@@ -165,6 +172,8 @@ export interface CodexHistorySyncResult {
|
|
|
165
172
|
ejectedRows?: number;
|
|
166
173
|
/** Set when a lock/busy error survived retries and the sync was SKIPPED, not empty. */
|
|
167
174
|
failed?: true;
|
|
175
|
+
/** Why the retry budget was exhausted when `failed` is set. */
|
|
176
|
+
failureReason?: CodexHistoryFailureReason;
|
|
168
177
|
}
|
|
169
178
|
|
|
170
179
|
interface ThreadRow {
|
|
@@ -189,6 +198,49 @@ interface BackupManifest {
|
|
|
189
198
|
entries: Record<string, BackupEntry>;
|
|
190
199
|
}
|
|
191
200
|
|
|
201
|
+
export interface CodexHistoryVerifiedNoopProof {
|
|
202
|
+
readonly kind: "verified-noop";
|
|
203
|
+
readonly pendingRows: 0;
|
|
204
|
+
readonly backupEntries: 0;
|
|
205
|
+
readonly canonicalStateDbPath: string;
|
|
206
|
+
readonly stateDbPresent: true;
|
|
207
|
+
readonly canonicalBackupPath: string;
|
|
208
|
+
readonly backupPresent: boolean;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export type CodexHistoryNoopSnapshot =
|
|
212
|
+
| CodexHistoryVerifiedNoopProof
|
|
213
|
+
| {
|
|
214
|
+
readonly kind: "work-pending";
|
|
215
|
+
readonly pendingRows: number;
|
|
216
|
+
readonly backupEntries: number;
|
|
217
|
+
readonly canonicalStateDbPath: string;
|
|
218
|
+
readonly stateDbPresent: boolean;
|
|
219
|
+
readonly canonicalBackupPath: string;
|
|
220
|
+
readonly backupPresent: boolean;
|
|
221
|
+
}
|
|
222
|
+
| {
|
|
223
|
+
readonly kind: "unknown";
|
|
224
|
+
readonly pendingRows: null;
|
|
225
|
+
readonly backupEntries: null;
|
|
226
|
+
readonly canonicalStateDbPath: string;
|
|
227
|
+
readonly stateDbPresent: boolean;
|
|
228
|
+
readonly canonicalBackupPath: string;
|
|
229
|
+
readonly backupPresent: boolean;
|
|
230
|
+
readonly reason: "backup-path" | "database-absent" | "manifest-read" | "manifest-schema" | "manifest-foreign" | "database-query" | "snapshot-race";
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
type StrictBackupInspection =
|
|
234
|
+
| { readonly kind: "known"; readonly present: boolean; readonly entries: number; readonly fingerprint: string }
|
|
235
|
+
| { readonly kind: "unknown"; readonly present: boolean; readonly reason: "manifest-read" | "manifest-schema" | "manifest-foreign" };
|
|
236
|
+
|
|
237
|
+
let afterNoopPendingCountForTests: (() => void) | undefined;
|
|
238
|
+
|
|
239
|
+
/** Test seam: runs after the pending count and before stability validation. */
|
|
240
|
+
export function setAfterNoopPendingCountForTests(hook: (() => void) | undefined): void {
|
|
241
|
+
afterNoopPendingCountForTests = hook;
|
|
242
|
+
}
|
|
243
|
+
|
|
192
244
|
interface NativeRestoreTarget {
|
|
193
245
|
modelProvider: string;
|
|
194
246
|
source: string;
|
|
@@ -201,6 +253,65 @@ function samePath(a: string, b: string): boolean {
|
|
|
201
253
|
return process.platform === "win32" ? left.toLowerCase() === right.toLowerCase() : left === right;
|
|
202
254
|
}
|
|
203
255
|
|
|
256
|
+
function inspectBackupForNoop(path: string, stateDbPath: string): StrictBackupInspection {
|
|
257
|
+
if (!existsSync(path)) return { kind: "known", present: false, entries: 0, fingerprint: "absent" };
|
|
258
|
+
let parsed: unknown;
|
|
259
|
+
let raw: string;
|
|
260
|
+
try {
|
|
261
|
+
raw = readFileSync(path, "utf8");
|
|
262
|
+
parsed = JSON.parse(raw);
|
|
263
|
+
} catch {
|
|
264
|
+
return { kind: "unknown", present: true, reason: "manifest-read" };
|
|
265
|
+
}
|
|
266
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
267
|
+
return { kind: "unknown", present: true, reason: "manifest-schema" };
|
|
268
|
+
}
|
|
269
|
+
const manifest = parsed as Partial<BackupManifest>;
|
|
270
|
+
if (manifest.version !== 1 || typeof manifest.stateDbPath !== "string") {
|
|
271
|
+
return { kind: "unknown", present: true, reason: "manifest-schema" };
|
|
272
|
+
}
|
|
273
|
+
if (!samePath(manifest.stateDbPath, stateDbPath)) {
|
|
274
|
+
return { kind: "unknown", present: true, reason: "manifest-foreign" };
|
|
275
|
+
}
|
|
276
|
+
if (!manifest.entries || typeof manifest.entries !== "object" || Array.isArray(manifest.entries)) {
|
|
277
|
+
return { kind: "unknown", present: true, reason: "manifest-schema" };
|
|
278
|
+
}
|
|
279
|
+
for (const [id, value] of Object.entries(manifest.entries)) {
|
|
280
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
281
|
+
return { kind: "unknown", present: true, reason: "manifest-schema" };
|
|
282
|
+
}
|
|
283
|
+
const entry = value as Partial<BackupEntry>;
|
|
284
|
+
if (entry.id !== id
|
|
285
|
+
|| typeof entry.rolloutPath !== "string"
|
|
286
|
+
|| typeof entry.modelProvider !== "string"
|
|
287
|
+
|| typeof entry.source !== "string"
|
|
288
|
+
|| typeof entry.hasUserEvent !== "number") {
|
|
289
|
+
return { kind: "unknown", present: true, reason: "manifest-schema" };
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
kind: "known",
|
|
294
|
+
present: true,
|
|
295
|
+
entries: Object.keys(manifest.entries).length,
|
|
296
|
+
fingerprint: createHash("sha256").update(raw).digest("hex"),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function historyFileIdentity(path: string): string | null {
|
|
301
|
+
try {
|
|
302
|
+
const stat = statSync(path);
|
|
303
|
+
return [stat.dev, stat.ino, stat.size, stat.mtimeMs, stat.ctimeMs].join(":");
|
|
304
|
+
} catch {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function readHistoryDataVersion(db: Database): number | null {
|
|
310
|
+
const row = db.query<{ data_version: number }, []>("PRAGMA data_version").get();
|
|
311
|
+
const value = row?.data_version;
|
|
312
|
+
return typeof value === "number" && Number.isSafeInteger(value) ? value : null;
|
|
313
|
+
}
|
|
314
|
+
|
|
204
315
|
function readBackup(path: string, stateDbPath?: string): BackupManifest {
|
|
205
316
|
if (!existsSync(path)) return { version: 1, stateDbPath, entries: {} };
|
|
206
317
|
try {
|
|
@@ -508,19 +619,24 @@ function ejectRemainingOpencodexHistory(db: Database): { rows: number; files: nu
|
|
|
508
619
|
return { rows: rows.length, files };
|
|
509
620
|
}
|
|
510
621
|
|
|
511
|
-
export function
|
|
622
|
+
export function classifyRecoverableHistoryError(error: unknown): CodexHistoryFailureReason | null {
|
|
512
623
|
const code = typeof error === "object" && error && "code" in error ? String((error as { code?: unknown }).code) : "";
|
|
513
624
|
const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
|
|
514
|
-
|
|
625
|
+
if (code === "SQLITE_BUSY"
|
|
515
626
|
|| code === "SQLITE_LOCKED"
|
|
516
627
|
|| code === "EBUSY"
|
|
517
|
-
|| code === "EPERM"
|
|
518
|
-
|| code === "EACCES"
|
|
519
628
|
|| message.includes("database is locked")
|
|
520
629
|
|| message.includes("database is busy")
|
|
521
|
-
|| message.includes("resource busy")
|
|
630
|
+
|| message.includes("resource busy")) return "busy";
|
|
631
|
+
if (code === "EPERM"
|
|
632
|
+
|| code === "EACCES"
|
|
522
633
|
|| message.includes("operation not permitted")
|
|
523
|
-
|| message.includes("permission denied");
|
|
634
|
+
|| message.includes("permission denied")) return "permission";
|
|
635
|
+
return null;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
export function isRecoverableHistoryError(error: unknown): boolean {
|
|
639
|
+
return classifyRecoverableHistoryError(error) !== null;
|
|
524
640
|
}
|
|
525
641
|
|
|
526
642
|
const HISTORY_RETRY_DELAY_MS = 500;
|
|
@@ -533,21 +649,29 @@ const HISTORY_RETRY_ATTEMPTS = 2;
|
|
|
533
649
|
* error — callers surface that as `failed: true` instead of a silent no-op. Hard errors
|
|
534
650
|
* (corruption, programming bugs) still throw.
|
|
535
651
|
*/
|
|
536
|
-
|
|
652
|
+
function withHistoryRetryResult<T>(fn: () => T, io: { sleepFn?: (ms: number) => void; attempts?: number; delayMs?: number } = {}):
|
|
653
|
+
| { ok: true; value: T }
|
|
654
|
+
| { ok: false; reason: CodexHistoryFailureReason } {
|
|
537
655
|
const sleepFn = io.sleepFn ?? Bun.sleepSync;
|
|
538
656
|
const attempts = Math.max(1, io.attempts ?? HISTORY_RETRY_ATTEMPTS);
|
|
539
657
|
const delayMs = io.delayMs ?? HISTORY_RETRY_DELAY_MS;
|
|
540
658
|
for (let attempt = 0; ; attempt++) {
|
|
541
659
|
try {
|
|
542
|
-
return fn();
|
|
660
|
+
return { ok: true, value: fn() };
|
|
543
661
|
} catch (error) {
|
|
544
|
-
|
|
545
|
-
if (
|
|
662
|
+
const reason = classifyRecoverableHistoryError(error);
|
|
663
|
+
if (!reason) throw error;
|
|
664
|
+
if (attempt >= attempts - 1) return { ok: false, reason };
|
|
546
665
|
try { sleepFn(delayMs); } catch { /* sleep is best-effort */ }
|
|
547
666
|
}
|
|
548
667
|
}
|
|
549
668
|
}
|
|
550
669
|
|
|
670
|
+
export function withHistoryRetry<T>(fn: () => T, io: { sleepFn?: (ms: number) => void; attempts?: number; delayMs?: number } = {}): T | null {
|
|
671
|
+
const result = withHistoryRetryResult(fn, io);
|
|
672
|
+
return result.ok ? result.value : null;
|
|
673
|
+
}
|
|
674
|
+
|
|
551
675
|
/**
|
|
552
676
|
* True when a READONLY probe proves the openai-direction restore would be a no-op:
|
|
553
677
|
* zero threads still tagged opencodex AND an empty backup manifest. Used to skip the
|
|
@@ -564,8 +688,8 @@ function openaiRestoreIsNoop(stateDbPath: string, backupPath: string): boolean {
|
|
|
564
688
|
|
|
565
689
|
export function syncCodexHistoryProvider(
|
|
566
690
|
provider: CodexHistoryProvider,
|
|
567
|
-
stateDbPath =
|
|
568
|
-
backupPath =
|
|
691
|
+
stateDbPath = resolveCodexStateDbPath(),
|
|
692
|
+
backupPath = historyBackupPathFor(stateDbPath),
|
|
569
693
|
opts: { skipWhenProvablyNoop?: boolean } = {},
|
|
570
694
|
): CodexHistorySyncResult {
|
|
571
695
|
// Opt-in steady-state gate (Design B loopback callers only): default semantics of
|
|
@@ -574,8 +698,8 @@ export function syncCodexHistoryProvider(
|
|
|
574
698
|
&& openaiRestoreIsNoop(stateDbPath, backupPath)) {
|
|
575
699
|
return { rows: 0, files: 0 };
|
|
576
700
|
}
|
|
577
|
-
|
|
578
|
-
|
|
701
|
+
const retried = withHistoryRetryResult(() => syncCodexHistoryProviderUnsafe(provider, stateDbPath, backupPath));
|
|
702
|
+
return retried.ok ? retried.value : { rows: 0, files: 0, failed: true, failureReason: retried.reason };
|
|
579
703
|
}
|
|
580
704
|
|
|
581
705
|
function syncCodexHistoryProviderUnsafe(provider: CodexHistoryProvider, stateDbPath: string, backupPath: string): CodexHistorySyncResult {
|
|
@@ -698,16 +822,17 @@ function restoreCodexHistoryProvider(stateDbPath: string, backupPath: string): C
|
|
|
698
822
|
}
|
|
699
823
|
}
|
|
700
824
|
|
|
701
|
-
export function restoreLegacyOpenaiHistory(stateDbPath =
|
|
825
|
+
export function restoreLegacyOpenaiHistory(stateDbPath = resolveCodexStateDbPath()): CodexHistorySyncResult {
|
|
702
826
|
if (!existsSync(stateDbPath)) return { rows: 0, files: 0 };
|
|
703
|
-
|
|
827
|
+
const retried = withHistoryRetryResult(() => {
|
|
704
828
|
const db = openStateDb(stateDbPath);
|
|
705
829
|
try {
|
|
706
830
|
return ejectRemainingOpencodexHistory(db);
|
|
707
831
|
} finally {
|
|
708
832
|
db.close();
|
|
709
833
|
}
|
|
710
|
-
})
|
|
834
|
+
});
|
|
835
|
+
return retried.ok ? retried.value : { rows: 0, files: 0, failed: true, failureReason: retried.reason };
|
|
711
836
|
}
|
|
712
837
|
|
|
713
838
|
/**
|
|
@@ -717,8 +842,8 @@ export function restoreLegacyOpenaiHistory(stateDbPath = STATE_DB_PATH): { rows:
|
|
|
717
842
|
* per tick so a locked DB never stalls the event loop beyond one sqlite busy wait.
|
|
718
843
|
*/
|
|
719
844
|
export function migrateHistoryToOpenai(
|
|
720
|
-
stateDbPath =
|
|
721
|
-
backupPath =
|
|
845
|
+
stateDbPath = resolveCodexStateDbPath(),
|
|
846
|
+
backupPath = historyBackupPathFor(stateDbPath),
|
|
722
847
|
opts: { attempts?: number; delayMs?: number; sleepFn?: (ms: number) => void } = {},
|
|
723
848
|
): CodexHistorySyncResult {
|
|
724
849
|
if (!existsSync(stateDbPath)) return { rows: 0, files: 0 };
|
|
@@ -727,8 +852,83 @@ export function migrateHistoryToOpenai(
|
|
|
727
852
|
// nothing. A missing DB with a leftover backup manifest does NOT satisfy the gate
|
|
728
853
|
// (backupEntries > 0), so the guardian's fresh-reinstall re-count protection holds.
|
|
729
854
|
if (openaiRestoreIsNoop(stateDbPath, backupPath)) return { rows: 0, files: 0 };
|
|
730
|
-
|
|
731
|
-
|
|
855
|
+
const retried = withHistoryRetryResult(() => syncCodexHistoryProviderUnsafe("openai", stateDbPath, backupPath), opts);
|
|
856
|
+
return retried.ok ? retried.value : { rows: 0, files: 0, failed: true, failureReason: retried.reason };
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* Captures no-op evidence while the caller holds the history serialization
|
|
861
|
+
* lock H. This function does not acquire H itself. Unknown or foreign backup
|
|
862
|
+
* state is never collapsed into an empty manifest.
|
|
863
|
+
*/
|
|
864
|
+
export function snapshotCodexHistoryNoop(
|
|
865
|
+
stateDbPath: string,
|
|
866
|
+
backupPath: string,
|
|
867
|
+
): CodexHistoryNoopSnapshot {
|
|
868
|
+
const canonicalStateDbPath = resolve(stateDbPath);
|
|
869
|
+
const canonicalBackupPath = resolve(backupPath);
|
|
870
|
+
const stateDbPresent = existsSync(stateDbPath);
|
|
871
|
+
const backupPresent = existsSync(backupPath);
|
|
872
|
+
const base = { canonicalStateDbPath, stateDbPresent, canonicalBackupPath, backupPresent };
|
|
873
|
+
if (!samePath(backupPath, historyBackupPathFor(stateDbPath))) {
|
|
874
|
+
return { kind: "unknown", pendingRows: null, backupEntries: null, ...base, reason: "backup-path" };
|
|
875
|
+
}
|
|
876
|
+
const backup = inspectBackupForNoop(backupPath, stateDbPath);
|
|
877
|
+
if (backup.kind === "unknown") {
|
|
878
|
+
return { kind: "unknown", pendingRows: null, backupEntries: null, ...base, reason: backup.reason };
|
|
879
|
+
}
|
|
880
|
+
if (!stateDbPresent) {
|
|
881
|
+
return backup.entries > 0
|
|
882
|
+
? { kind: "work-pending", pendingRows: 0, backupEntries: backup.entries, ...base }
|
|
883
|
+
: { kind: "unknown", pendingRows: null, backupEntries: null, ...base, reason: "database-absent" };
|
|
884
|
+
}
|
|
885
|
+
const stateDbIdentity = historyFileIdentity(stateDbPath);
|
|
886
|
+
if (stateDbIdentity === null) {
|
|
887
|
+
return { kind: "unknown", pendingRows: null, backupEntries: null, ...base, reason: "snapshot-race" };
|
|
888
|
+
}
|
|
889
|
+
let monitor: Database | undefined;
|
|
890
|
+
try {
|
|
891
|
+
monitor = new Database(stateDbPath, { readonly: true });
|
|
892
|
+
monitor.exec("PRAGMA busy_timeout = 100");
|
|
893
|
+
const dataVersionBefore = readHistoryDataVersion(monitor);
|
|
894
|
+
if (dataVersionBefore === null) {
|
|
895
|
+
return { kind: "unknown", pendingRows: null, backupEntries: null, ...base, reason: "database-query" };
|
|
896
|
+
}
|
|
897
|
+
const pending = countPendingOpencodexHistory(stateDbPath, backupPath);
|
|
898
|
+
if (pending.failed) {
|
|
899
|
+
return { kind: "unknown", pendingRows: null, backupEntries: null, ...base, reason: "database-query" };
|
|
900
|
+
}
|
|
901
|
+
afterNoopPendingCountForTests?.();
|
|
902
|
+
const backupAfter = inspectBackupForNoop(backupPath, stateDbPath);
|
|
903
|
+
if (backupAfter.kind === "unknown") {
|
|
904
|
+
return { kind: "unknown", pendingRows: null, backupEntries: null, ...base, reason: backupAfter.reason };
|
|
905
|
+
}
|
|
906
|
+
const dataVersionAfter = readHistoryDataVersion(monitor);
|
|
907
|
+
if (dataVersionAfter === null) {
|
|
908
|
+
return { kind: "unknown", pendingRows: null, backupEntries: null, ...base, reason: "database-query" };
|
|
909
|
+
}
|
|
910
|
+
if (dataVersionAfter !== dataVersionBefore
|
|
911
|
+
|| pending.backupEntries !== backup.entries
|
|
912
|
+
|| backupAfter.entries !== backup.entries
|
|
913
|
+
|| backupAfter.present !== backup.present
|
|
914
|
+
|| backupAfter.fingerprint !== backup.fingerprint
|
|
915
|
+
|| historyFileIdentity(stateDbPath) !== stateDbIdentity
|
|
916
|
+
|| existsSync(stateDbPath) !== stateDbPresent
|
|
917
|
+
|| existsSync(backupPath) !== backupPresent) {
|
|
918
|
+
return { kind: "unknown", pendingRows: null, backupEntries: null, ...base, reason: "snapshot-race" };
|
|
919
|
+
}
|
|
920
|
+
return pending.pendingRows === 0 && backup.entries === 0
|
|
921
|
+
? { kind: "verified-noop", pendingRows: 0, backupEntries: 0, ...base, stateDbPresent: true }
|
|
922
|
+
: { kind: "work-pending", pendingRows: pending.pendingRows, backupEntries: backup.entries, ...base };
|
|
923
|
+
} catch {
|
|
924
|
+
return { kind: "unknown", pendingRows: null, backupEntries: null, ...base, reason: "database-query" };
|
|
925
|
+
} finally {
|
|
926
|
+
try {
|
|
927
|
+
monitor?.close();
|
|
928
|
+
} catch {
|
|
929
|
+
// Read-only monitor cleanup cannot make an uncertain snapshot authoritative.
|
|
930
|
+
}
|
|
931
|
+
}
|
|
732
932
|
}
|
|
733
933
|
|
|
734
934
|
export interface PendingHistoryCount {
|
|
@@ -746,7 +946,10 @@ export interface PendingHistoryCount {
|
|
|
746
946
|
* pending predicate mirrors ejectRemainingOpencodexHistory exactly — rows eject ignores
|
|
747
947
|
* (empty first_user_message) are not counted, so 0 really means "migration done".
|
|
748
948
|
*/
|
|
749
|
-
export function countPendingOpencodexHistory(
|
|
949
|
+
export function countPendingOpencodexHistory(
|
|
950
|
+
stateDbPath = resolveCodexStateDbPath(),
|
|
951
|
+
backupPath = historyBackupPathFor(stateDbPath),
|
|
952
|
+
): PendingHistoryCount {
|
|
750
953
|
let backupEntries = 0;
|
|
751
954
|
try {
|
|
752
955
|
const manifest = readBackup(backupPath, stateDbPath);
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the transition a history job belongs to.
|
|
3
|
+
*
|
|
4
|
+
* `updateCodexHistoryTransition` had no production caller, so every completed or
|
|
5
|
+
* skipped job left the coordinator row permanently `pending` — a transition was
|
|
6
|
+
* published and never resolved. This is that caller.
|
|
7
|
+
*
|
|
8
|
+
* The classification is `020_history_isolation.md:564-572`, applied rather than
|
|
9
|
+
* reinvented. The two unions do not line up one-to-one, so each outcome is
|
|
10
|
+
* mapped by hand: a cast across them would compile on the words they share and
|
|
11
|
+
* lie about the rest.
|
|
12
|
+
*/
|
|
13
|
+
import type { CodexHistoryJobOutcome } from "./history-job";
|
|
14
|
+
import type { CodexHistoryState, CodexTransitionVersion } from "./convergence-types";
|
|
15
|
+
import { updateCodexHistoryTransition } from "./transition-state";
|
|
16
|
+
|
|
17
|
+
/** The retry budget for a contended terminal CAS. Bounded; never unbounded. */
|
|
18
|
+
const TERMINAL_RETRY_ATTEMPTS = 3;
|
|
19
|
+
const TERMINAL_RETRY_DELAY_MS = 250;
|
|
20
|
+
|
|
21
|
+
function sleep(ms: number): void {
|
|
22
|
+
// The caller path here is synchronous after the awaited job, so a spin is the
|
|
23
|
+
// honest tool — awaiting would be, and this is short.
|
|
24
|
+
const until = Date.now() + ms;
|
|
25
|
+
while (Date.now() < until) { /* bounded */ }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function classify(outcome: CodexHistoryJobOutcome, txId: string | null): CodexHistoryState {
|
|
29
|
+
switch (outcome.kind) {
|
|
30
|
+
case "converged":
|
|
31
|
+
return {
|
|
32
|
+
status: "converged",
|
|
33
|
+
attempts: 1,
|
|
34
|
+
nextRetryAt: null,
|
|
35
|
+
txId,
|
|
36
|
+
// A zero is durable only when the worker proved the exact DB/manifest
|
|
37
|
+
// state while H was held. Without proof, keep the counts unknown. Keep
|
|
38
|
+
// `??`: `||` would discard a verified zero.
|
|
39
|
+
pendingRows: outcome.proof?.pendingRows ?? null,
|
|
40
|
+
backupEntries: outcome.proof?.backupEntries ?? null,
|
|
41
|
+
};
|
|
42
|
+
case "skipped":
|
|
43
|
+
// The user opting out is a completed decision, not a failure — converged
|
|
44
|
+
// with no reason. Marking it blocked would retry what they asked not to do.
|
|
45
|
+
return { status: "converged", attempts: 0, nextRetryAt: null, txId, pendingRows: null, backupEntries: null };
|
|
46
|
+
case "blocked":
|
|
47
|
+
return {
|
|
48
|
+
status: outcome.reason === "busy" ? "pending" : "blocked",
|
|
49
|
+
reason: outcome.reason === "busy" ? "db-busy"
|
|
50
|
+
: outcome.reason === "database" ? "unreadable"
|
|
51
|
+
: "permission",
|
|
52
|
+
attempts: 1,
|
|
53
|
+
// A busy unit retries; the others do not reschedule themselves.
|
|
54
|
+
nextRetryAt: outcome.reason === "busy"
|
|
55
|
+
? new Date(Date.now() + TERMINAL_RETRY_DELAY_MS * 10).toISOString()
|
|
56
|
+
: null,
|
|
57
|
+
txId,
|
|
58
|
+
pendingRows: null,
|
|
59
|
+
backupEntries: null,
|
|
60
|
+
};
|
|
61
|
+
case "failed":
|
|
62
|
+
return {
|
|
63
|
+
status: "unknown",
|
|
64
|
+
reason: outcome.reason === "timeout" ? "timeout"
|
|
65
|
+
: outcome.reason === "worker-died" ? "worker-died"
|
|
66
|
+
: "record-write-failed",
|
|
67
|
+
attempts: 1,
|
|
68
|
+
nextRetryAt: null,
|
|
69
|
+
txId,
|
|
70
|
+
pendingRows: null,
|
|
71
|
+
backupEntries: null,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Publish the terminal state of a history job against the transition it belongs
|
|
78
|
+
* to. A `conflict` means a newer transition won and is deliberately left alone.
|
|
79
|
+
* A `busy` terminal CAS retries a bounded number of times; when that exhausts,
|
|
80
|
+
* the previously persisted `pending` schedule is left intact — the same update
|
|
81
|
+
* needs the lock that was busy, so it cannot record its own failure
|
|
82
|
+
* (`005_contract.md:277`), and the retry being out of attempts is itself a
|
|
83
|
+
* terminal observation.
|
|
84
|
+
*/
|
|
85
|
+
export function resolveCodexHistoryTransition(
|
|
86
|
+
receipt: CodexTransitionVersion,
|
|
87
|
+
outcome: CodexHistoryJobOutcome,
|
|
88
|
+
): void {
|
|
89
|
+
const state = classify(outcome, receipt.currentTxId);
|
|
90
|
+
for (let attempt = 0; attempt < TERMINAL_RETRY_ATTEMPTS; attempt += 1) {
|
|
91
|
+
const result = updateCodexHistoryTransition(receipt, state);
|
|
92
|
+
if (result.kind === "updated") return;
|
|
93
|
+
if (result.kind === "conflict") {
|
|
94
|
+
// A newer transition already owns the row. Overwriting it would be the
|
|
95
|
+
// overtaken job overwriting the winner.
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (result.reason === "busy") {
|
|
99
|
+
if (attempt + 1 < TERMINAL_RETRY_ATTEMPTS) sleep(TERMINAL_RETRY_DELAY_MS * (attempt + 1));
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
// database / unsafe-path: retried CAS will not help.
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|