@iislee/opencodex 2.11.0 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS_INSTALL.md +109 -0
- package/README.md +117 -22
- package/bin/ocx.mjs +245 -88
- package/bin/package-main.mjs +1 -1
- package/gui/dist/assets/index-Be1sDpWw.css +1 -0
- package/gui/dist/assets/index-D4OKgUV4.js +114 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/alibaba-color.svg +1 -1
- package/gui/dist/provider-icons/antigravity-color.svg +1 -1
- package/gui/dist/provider-icons/claude-color.svg +1 -1
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -1
- package/gui/dist/provider-icons/cursor-color.svg +1 -1
- package/gui/dist/provider-icons/deepseek-color.svg +1 -1
- package/gui/dist/provider-icons/firepass-color.svg +1 -1
- package/gui/dist/provider-icons/fireworks-color.svg +1 -1
- package/gui/dist/provider-icons/gemini-color.svg +1 -1
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
- package/gui/dist/provider-icons/grok.svg +1 -1
- package/gui/dist/provider-icons/groq-color.svg +1 -1
- package/gui/dist/provider-icons/huggingface-color.svg +1 -1
- package/gui/dist/provider-icons/kimi-color.svg +1 -1
- package/gui/dist/provider-icons/kiro-color.svg +2 -2
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
- package/gui/dist/provider-icons/mistral-color.svg +1 -1
- package/gui/dist/provider-icons/moonshot-color.svg +1 -1
- package/gui/dist/provider-icons/nvidia-color.svg +1 -1
- package/gui/dist/provider-icons/ollama-color.svg +1 -1
- package/gui/dist/provider-icons/openai.svg +1 -1
- package/gui/dist/provider-icons/opencode.svg +2 -1
- package/gui/dist/provider-icons/openrouter-color.svg +1 -1
- package/gui/dist/provider-icons/pi.svg +2 -2
- package/gui/dist/provider-icons/qianfan-color.svg +1 -1
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/vllm-color.svg +1 -1
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
- package/package.json +21 -10
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +475 -62
- package/src/adapters/base.ts +82 -7
- package/src/adapters/client-fingerprint.ts +18 -12
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +637 -0
- package/src/adapters/cursor/call-id.ts +44 -0
- package/src/adapters/cursor/catalog.ts +541 -0
- package/src/adapters/cursor/checkpoint-store.ts +308 -0
- package/src/adapters/cursor/cursor-errors.ts +144 -6
- package/src/adapters/cursor/discovery.ts +122 -14
- package/src/adapters/cursor/effort-map.ts +106 -4
- package/src/adapters/cursor/envelope-echo.ts +290 -0
- package/src/adapters/cursor/framing.ts +39 -0
- package/src/adapters/cursor/h2-pool.ts +123 -0
- package/src/adapters/cursor/http1-bidi.ts +361 -0
- package/src/adapters/cursor/images.ts +704 -0
- package/src/adapters/cursor/live-models.ts +180 -59
- package/src/adapters/cursor/live-transport.ts +623 -170
- package/src/adapters/cursor/message-mapper.ts +4 -1
- package/src/adapters/cursor/native-exec-common.ts +23 -2
- package/src/adapters/cursor/native-exec-desktop.ts +23 -0
- package/src/adapters/cursor/native-exec-fs.ts +10 -7
- package/src/adapters/cursor/native-exec-network.ts +1 -1
- package/src/adapters/cursor/native-exec-shell.ts +5 -3
- package/src/adapters/cursor/native-exec.ts +121 -14
- package/src/adapters/cursor/protobuf-events.ts +829 -11
- package/src/adapters/cursor/protobuf-request.ts +447 -75
- package/src/adapters/cursor/request-builder.ts +271 -35
- package/src/adapters/cursor/tool-definitions.ts +252 -12
- package/src/adapters/cursor/tool-result-normalize.ts +115 -0
- package/src/adapters/cursor/transport.ts +22 -0
- package/src/adapters/cursor/types.ts +48 -1
- package/src/adapters/cursor.ts +336 -39
- package/src/adapters/exec-tool-result-normalize.ts +99 -0
- package/src/adapters/google-antigravity-replay.ts +713 -41
- package/src/adapters/google-antigravity-wire.ts +48 -10
- package/src/adapters/google-errors.ts +44 -12
- package/src/adapters/google-http.ts +38 -10
- package/src/adapters/google-tool-schema.ts +80 -15
- package/src/adapters/google-truncation.ts +11 -0
- package/src/adapters/google.ts +742 -86
- package/src/adapters/identity.ts +39 -6
- package/src/adapters/image.ts +1 -1
- package/src/adapters/kiro-constants.ts +27 -0
- package/src/adapters/kiro-errors.ts +11 -0
- package/src/adapters/kiro-events.ts +19 -1
- package/src/adapters/kiro-thinking.ts +18 -2
- package/src/adapters/kiro-tools.ts +65 -17
- package/src/adapters/kiro.ts +270 -73
- package/src/adapters/mimo-free.ts +17 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1377 -344
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +1164 -64
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/run-turn-queue.ts +36 -1
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +105 -21
- package/src/adapters/xai-tool-schema.ts +436 -0
- package/src/adapters/xai-web-search.ts +186 -0
- package/src/bridge.ts +512 -92
- package/src/chat/inbound.ts +57 -20
- package/src/chat/outbound.ts +97 -33
- package/src/claude/agents-inject.ts +40 -10
- package/src/claude/context-windows.ts +37 -14
- package/src/claude/desktop-3p.ts +243 -9
- package/src/claude/gateway-cache.ts +41 -4
- package/src/claude/inbound.ts +72 -3
- package/src/claude/model-info.ts +38 -15
- package/src/claude/outbound.ts +88 -21
- package/src/cli/access.ts +46 -3
- package/src/cli/account-api.ts +150 -19
- package/src/cli/account-auth.ts +33 -6
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +648 -28
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +97 -19
- package/src/cli/agent.ts +53 -2
- package/src/cli/alias.ts +66 -0
- package/src/cli/capabilities-command.ts +94 -0
- package/src/cli/capabilities.ts +496 -0
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +60 -15
- package/src/cli/claude.ts +129 -35
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +2 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +8 -0
- package/src/cli/config-command.ts +74 -10
- package/src/cli/dispatch.ts +821 -0
- package/src/cli/doctor.ts +440 -56
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +46 -20
- package/src/cli/help.ts +34 -274
- package/src/cli/index.ts +417 -528
- package/src/cli/init.ts +5 -17
- package/src/cli/inspect.ts +230 -0
- package/src/cli/integrations.ts +120 -2
- package/src/cli/lab.ts +607 -0
- package/src/cli/launcher-context.ts +77 -0
- package/src/cli/minimax.ts +497 -0
- package/src/cli/models-runtime.ts +130 -2
- package/src/cli/models.ts +118 -16
- package/src/cli/observe.ts +123 -11
- package/src/cli/opencode.ts +4 -2
- package/src/cli/provider-runtime.ts +34 -3
- package/src/cli/provider.ts +25 -3
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +476 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +57 -10
- package/src/cli/star-prompt.ts +71 -15
- package/src/cli/status.ts +51 -4
- package/src/cli/storage.ts +234 -0
- package/src/cli/system-command.ts +16 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +153 -6
- package/src/cli/usage-report.ts +184 -0
- package/src/cli/v2.ts +137 -18
- package/src/cli/version-skew.ts +46 -0
- package/src/cli.ts +1 -1
- package/src/clients/config-export.ts +1442 -23
- package/src/clients/effective-status.ts +30 -2
- package/src/clients/probes/cline.ts +81 -0
- package/src/codex/account-label.ts +35 -1
- package/src/codex/account-lifecycle.ts +130 -13
- package/src/codex/account-namespaces.ts +49 -3
- package/src/codex/account-pause.ts +2 -1
- package/src/codex/account-priority.ts +84 -0
- package/src/codex/account-store.ts +29 -2
- package/src/codex/account-usability.ts +25 -2
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/app-server-processes.ts +570 -107
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +893 -246
- package/src/codex/auth-collision.ts +5 -3
- package/src/codex/auth-context.ts +348 -32
- package/src/codex/autostart-health.ts +24 -1
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +86 -10
- package/src/codex/catalog/bundled.ts +331 -33
- package/src/codex/catalog/effort.ts +138 -32
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +555 -45
- package/src/codex/catalog/native-models.ts +75 -0
- package/src/codex/catalog/parsing.ts +269 -30
- package/src/codex/catalog/provider-fetch.ts +1626 -144
- package/src/codex/catalog/sync.ts +1576 -187
- package/src/codex/catalog-admission.ts +199 -0
- package/src/codex/catalog-refresh-status.ts +105 -0
- package/src/codex/catalog-write-serialization.ts +242 -0
- package/src/codex/catalog.ts +6 -3
- package/src/codex/codex-write-lock.ts +386 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +676 -0
- package/src/codex/coordinator-doctor.ts +332 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/desktop-app-restart.ts +355 -0
- package/src/codex/features.ts +636 -39
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +436 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-manifest.ts +112 -0
- package/src/codex/history-migration-guardian.ts +30 -24
- package/src/codex/history-provider.ts +1016 -235
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +223 -0
- package/src/codex/inject-coordination.ts +373 -0
- package/src/codex/inject.ts +1114 -152
- package/src/codex/injected-marker.ts +37 -3
- package/src/codex/integration-record.ts +266 -0
- package/src/codex/internal/catalog-writer.ts +203 -0
- package/src/codex/internal/history-writer.ts +81 -0
- package/src/codex/journal.ts +66 -4
- package/src/codex/log-guard/inspect.ts +524 -0
- package/src/codex/log-guard/lock.ts +150 -0
- package/src/codex/log-guard/maintenance.ts +403 -0
- package/src/codex/log-guard/path-safety.ts +88 -0
- package/src/codex/log-guard/policy.ts +44 -0
- package/src/codex/log-guard/processes.ts +205 -0
- package/src/codex/log-guard/protection.ts +489 -0
- package/src/codex/log-guard/sqlite-errors.ts +9 -0
- package/src/codex/main-account-cache.ts +24 -0
- package/src/codex/main-account.ts +29 -1
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +56 -10
- package/src/codex/model-entitlements.ts +360 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +178 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +622 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +675 -0
- package/src/codex/paths.ts +80 -1
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +1 -1
- package/src/codex/pool-rotation.ts +74 -4
- package/src/codex/project-config-warnings.ts +20 -6
- package/src/codex/prompt-journal.ts +352 -0
- package/src/codex/prompt-layers.ts +1313 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/prompt-text-probe.ts +238 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +264 -21
- package/src/codex/refresh.ts +11 -2
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +514 -94
- package/src/codex/runtime.ts +159 -38
- package/src/codex/shim.ts +1065 -31
- package/src/codex/subagent-model-fallback.ts +437 -43
- package/src/codex/sync.ts +191 -2
- package/src/codex/transition-state.ts +720 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +557 -0
- package/src/codex/warmup.ts +187 -81
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +47 -0
- package/src/combos/index.ts +4 -0
- package/src/combos/request.ts +32 -0
- package/src/combos/types.ts +91 -9
- package/src/compatibility/index.ts +26 -0
- package/src/compatibility/manifest.ts +253 -0
- package/src/compatibility/openai-responses.ts +121 -0
- package/src/config/atomic-write.ts +219 -0
- package/src/config/paths.ts +40 -0
- package/src/config/process-state.ts +309 -0
- package/src/config/provider-name.ts +24 -0
- package/src/config/provider-validation.ts +177 -0
- package/src/config/rebase-provenance.ts +68 -0
- package/src/config.ts +1713 -709
- package/src/generated/compatibility-version.json +3324 -0
- package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
- package/src/grok/inject.ts +16 -5
- package/src/grok/inspect.ts +45 -0
- package/src/grok/sync.ts +2 -2
- package/src/images/loop.ts +157 -33
- package/src/images/plan.ts +24 -13
- package/src/integrations/config-io.ts +269 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/mutation-flight.ts +71 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/omp-yaml-source.ts +358 -0
- package/src/integrations/owned-refresh.ts +74 -0
- package/src/integrations/ownership-policy.ts +160 -0
- package/src/integrations/ownership.ts +155 -0
- package/src/integrations/registry.ts +166 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +433 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +715 -0
- package/src/lab/artifacts/sanitize.ts +586 -0
- package/src/lab/artifacts/secure-fs.ts +475 -0
- package/src/lab/artifacts/store.ts +310 -0
- package/src/lab/automation/budgets.ts +78 -0
- package/src/lab/automation/config-persistence.ts +256 -0
- package/src/lab/automation/constants.ts +39 -0
- package/src/lab/automation/cooldown.ts +103 -0
- package/src/lab/automation/dispatch.ts +211 -0
- package/src/lab/automation/index.ts +13 -0
- package/src/lab/automation/orchestrator.ts +499 -0
- package/src/lab/automation/persistence.ts +512 -0
- package/src/lab/automation/planner.ts +371 -0
- package/src/lab/automation/policy.ts +136 -0
- package/src/lab/automation/queue.ts +191 -0
- package/src/lab/automation/recovery.ts +24 -0
- package/src/lab/automation/route-context.ts +21 -0
- package/src/lab/automation/run-key.ts +44 -0
- package/src/lab/automation/runs-query.ts +34 -0
- package/src/lab/automation/types.ts +160 -0
- package/src/lab/conformance/assertion.ts +325 -0
- package/src/lab/conformance/digest.ts +22 -0
- package/src/lab/conformance/executor.ts +741 -0
- package/src/lab/conformance/fixture-provider.ts +27 -0
- package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
- package/src/lab/conformance/harness-budget.ts +47 -0
- package/src/lab/conformance/index.ts +5 -0
- package/src/lab/conformance/jcs.ts +64 -0
- package/src/lab/conformance/json-pointer.ts +39 -0
- package/src/lab/conformance/manifest.ts +180 -0
- package/src/lab/conformance/mcp-stub.ts +179 -0
- package/src/lab/conformance/negative-controls.ts +164 -0
- package/src/lab/conformance/observation.ts +355 -0
- package/src/lab/conformance/runner.ts +68 -0
- package/src/lab/conformance/sse-normalize.ts +59 -0
- package/src/lab/conformance/suite-manifest.ts +78 -0
- package/src/lab/conformance/types.ts +214 -0
- package/src/lab/constants.ts +126 -0
- package/src/lab/digest.ts +64 -0
- package/src/lab/events/errors.ts +9 -0
- package/src/lab/events/limits.ts +117 -0
- package/src/lab/events/types.ts +229 -0
- package/src/lab/events/validate.ts +781 -0
- package/src/lab/fabric/constants.ts +40 -0
- package/src/lab/fabric/executor.ts +492 -0
- package/src/lab/fabric/index.ts +80 -0
- package/src/lab/fabric/manifest.ts +222 -0
- package/src/lab/fabric/observe.ts +489 -0
- package/src/lab/fabric/patch.ts +79 -0
- package/src/lab/fabric/producer-child.ts +139 -0
- package/src/lab/fabric/producer-isolate.ts +276 -0
- package/src/lab/fabric/producer-protocol.ts +61 -0
- package/src/lab/fabric/scratch.ts +439 -0
- package/src/lab/fabric/subject.ts +106 -0
- package/src/lab/fabric/types.ts +134 -0
- package/src/lab/fabric/verifier.ts +98 -0
- package/src/lab/index.ts +54 -0
- package/src/lab/ledger/artifact-refs.ts +127 -0
- package/src/lab/ledger/invalidation.ts +136 -0
- package/src/lab/ledger/purge.ts +310 -0
- package/src/lab/ledger/store.ts +532 -0
- package/src/lab/live/credential-lease.ts +53 -0
- package/src/lab/live/destination.ts +155 -0
- package/src/lab/live/executor.ts +336 -0
- package/src/lab/live/inert-tools.ts +56 -0
- package/src/lab/live/manifest.ts +85 -0
- package/src/lab/live/mcp-loopback.ts +57 -0
- package/src/lab/live/runner.ts +19 -0
- package/src/lab/live/sandbox.ts +61 -0
- package/src/lab/live/suite-manifest.ts +41 -0
- package/src/lab/live/transport.ts +118 -0
- package/src/lab/live/types.ts +197 -0
- package/src/lab/observe/from-conformance.ts +301 -0
- package/src/lab/observe/from-live.ts +117 -0
- package/src/lab/paths.ts +153 -0
- package/src/lab/projection/rebuild.ts +495 -0
- package/src/lab/projection/schema.ts +135 -0
- package/src/lab/projection/verdicts.ts +474 -0
- package/src/lab/projection/verification.ts +412 -0
- package/src/lab/public/bundle.ts +217 -0
- package/src/lab/public/community-authority.ts +175 -0
- package/src/lab/public/community-files.ts +29 -0
- package/src/lab/public/community.ts +479 -0
- package/src/lab/public/file-safety.ts +155 -0
- package/src/lab/public/ids.ts +26 -0
- package/src/lab/public/index.ts +16 -0
- package/src/lab/public/mutation-lock.ts +424 -0
- package/src/lab/public/operator.ts +353 -0
- package/src/lab/public/origin-purge.ts +79 -0
- package/src/lab/public/origin.ts +203 -0
- package/src/lab/public/privacy.ts +143 -0
- package/src/lab/public/private-file.ts +261 -0
- package/src/lab/public/project.ts +124 -0
- package/src/lab/public/purge-test-fault.ts +21 -0
- package/src/lab/public/purge.ts +223 -0
- package/src/lab/public/registry.ts +44 -0
- package/src/lab/public/revocation.ts +252 -0
- package/src/lab/public/signature.ts +243 -0
- package/src/lab/public/storage.ts +105 -0
- package/src/lab/public/strict-json.ts +206 -0
- package/src/lab/public/time.ts +26 -0
- package/src/lab/public/types.ts +172 -0
- package/src/lab/public/validate.ts +391 -0
- package/src/lab/query/catalog.ts +101 -0
- package/src/lab/query/connection.ts +107 -0
- package/src/lab/query/constants.ts +4 -0
- package/src/lab/query/cursor.ts +132 -0
- package/src/lab/query/dto-map.ts +277 -0
- package/src/lab/query/errors.ts +22 -0
- package/src/lab/query/freshness.ts +53 -0
- package/src/lab/query/index.ts +45 -0
- package/src/lab/query/latest-observation.ts +59 -0
- package/src/lab/query/passive-production.ts +159 -0
- package/src/lab/query/queries.ts +444 -0
- package/src/lab/query/types.ts +266 -0
- package/src/lab/subject/behavior-fingerprint.ts +77 -0
- package/src/lab/subject/installation-salt.ts +112 -0
- package/src/lab/subject/protocol-subject.ts +80 -0
- package/src/lab/subject/route-subject.ts +74 -0
- package/src/lib/admin-secrets.ts +24 -0
- package/src/lib/app-owned-memory-stores.ts +22 -0
- package/src/lib/bounded-body.ts +167 -11
- package/src/lib/bun-runtime.ts +125 -12
- package/src/lib/bun-stream-caps.ts +13 -9
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +26 -2
- package/src/lib/destination-policy.ts +65 -1
- package/src/lib/errors.ts +80 -5
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/lab-activation.ts +223 -0
- package/src/lib/lab-live-execution-authority.ts +13 -0
- package/src/lib/lab-live-host.ts +30 -0
- package/src/lib/lab-live-pinned-sender.ts +56 -0
- package/src/lib/lab-live-route-production.ts +130 -0
- package/src/lib/lab-passive-linker-registration.ts +26 -0
- package/src/lib/local-management-attestation.ts +51 -0
- package/src/lib/local-management-capability.ts +100 -0
- package/src/lib/local-provider-reload-contract.ts +100 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/package-tree-integrity.ts +101 -0
- package/src/lib/pinned-http.ts +145 -26
- package/src/lib/process-control.ts +6 -2
- package/src/lib/provider-outbound.ts +49 -9
- package/src/lib/redact.ts +419 -3
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/service-secrets.ts +15 -0
- package/src/lib/shadow-call.ts +35 -4
- package/src/lib/sse-decoder.ts +41 -0
- package/src/lib/state-store-registrations.ts +10 -2
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/token-estimate.ts +19 -2
- package/src/lib/tool-argument-integers.ts +253 -0
- package/src/lib/translator-budget.ts +44 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +156 -3
- package/src/lib/windows-atomic-replace.ts +155 -0
- package/src/lib/windows-elevation.ts +70 -2
- package/src/lib/windows-secret-acl.ts +409 -69
- package/src/lib/windows-service-wrappers.ts +72 -0
- package/src/lib/windows-text.ts +106 -0
- package/src/lib/windows-user-principal.ts +341 -0
- package/src/lib/winsw.ts +33 -5
- package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
- package/src/oauth/account-import/index.ts +15 -0
- package/src/oauth/account-import/parser.ts +83 -0
- package/src/oauth/account-import/registry.ts +18 -0
- package/src/oauth/account-import/service.ts +75 -0
- package/src/oauth/account-import/types.ts +91 -0
- package/src/oauth/anthropic.ts +12 -1
- package/src/oauth/callback-server.ts +30 -4
- package/src/oauth/chatgpt.ts +12 -1
- package/src/oauth/cline.ts +203 -0
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +46 -5
- package/src/oauth/generic-account-failover.ts +231 -0
- package/src/oauth/google-antigravity.ts +35 -3
- package/src/oauth/health.ts +20 -12
- package/src/oauth/index.ts +462 -71
- package/src/oauth/key-providers.ts +25 -0
- package/src/oauth/kimi.ts +25 -3
- package/src/oauth/kiro.ts +95 -6
- package/src/oauth/local-token-detect.ts +13 -2
- package/src/oauth/log.ts +3 -1
- package/src/oauth/login-cli.ts +88 -28
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/open-browser-choice.ts +26 -0
- package/src/oauth/store.ts +133 -26
- package/src/oauth/token-guardian.ts +9 -3
- package/src/oauth/types.ts +15 -0
- package/src/pi/models.ts +2 -2
- package/src/providers/alibaba-region-migration.ts +1 -1
- package/src/providers/antigravity-models.ts +521 -31
- package/src/providers/auto-compact-budget.ts +65 -0
- package/src/providers/base-url-choices.ts +10 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +176 -0
- package/src/providers/context-cap.ts +26 -8
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/default-aliases.ts +65 -0
- package/src/providers/derive.ts +281 -6
- package/src/providers/fastwire.ts +507 -0
- package/src/providers/free-directory.ts +10 -7
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +71 -3
- package/src/providers/label.ts +35 -2
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +115 -22
- package/src/providers/model-presets.ts +119 -0
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/new-model-policy.ts +146 -0
- package/src/providers/openai-sidecar.ts +72 -4
- package/src/providers/openai-tier-startup.ts +31 -2
- package/src/providers/openai-tiers.ts +119 -4
- package/src/providers/openai-virtual-models.ts +1 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +30 -0
- package/src/providers/quota.ts +1379 -40
- package/src/providers/registry.ts +1545 -112
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +94 -6
- package/src/providers/static-model-discovery.ts +86 -0
- package/src/providers/xai-responses-opt-in.ts +15 -0
- package/src/providers/xai-transport.ts +32 -4
- package/src/reasoning-effort.ts +68 -3
- package/src/responses/apply-patch-envelope.ts +63 -0
- package/src/responses/code-mode-helper-compat.ts +50 -0
- package/src/responses/compaction.ts +26 -1
- package/src/responses/custom-tool-compat.ts +384 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +435 -0
- package/src/responses/parser.ts +225 -38
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +9 -1
- package/src/responses/reasoning-replay-cache.ts +504 -0
- package/src/responses/schema.ts +12 -2
- package/src/responses/spill-store.ts +75 -10
- package/src/responses/state.ts +659 -31
- package/src/responses/thought-signature-replay.ts +364 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/responses/turn-termination.ts +107 -0
- package/src/router.ts +405 -31
- package/src/routing/analytics.ts +379 -0
- package/src/routing/capability.ts +244 -0
- package/src/routing/compatibility/assemble.ts +73 -0
- package/src/routing/compatibility/behavior.ts +278 -0
- package/src/routing/compatibility/catalog.ts +99 -0
- package/src/routing/compatibility/endpoint.ts +52 -0
- package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
- package/src/routing/compatibility/policy.ts +181 -0
- package/src/routing/compatibility/provider-slot.ts +56 -0
- package/src/routing/compatibility/reader.ts +110 -0
- package/src/routing/compatibility/subject.ts +191 -0
- package/src/routing/compatibility/types.ts +64 -0
- package/src/routing/compatibility/version.ts +104 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +495 -0
- package/src/routing/health.ts +412 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +547 -0
- package/src/routing/quota.ts +155 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +776 -0
- package/src/server/adapter-resolve.ts +2 -29
- package/src/server/auth-cors.ts +289 -48
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +154 -72
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +445 -0
- package/src/server/claude-messages.ts +160 -44
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +18 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +39 -10
- package/src/server/images.ts +94 -12
- package/src/server/index.ts +1021 -190
- package/src/server/lifecycle.ts +336 -14
- package/src/server/live.ts +136 -17
- package/src/server/local-management-read-client.ts +90 -0
- package/src/server/local-provider-reload-client.ts +137 -0
- package/src/server/management/agent-settings-routes.ts +433 -116
- package/src/server/management/api-key-usage.ts +31 -5
- package/src/server/management/body.ts +6 -0
- package/src/server/management/codex-prompt-routes.ts +570 -0
- package/src/server/management/combo-routes.ts +64 -25
- package/src/server/management/config-routes.ts +511 -51
- package/src/server/management/context.ts +89 -2
- package/src/server/management/integration-routes.ts +498 -0
- package/src/server/management/lab-automation-routes.ts +206 -0
- package/src/server/management/lab-routes.ts +563 -0
- package/src/server/management/logs-usage-routes.ts +127 -52
- package/src/server/management/model-routes.ts +461 -133
- package/src/server/management/model-rows.ts +167 -0
- package/src/server/management/native-integration-routes.ts +770 -0
- package/src/server/management/oauth-account-routes.ts +90 -8
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +836 -159
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/route-registry.ts +332 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +380 -0
- package/src/server/management/shared.ts +27 -11
- package/src/server/management/sidebar-routes.ts +47 -31
- package/src/server/management/storage-log-guard-routes.ts +186 -0
- package/src/server/management/sync-response.ts +69 -0
- package/src/server/management/system-restart.ts +289 -33
- package/src/server/management/system-routes.ts +77 -0
- package/src/server/management/usage-summary-cache.ts +9 -1
- package/src/server/management/vision-sidecar-options.ts +167 -0
- package/src/server/management/web-search-sidecar-options.ts +120 -0
- package/src/server/management-api.ts +126 -23
- package/src/server/management-auth.ts +220 -5
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/port-reclaim.ts +1 -1
- package/src/server/ports.ts +41 -1
- package/src/server/proxy-liveness.ts +161 -10
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +221 -54
- package/src/server/relay.ts +479 -87
- package/src/server/request-decompress.ts +113 -6
- package/src/server/request-log-conversation.ts +51 -0
- package/src/server/request-log.ts +298 -31
- package/src/server/responses/agent-task-recovery-cache.ts +143 -0
- package/src/server/responses/agent-task-recovery.ts +465 -0
- package/src/server/responses/codex-auth-error.ts +55 -0
- package/src/server/responses/collaboration.ts +239 -36
- package/src/server/responses/combo-stream-preflight.ts +178 -0
- package/src/server/responses/compact.ts +444 -72
- package/src/server/responses/core.ts +3579 -436
- package/src/server/responses/empty-completion-guard.ts +333 -0
- package/src/server/responses/encrypted-payload.ts +62 -39
- package/src/server/responses/fetch-helpers.ts +89 -99
- package/src/server/responses/input-admission.ts +187 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/passthrough-error.ts +33 -9
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +343 -0
- package/src/server/responses/terminal-guard.ts +26 -5
- package/src/server/responses/upstream-error.ts +5 -0
- package/src/server/responses/ws-upstream.ts +381 -0
- package/src/server/responses-custom-tool-repair.ts +363 -0
- package/src/server/responses-item-id-repair.ts +54 -6
- package/src/server/responses-json-events.ts +90 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses-terminal-repair.ts +363 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +376 -0
- package/src/server/responses.ts +18 -2
- package/src/server/search.ts +78 -13
- package/src/server/sse-frame-buffer.ts +319 -0
- package/src/server/sse-payload-rewrite.ts +110 -22
- package/src/server/startup-action-control.ts +8 -1
- package/src/server/startup-health-cache.ts +19 -1
- package/src/server/system-env.ts +80 -9
- package/src/server/ws-bridge.ts +53 -40
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +1153 -94
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/storage/cleanup.ts +2 -2
- package/src/storage/policy-job.ts +14 -4
- package/src/storage/policy.ts +88 -23
- package/src/storage/scanner.ts +1 -1
- package/src/storage/worker-lifecycle.ts +14 -14
- package/src/tray/windows-tray.ps1 +83 -9
- package/src/tray/windows.ts +43 -16
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +911 -0
- package/src/types/provider.ts +614 -0
- package/src/types/request.ts +397 -0
- package/src/types/tools.ts +236 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +107 -1237
- package/src/update/index.ts +37 -23
- package/src/update/job.ts +445 -68
- package/src/update/notify.ts +12 -6
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +266 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/expected-prices.ts +287 -16
- package/src/usage/log.ts +666 -50
- package/src/usage/summary.ts +388 -17
- package/src/usage/user-cost-overlay-reconciler.ts +313 -0
- package/src/usage/user-cost-overlays.ts +314 -0
- package/src/vision/anthropic-describe.ts +10 -6
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +27 -16
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +238 -24
- package/src/vision/reasoning.ts +55 -0
- package/src/vision/routed-describe.ts +175 -0
- package/src/vision/timeout-bounds.ts +9 -0
- package/src/web-search/anthropic-executor.ts +13 -7
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +119 -0
- package/src/web-search/executor.ts +21 -6
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +150 -15
- package/src/web-search/loop.ts +284 -54
- package/src/web-search/parse.ts +125 -30
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/xai-executor.ts +219 -0
- package/gui/dist/assets/index-DTpMHS4F.js +0 -67
- package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
- package/gui/dist/provider-icons/antigravity.svg +0 -1
- package/gui/dist/provider-icons/claude.svg +0 -1
- package/gui/dist/provider-icons/copilot.svg +0 -1
- package/gui/dist/provider-icons/cursor.svg +0 -2
- package/gui/dist/provider-icons/gemini.svg +0 -1
- package/gui/dist/provider-icons/grok-color.svg +0 -1
- package/gui/dist/provider-icons/kiro.svg +0 -14
- package/src/cli/internal-dispatch.ts +0 -20
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Additive merge and surgical removal of the fragments opencodex owns.
|
|
3
|
+
*
|
|
4
|
+
* The rule that shapes this file: we insert exactly the paths our builder
|
|
5
|
+
* named, and we delete exactly the paths a record says we wrote. Nothing here
|
|
6
|
+
* ever scans for a prefix — a user's own `opencodex/...` entry is not ours to
|
|
7
|
+
* remove, and inferring ownership from a name is how a config editor destroys
|
|
8
|
+
* work it did not create.
|
|
9
|
+
*
|
|
10
|
+
* Design of record: devlog/_fin/260802_client_toggle_api/031_wp3_writer_impl.md.
|
|
11
|
+
*/
|
|
12
|
+
import type { ManagedContribution } from "../clients/config-export";
|
|
13
|
+
|
|
14
|
+
function isPlainRecord(value: unknown): value is Record<string, unknown> {
|
|
15
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Structured clone via JSON: our documents are plain data by construction. */
|
|
19
|
+
function clone<T>(value: T): T {
|
|
20
|
+
return value === undefined ? value : (JSON.parse(JSON.stringify(value)) as T);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Write `value` at `path`, creating intermediate objects. Returns a new document. */
|
|
24
|
+
export function setPath(doc: unknown, path: readonly string[], value: unknown): unknown {
|
|
25
|
+
if (path.length === 0) throw new Error("setPath needs a non-empty path");
|
|
26
|
+
const root: Record<string, unknown> = isPlainRecord(doc) ? clone(doc) : {};
|
|
27
|
+
let cursor = root;
|
|
28
|
+
for (const key of path.slice(0, -1)) {
|
|
29
|
+
const next = cursor[key];
|
|
30
|
+
if (!isPlainRecord(next)) cursor[key] = {};
|
|
31
|
+
cursor = cursor[key] as Record<string, unknown>;
|
|
32
|
+
}
|
|
33
|
+
cursor[path[path.length - 1]!] = clone(value);
|
|
34
|
+
return root;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Delete `path`, optionally pruning containers that WE created.
|
|
39
|
+
*
|
|
40
|
+
* Two properties have to hold at once, and they pull in opposite directions.
|
|
41
|
+
* A user who wrote `providers: {}` before we existed still has it after a
|
|
42
|
+
* disable — pruning it because our entry left it empty would delete their
|
|
43
|
+
* line. But a container we conjured ourselves (Kimi's `models` map exists only
|
|
44
|
+
* because our aliases need somewhere to live) must not survive as empty
|
|
45
|
+
* residue in a file the user never asked us to restructure.
|
|
46
|
+
*
|
|
47
|
+
* `createdContainers` is the difference: paths recorded at apply time as
|
|
48
|
+
* absent beforehand. Anything not in that set is treated as the user's.
|
|
49
|
+
*/
|
|
50
|
+
export function deletePath(
|
|
51
|
+
doc: unknown,
|
|
52
|
+
path: readonly string[],
|
|
53
|
+
createdContainers: ReadonlySet<string> = new Set(),
|
|
54
|
+
): { doc: unknown; removed: boolean } {
|
|
55
|
+
if (!isPlainRecord(doc) || path.length === 0) return { doc, removed: false };
|
|
56
|
+
const root = clone(doc) as Record<string, unknown>;
|
|
57
|
+
const chain: Record<string, unknown>[] = [root];
|
|
58
|
+
let cursor: Record<string, unknown> = root;
|
|
59
|
+
for (const key of path.slice(0, -1)) {
|
|
60
|
+
const next = cursor[key];
|
|
61
|
+
if (!isPlainRecord(next)) return { doc: root, removed: false };
|
|
62
|
+
cursor = next;
|
|
63
|
+
chain.push(cursor);
|
|
64
|
+
}
|
|
65
|
+
const leaf = path[path.length - 1]!;
|
|
66
|
+
if (!(leaf in cursor)) return { doc: root, removed: false };
|
|
67
|
+
delete cursor[leaf];
|
|
68
|
+
/*
|
|
69
|
+
* Walk back up, pruning only containers this deletion emptied AND that we
|
|
70
|
+
* created. The root is never pruned.
|
|
71
|
+
*/
|
|
72
|
+
for (let index = chain.length - 1; index >= 1; index -= 1) {
|
|
73
|
+
const container = chain[index]!;
|
|
74
|
+
if (Object.keys(container).length > 0) break;
|
|
75
|
+
const containerPath = path.slice(0, index).join("\u0000");
|
|
76
|
+
if (!createdContainers.has(containerPath)) break;
|
|
77
|
+
delete chain[index - 1]![path[index - 1]!];
|
|
78
|
+
}
|
|
79
|
+
return { doc: root, removed: true };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Insert every fragment. Everything else in the document is preserved. */
|
|
83
|
+
export function mergeContribution(doc: unknown, contribution: ManagedContribution): unknown {
|
|
84
|
+
let next = doc;
|
|
85
|
+
for (const fragment of contribution.fragments) next = setPath(next, fragment.path, fragment.value);
|
|
86
|
+
return next;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Remove exactly the RECORDED paths — never a prefix scan. An entry that
|
|
91
|
+
* matches our naming but has no recorded path is not ours: it reads as
|
|
92
|
+
* `conflict` and survives untouched.
|
|
93
|
+
*/
|
|
94
|
+
export function removeFragments(
|
|
95
|
+
doc: unknown,
|
|
96
|
+
paths: readonly (readonly string[])[],
|
|
97
|
+
createdContainers: ReadonlySet<string> = new Set(),
|
|
98
|
+
): { doc: unknown; removed: boolean } {
|
|
99
|
+
let next = doc;
|
|
100
|
+
let removed = false;
|
|
101
|
+
for (const path of paths) {
|
|
102
|
+
const result = deletePath(next, path, createdContainers);
|
|
103
|
+
next = result.doc;
|
|
104
|
+
removed = removed || result.removed;
|
|
105
|
+
}
|
|
106
|
+
return { doc: next, removed };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Container paths a contribution would have to CREATE in `doc`.
|
|
111
|
+
*
|
|
112
|
+
* Computed before the merge, because afterwards every container exists and the
|
|
113
|
+
* question is unanswerable. Recorded on the ownership record so a later
|
|
114
|
+
* disable can tell its own scaffolding from the user's structure.
|
|
115
|
+
*/
|
|
116
|
+
export function createdContainerPaths(
|
|
117
|
+
doc: unknown,
|
|
118
|
+
contribution: ManagedContribution,
|
|
119
|
+
): string[] {
|
|
120
|
+
const created = new Set<string>();
|
|
121
|
+
for (const fragment of contribution.fragments) {
|
|
122
|
+
let cursor: unknown = doc;
|
|
123
|
+
for (let depth = 0; depth < fragment.path.length - 1; depth += 1) {
|
|
124
|
+
const key = fragment.path[depth]!;
|
|
125
|
+
const next = isPlainRecord(cursor) ? cursor[key] : undefined;
|
|
126
|
+
if (!isPlainRecord(next)) {
|
|
127
|
+
created.add(fragment.path.slice(0, depth + 1).join("\u0000"));
|
|
128
|
+
cursor = undefined;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
cursor = next;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return [...created];
|
|
135
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { IntegrationClientId } from "./registry";
|
|
2
|
+
|
|
3
|
+
const INTEGRATION_MUTATION_JOIN_MS = 120_000;
|
|
4
|
+
export const INTEGRATION_MUTATION_TERMINAL_MS = 10 * 60_000;
|
|
5
|
+
|
|
6
|
+
interface IntegrationMutationFlight {
|
|
7
|
+
key: string;
|
|
8
|
+
startedAt: number;
|
|
9
|
+
promise: Promise<unknown>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class IntegrationMutationBusyError extends Error {
|
|
13
|
+
constructor(readonly clientId: IntegrationClientId) {
|
|
14
|
+
super("integration_mutation_busy");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const integrationMutationFlights = new Map<IntegrationClientId, IntegrationMutationFlight>();
|
|
19
|
+
let integrationMutationRunTestHook: ((operation: () => Promise<unknown>) => Promise<unknown>) | null = null;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* One in-process flight per client, shared by explicit HTTP mutations and
|
|
23
|
+
* implicit catalog refreshes. Equal operations join; different semantics are
|
|
24
|
+
* busy instead of, for example, letting an explicit apply join a refresh-only
|
|
25
|
+
* no-op for an absent block.
|
|
26
|
+
*/
|
|
27
|
+
export function runIntegrationMutationFlight<T>(
|
|
28
|
+
clientId: IntegrationClientId,
|
|
29
|
+
key: string,
|
|
30
|
+
now: () => number,
|
|
31
|
+
operation: () => Promise<T>,
|
|
32
|
+
): Promise<T> {
|
|
33
|
+
const startedAt = now();
|
|
34
|
+
const current = integrationMutationFlights.get(clientId);
|
|
35
|
+
if (current) {
|
|
36
|
+
const age = startedAt - current.startedAt;
|
|
37
|
+
if (current.key === key && age < INTEGRATION_MUTATION_JOIN_MS) {
|
|
38
|
+
return current.promise as Promise<T>;
|
|
39
|
+
}
|
|
40
|
+
if (age <= INTEGRATION_MUTATION_TERMINAL_MS) {
|
|
41
|
+
return Promise.reject(new IntegrationMutationBusyError(clientId));
|
|
42
|
+
}
|
|
43
|
+
if (integrationMutationFlights.get(clientId) === current) {
|
|
44
|
+
integrationMutationFlights.delete(clientId);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const flight: IntegrationMutationFlight = {
|
|
49
|
+
key,
|
|
50
|
+
startedAt,
|
|
51
|
+
promise: Promise.resolve(),
|
|
52
|
+
};
|
|
53
|
+
const run = async (): Promise<unknown> => operation();
|
|
54
|
+
flight.promise = (integrationMutationRunTestHook
|
|
55
|
+
? integrationMutationRunTestHook(run)
|
|
56
|
+
: run()
|
|
57
|
+
).finally(() => {
|
|
58
|
+
if (integrationMutationFlights.get(clientId) === flight) {
|
|
59
|
+
integrationMutationFlights.delete(clientId);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
integrationMutationFlights.set(clientId, flight);
|
|
63
|
+
return flight.promise as Promise<T>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function setIntegrationMutationFlightTestHook(
|
|
67
|
+
run: ((operation: () => Promise<unknown>) => Promise<unknown>) | null,
|
|
68
|
+
): void {
|
|
69
|
+
integrationMutationRunTestHook = run;
|
|
70
|
+
integrationMutationFlights.clear();
|
|
71
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The service-home preflight for native-client teardown (WP2, audit r1 #5;
|
|
3
|
+
* devlog 260803_integrations_toggle_all/012).
|
|
4
|
+
*
|
|
5
|
+
* `ocx stop` has honored `ServiceOwnershipError` since it started catching it
|
|
6
|
+
* (src/cli/index.ts:464); nothing on the HTTP side ever did. A route that calls
|
|
7
|
+
* `stripGrokConfig` directly would otherwise pull the fence out from under a
|
|
8
|
+
* service running from another CODEX_HOME/OPENCODEX_HOME — the installed
|
|
9
|
+
* service is still live and the shared state belongs to it.
|
|
10
|
+
*
|
|
11
|
+
* ENABLE is not gated by this: writing our own fence is not a shared teardown,
|
|
12
|
+
* and `injectGrokConfig` already runs unguarded from `ocx start`/`ensure`.
|
|
13
|
+
*/
|
|
14
|
+
import {
|
|
15
|
+
assertServiceEnvironmentMatchesInstall,
|
|
16
|
+
isServiceOwnershipError,
|
|
17
|
+
} from "../../service";
|
|
18
|
+
import {
|
|
19
|
+
currentServiceHomes,
|
|
20
|
+
inspectServiceStateEvidence,
|
|
21
|
+
serviceHomeMatches,
|
|
22
|
+
type ServiceStateEvidence,
|
|
23
|
+
} from "../../service";
|
|
24
|
+
import {
|
|
25
|
+
inspectServiceManagerInstallation,
|
|
26
|
+
type ProbeDeps,
|
|
27
|
+
type ServiceManagerClaim,
|
|
28
|
+
} from "../../service-manager-probe";
|
|
29
|
+
|
|
30
|
+
export type NativeTeardownOwnership = { ok: true } | { ok: false; message: string };
|
|
31
|
+
|
|
32
|
+
export function assertNativeTeardownOwned(): NativeTeardownOwnership {
|
|
33
|
+
try {
|
|
34
|
+
assertServiceEnvironmentMatchesInstall();
|
|
35
|
+
return { ok: true };
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (isServiceOwnershipError(error)) {
|
|
38
|
+
// The message names both the recorded and the current home — that is the
|
|
39
|
+
// refusal text, verbatim, because the user has to act on it.
|
|
40
|
+
return { ok: false, message: error.message };
|
|
41
|
+
}
|
|
42
|
+
// Unrelated failure (corrupt state file, IO): mirror
|
|
43
|
+
// `serviceEnvironmentOwnedHere` and fail open rather than wedging the route
|
|
44
|
+
// behind a check whose own input is broken.
|
|
45
|
+
return { ok: true };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Tri-state ownership for UNATTENDED writes.
|
|
51
|
+
*
|
|
52
|
+
* Deliberately not `assertNativeTeardownOwned`. That one fails OPEN — a corrupt
|
|
53
|
+
* state file yields `{ok:true}` — which is right for a teardown route a human
|
|
54
|
+
* just invoked, and catastrophic as an authority for automatic convergence:
|
|
55
|
+
* "could not read" would become "belongs to me".
|
|
56
|
+
*
|
|
57
|
+
* `owned` here means NO PERSISTENT SERVICE CLAIM WAS OBSERVED. It does not mean
|
|
58
|
+
* this process is the only writer. Two foreground `ocx start` processes on one
|
|
59
|
+
* home both read `owned`, and correctly so, because neither installs a service —
|
|
60
|
+
* keeping them apart is the write lock's job, not this function's.
|
|
61
|
+
*/
|
|
62
|
+
export type NativeCodexOwnership = "owned" | "foreign" | "unknown";
|
|
63
|
+
|
|
64
|
+
export interface OwnershipInspection {
|
|
65
|
+
readonly ownership: NativeCodexOwnership;
|
|
66
|
+
/** Why, in the words a refusal message can use. */
|
|
67
|
+
readonly reason: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function claimNamesDifferentHome(
|
|
71
|
+
claim: ServiceManagerClaim,
|
|
72
|
+
current: { codexHome: string; opencodexHome: string },
|
|
73
|
+
): boolean {
|
|
74
|
+
// A definition that OMITS a home is not a definition that disagrees about it:
|
|
75
|
+
// an install run without CODEX_HOME set writes no such key at all.
|
|
76
|
+
if (claim.homes.codexHome !== null && !serviceHomeMatches(claim.homes.codexHome, current.codexHome)) return true;
|
|
77
|
+
if (claim.homes.opencodexHome !== null && !serviceHomeMatches(claim.homes.opencodexHome, current.opencodexHome)) return true;
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Map a service-manager claim backend to the `ServiceInstallState.backend`
|
|
83
|
+
* value it corresponds to. `scheduler` (Task Scheduler) and `winsw` (native)
|
|
84
|
+
* are the two Windows manager backends; launchd/systemd claims have no Windows
|
|
85
|
+
* backend and can never mismatch a v2 state file.
|
|
86
|
+
*/
|
|
87
|
+
function claimBackendToStateBackend(backend: ServiceManagerClaim["backend"]): "scheduler" | "native" | null {
|
|
88
|
+
if (backend === "scheduler") return "scheduler";
|
|
89
|
+
if (backend === "winsw") return "native";
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** True when the recorded state backend disagrees with the manager claim. Legacy v1 means scheduler. */
|
|
94
|
+
function claimBackendMismatchesState(claim: ServiceManagerClaim, state: { backend?: "scheduler" | "native" }): boolean {
|
|
95
|
+
const expected = claimBackendToStateBackend(claim.backend);
|
|
96
|
+
if (expected === null) return false;
|
|
97
|
+
return (state.backend ?? "scheduler") !== expected;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface OwnershipDeps extends ProbeDeps {
|
|
101
|
+
/**
|
|
102
|
+
* Which state paths to consult. Injectable because the default set includes
|
|
103
|
+
* the DEFAULT home mirror, resolved from `homedir()` — which no test sandbox
|
|
104
|
+
* moves. Without this a fixture reads the developer's real installation and
|
|
105
|
+
* calls their own machine foreign.
|
|
106
|
+
*/
|
|
107
|
+
readonly statePaths?: readonly string[];
|
|
108
|
+
readonly currentHomes?: { codexHome: string; opencodexHome: string };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function inspectNativeCodexOwnership(deps: OwnershipDeps = {}): OwnershipInspection {
|
|
112
|
+
const current = deps.currentHomes ?? currentServiceHomes();
|
|
113
|
+
const evidence = deps.statePaths
|
|
114
|
+
? inspectServiceStateEvidence(deps.statePaths)
|
|
115
|
+
: inspectServiceStateEvidence();
|
|
116
|
+
|
|
117
|
+
const unreadable = evidence.find((e): e is Extract<ServiceStateEvidence, { kind: "unreadable" }> => e.kind === "unreadable");
|
|
118
|
+
if (unreadable) {
|
|
119
|
+
return { ownership: "unknown", reason: `service state at ${unreadable.path} could not be read (${unreadable.reason})` };
|
|
120
|
+
}
|
|
121
|
+
const invalid = evidence.find(e => e.kind === "invalid");
|
|
122
|
+
if (invalid) {
|
|
123
|
+
return { ownership: "unknown", reason: `service state at ${invalid.path} is malformed` };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const valid = evidence.filter((e): e is Extract<ServiceStateEvidence, { kind: "valid" }> => e.kind === "valid");
|
|
127
|
+
// Mirrors that disagree with each other are not a majority vote.
|
|
128
|
+
for (const one of valid) {
|
|
129
|
+
for (const other of valid) {
|
|
130
|
+
if (!serviceHomeMatches(one.state.codexHome, other.state.codexHome)
|
|
131
|
+
|| !serviceHomeMatches(one.state.opencodexHome, other.state.opencodexHome)) {
|
|
132
|
+
return { ownership: "unknown", reason: "two service state files disagree about which homes are installed" };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const foreign = valid.find(e =>
|
|
138
|
+
!serviceHomeMatches(e.state.codexHome, current.codexHome)
|
|
139
|
+
|| !serviceHomeMatches(e.state.opencodexHome, current.opencodexHome));
|
|
140
|
+
if (foreign) {
|
|
141
|
+
return {
|
|
142
|
+
ownership: "foreign",
|
|
143
|
+
reason: `a service is installed for CODEX_HOME=${foreign.state.codexHome} / OPENCODEX_HOME=${foreign.state.opencodexHome}`,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// The manager assets live under the effective OPENCODEX_HOME. Production
|
|
148
|
+
// callers do not inject ProbeDeps.configDir, so derive it from the same
|
|
149
|
+
// current-home snapshot used for ownership comparison rather than silently
|
|
150
|
+
// falling back to <homedir>/.opencodex.
|
|
151
|
+
const manager = inspectServiceManagerInstallation({
|
|
152
|
+
...deps,
|
|
153
|
+
configDir: deps.configDir ?? current.opencodexHome,
|
|
154
|
+
});
|
|
155
|
+
if (manager.kind === "unknown") {
|
|
156
|
+
return { ownership: "unknown", reason: manager.reason };
|
|
157
|
+
}
|
|
158
|
+
if (manager.kind === "conflict") {
|
|
159
|
+
return { ownership: "unknown", reason: "more than one service manager holds a registration for this proxy" };
|
|
160
|
+
}
|
|
161
|
+
if (manager.kind === "present") {
|
|
162
|
+
const disagreeing = manager.claims.find(claim => claimNamesDifferentHome(claim, current));
|
|
163
|
+
if (disagreeing) {
|
|
164
|
+
/*
|
|
165
|
+
* The state file says this home and the definition says another. An
|
|
166
|
+
* interrupted reinstall looks exactly like this — installation writes the
|
|
167
|
+
* definition BEFORE the state file — and picking a winner unattended would
|
|
168
|
+
* be guessing which half of a half-finished operation to believe.
|
|
169
|
+
*/
|
|
170
|
+
return {
|
|
171
|
+
ownership: "unknown",
|
|
172
|
+
reason: `${disagreeing.backend} is installed from ${disagreeing.definitionPath}, which names different homes than the recorded service state`,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// A manager backend that disagrees with the recorded state (e.g. state says
|
|
176
|
+
// native/WinSW but a scheduler task is found) is an interrupted backend
|
|
177
|
+
// switch: it does not prove which manager owns the installation. v1 state
|
|
178
|
+
// predates the field and is scheduler by contract.
|
|
179
|
+
const stateBackendMismatch = valid.find(state => manager.claims.some(claim => claimBackendMismatchesState(claim, state.state)));
|
|
180
|
+
if (stateBackendMismatch) {
|
|
181
|
+
return {
|
|
182
|
+
ownership: "unknown",
|
|
183
|
+
reason: `the service state records backend ${stateBackendMismatch.state.backend ?? "scheduler"} but ${manager.claims[0]?.backend ?? "a service manager"} is installed`,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
// Definition agrees. Valid state agreeing with it is ownership; no state at
|
|
187
|
+
// all beside an installed definition is not, because the definition is the
|
|
188
|
+
// claim and nothing here recorded making it.
|
|
189
|
+
if (valid.length === 0) {
|
|
190
|
+
return {
|
|
191
|
+
ownership: "unknown",
|
|
192
|
+
reason: `${manager.claims[0]?.backend ?? "a service manager"} holds a registration that no service state file accounts for`,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
return { ownership: "owned", reason: "the installed service names these homes" };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// manager.kind === "absent"
|
|
199
|
+
return valid.length === 0
|
|
200
|
+
? { ownership: "owned", reason: "no service state and no service manager claim" }
|
|
201
|
+
: { ownership: "owned", reason: "the recorded service state names these homes" };
|
|
202
|
+
}
|