@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
|
@@ -9,6 +9,56 @@ import type { TranslatorBudget } from "../lib/translator-budget";
|
|
|
9
9
|
|
|
10
10
|
export type SsePayloadRewrite = (payload: string) => string;
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Block-level SSE rewrite: maps one complete SSE event block (without its
|
|
14
|
+
* blank-line delimiter) to zero or more replacement blocks. This is the
|
|
15
|
+
* contract lifecycle repair needs: injecting missing canonical events
|
|
16
|
+
* (#893) is impossible in the one-payload-in/one-payload-out model.
|
|
17
|
+
*
|
|
18
|
+
* `dispose` releases any retained state (budget-charged collectors) when the
|
|
19
|
+
* relay tears down — terminal, EOF, cancel, or error. Relays call it exactly
|
|
20
|
+
* once per teardown path.
|
|
21
|
+
*/
|
|
22
|
+
export type SseBlockRewrite = ((block: string) => readonly string[]) & {
|
|
23
|
+
dispose?: () => void;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/** Adapt a payload rewrite to the block contract (replace only on change). */
|
|
27
|
+
export function payloadRewriteAsBlockRewrite(rewrite: SsePayloadRewrite): SseBlockRewrite {
|
|
28
|
+
return (block) => {
|
|
29
|
+
const payload = sseDataPayload(block);
|
|
30
|
+
if (payload === null) return [block];
|
|
31
|
+
const rewritten = rewrite(payload);
|
|
32
|
+
return rewritten !== payload ? [replaceSseDataPayload(block, rewritten)] : [block];
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Chain block rewrites: every block stage N emits feeds stage N+1. */
|
|
37
|
+
export function composeSseBlockRewrites(...rewrites: SseBlockRewrite[]): SseBlockRewrite {
|
|
38
|
+
const active = rewrites.filter(Boolean);
|
|
39
|
+
if (active.length === 0) return Object.assign((block: string) => [block], {});
|
|
40
|
+
const composed: SseBlockRewrite = (block: string) => {
|
|
41
|
+
let blocks: readonly string[] = [block];
|
|
42
|
+
for (const rewrite of active) {
|
|
43
|
+
const next: string[] = [];
|
|
44
|
+
for (const current of blocks) next.push(...rewrite(current));
|
|
45
|
+
blocks = next;
|
|
46
|
+
}
|
|
47
|
+
return blocks;
|
|
48
|
+
};
|
|
49
|
+
// Child disposal is part of the contract: one idempotent disposer for the
|
|
50
|
+
// whole chain, so relay teardown never leaks a nested collector.
|
|
51
|
+
let disposed = false;
|
|
52
|
+
composed.dispose = () => {
|
|
53
|
+
if (disposed) return;
|
|
54
|
+
disposed = true;
|
|
55
|
+
for (const rewrite of active) {
|
|
56
|
+
try { rewrite.dispose?.(); } catch { /* teardown must not throw */ }
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
return composed;
|
|
60
|
+
}
|
|
61
|
+
|
|
12
62
|
/** Split one complete SSE event block while retaining its original blank-line delimiter. */
|
|
13
63
|
export function nextSseBlock(buffer: string): { block: string; delimiter: string; rest: string } | null {
|
|
14
64
|
const match = buffer.match(/\r?\n\r?\n/);
|
|
@@ -69,12 +119,34 @@ export function relaySseWithPayloadRewrite(
|
|
|
69
119
|
body: ReadableStream<Uint8Array>,
|
|
70
120
|
rewrite: SsePayloadRewrite,
|
|
71
121
|
translatorBudget: TranslatorBudget,
|
|
122
|
+
): ReadableStream<Uint8Array> {
|
|
123
|
+
return relaySseWithBlockRewrite(body, payloadRewriteAsBlockRewrite(rewrite), translatorBudget);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Relay an SSE body through a single JS pull wrapper, applying a block-level
|
|
128
|
+
* rewrite that may emit zero or more blocks per upstream event (lifecycle
|
|
129
|
+
* event injection, #893). The original stream's delimiter style is preserved
|
|
130
|
+
* for every emitted block.
|
|
131
|
+
*/
|
|
132
|
+
export function relaySseWithBlockRewrite(
|
|
133
|
+
body: ReadableStream<Uint8Array>,
|
|
134
|
+
rewrite: SseBlockRewrite,
|
|
135
|
+
translatorBudget: TranslatorBudget,
|
|
72
136
|
): ReadableStream<Uint8Array> {
|
|
73
137
|
const reader = body.getReader();
|
|
74
138
|
const decoder = new TextDecoder();
|
|
75
139
|
const encoder = new TextEncoder();
|
|
76
140
|
let buffer = "";
|
|
77
141
|
let bufferBytes = 0;
|
|
142
|
+
// Relays have several independent teardown paths; disposal is exactly once.
|
|
143
|
+
let disposed = false;
|
|
144
|
+
let cancelled = false;
|
|
145
|
+
const disposeRewrite = (): void => {
|
|
146
|
+
if (disposed) return;
|
|
147
|
+
disposed = true;
|
|
148
|
+
try { rewrite.dispose?.(); } catch { /* teardown must not throw */ }
|
|
149
|
+
};
|
|
78
150
|
|
|
79
151
|
const appendBuffer = (fragment: string): void => {
|
|
80
152
|
if (!fragment) return;
|
|
@@ -126,49 +198,65 @@ export function relaySseWithPayloadRewrite(
|
|
|
126
198
|
const emitProcessedBlocks = (
|
|
127
199
|
controller: ReadableStreamDefaultController<Uint8Array>,
|
|
128
200
|
flushFinal = false,
|
|
129
|
-
):
|
|
201
|
+
): number => {
|
|
202
|
+
let emitted = 0;
|
|
130
203
|
let next: { block: string; delimiter: string; rest: string } | null;
|
|
131
204
|
while ((next = nextSseBlock(buffer))) {
|
|
132
205
|
replaceBuffer(next.rest);
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
: next.block;
|
|
138
|
-
enqueueText(controller, block + next.delimiter);
|
|
206
|
+
for (const outBlock of rewrite(next.block)) {
|
|
207
|
+
enqueueText(controller, outBlock + next.delimiter);
|
|
208
|
+
emitted += 1;
|
|
209
|
+
}
|
|
139
210
|
}
|
|
140
211
|
if (flushFinal && buffer.length > 0) {
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
212
|
+
const tailBlocks = rewrite(buffer);
|
|
213
|
+
// A trailing fragment has no delimiter of its own; multiple emitted
|
|
214
|
+
// blocks must still be framed as separate events (#893 review).
|
|
215
|
+
const tailDelimiter = buffer.includes("\r\n") ? "\r\n\r\n" : "\n\n";
|
|
216
|
+
for (let i = 0; i < tailBlocks.length; i++) {
|
|
217
|
+
enqueueText(controller, tailBlocks[i]! + (i < tailBlocks.length - 1 ? tailDelimiter : ""));
|
|
218
|
+
emitted += 1;
|
|
219
|
+
}
|
|
147
220
|
releaseBuffer();
|
|
148
221
|
}
|
|
222
|
+
return emitted;
|
|
149
223
|
};
|
|
150
224
|
|
|
151
225
|
return new ReadableStream<Uint8Array>({
|
|
152
226
|
async pull(controller) {
|
|
153
227
|
try {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
228
|
+
// A network chunk is not an SSE-event boundary. Bun may not issue a
|
|
229
|
+
// second pull after a fulfilled pull enqueues nothing, so keep reading
|
|
230
|
+
// until at least one complete rewritten block is available or EOF is
|
|
231
|
+
// reached. This also handles block rewrites that intentionally drop an
|
|
232
|
+
// event without parking the client stream.
|
|
233
|
+
for (;;) {
|
|
234
|
+
const { done, value } = await reader.read();
|
|
235
|
+
// A cancel raced this pending read: never feed the rewriter again
|
|
236
|
+
// after its disposal (#893 review).
|
|
237
|
+
if (cancelled) return;
|
|
238
|
+
if (done) {
|
|
239
|
+
appendBuffer(decoder.decode());
|
|
240
|
+
emitProcessedBlocks(controller, true);
|
|
241
|
+
releaseBuffer();
|
|
242
|
+
disposeRewrite();
|
|
243
|
+
controller.close();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
appendBuffer(decoder.decode(value, { stream: true }));
|
|
247
|
+
if (emitProcessedBlocks(controller) > 0) return;
|
|
161
248
|
}
|
|
162
|
-
appendBuffer(decoder.decode(value, { stream: true }));
|
|
163
|
-
emitProcessedBlocks(controller);
|
|
164
249
|
} catch (error) {
|
|
165
250
|
releaseBuffer();
|
|
251
|
+
disposeRewrite();
|
|
166
252
|
try { await reader.cancel(error); } catch { /* already closed */ }
|
|
167
253
|
controller.error(error);
|
|
168
254
|
}
|
|
169
255
|
},
|
|
170
256
|
cancel(reason) {
|
|
257
|
+
cancelled = true;
|
|
171
258
|
releaseBuffer();
|
|
259
|
+
disposeRewrite();
|
|
172
260
|
reader.cancel(reason).catch(() => {});
|
|
173
261
|
},
|
|
174
262
|
});
|
|
@@ -164,10 +164,17 @@ function runCliInstall(
|
|
|
164
164
|
const cli = join(import.meta.dir, "..", "cli", "index.ts");
|
|
165
165
|
const argv = [cli, ...startupInstallArgv(action, options)];
|
|
166
166
|
return new Promise((resolve, reject) => {
|
|
167
|
+
const timeout = process.platform === "win32" && action === "install-service"
|
|
168
|
+
? 0
|
|
169
|
+
: 60_000;
|
|
167
170
|
execFile(bun, argv, {
|
|
168
171
|
encoding: "utf8",
|
|
169
172
|
env: process.env,
|
|
170
|
-
|
|
173
|
+
// A fresh Windows scheduler install now owns its UAC prompt inside this CLI
|
|
174
|
+
// transaction. Killing only the CLI at 60s can orphan its elevated schtasks child,
|
|
175
|
+
// which may register the task after the Dashboard has reported failure. Keep the
|
|
176
|
+
// async request/attempt lock alive until Windows returns approval or cancellation.
|
|
177
|
+
timeout,
|
|
171
178
|
windowsHide: true,
|
|
172
179
|
maxBuffer: 256 * 1024,
|
|
173
180
|
}, (error, stdout, stderr) => {
|
|
@@ -10,6 +10,7 @@ import { truncateRetainedUtf8 } from "../lib/admission";
|
|
|
10
10
|
|
|
11
11
|
const CACHE_TTL_MS = 30_000;
|
|
12
12
|
const PROBE_TIMEOUT_MS = 5_000;
|
|
13
|
+
const INITIAL_PROBE_WAIT_MS = 5_500;
|
|
13
14
|
const MAX_DIAGNOSTIC_VALUE_BYTES = 8 * 1024;
|
|
14
15
|
let cached: { timestamp: number; value: StartupHealth } | null = null;
|
|
15
16
|
let inflight: Promise<StartupHealth> | null = null;
|
|
@@ -23,9 +24,14 @@ export function markStartupHealthDiagnosticStale(value: StartupHealth): StartupH
|
|
|
23
24
|
rebootSafe: false,
|
|
24
25
|
protection: "none",
|
|
25
26
|
diagnosticStale: true,
|
|
27
|
+
// Mirror deriveStartupHealth's choice: an already-registered service is refreshed in
|
|
28
|
+
// place. Hardcoding installService here silently undid that for every stale-cache
|
|
29
|
+
// read, which is the path the dashboard hits while a probe is revalidating.
|
|
26
30
|
recommendedCommand: value.routingKind === "custom-local" || value.routingKind === "unknown"
|
|
27
31
|
? value.commands.restoreNative
|
|
28
|
-
: value.
|
|
32
|
+
: value.serviceInstalled && !value.serviceConflict
|
|
33
|
+
? value.commands.repairService
|
|
34
|
+
: value.commands.installService,
|
|
29
35
|
};
|
|
30
36
|
}
|
|
31
37
|
|
|
@@ -72,6 +78,7 @@ function runProbe(config: Pick<OcxConfig, "codexAutoStart">): Promise<StartupHea
|
|
|
72
78
|
: truncateRetainedUtf8(parsed.recommendedCommand, MAX_DIAGNOSTIC_VALUE_BYTES),
|
|
73
79
|
commands: {
|
|
74
80
|
installService: truncateRetainedUtf8(parsed.commands.installService, MAX_DIAGNOSTIC_VALUE_BYTES),
|
|
81
|
+
repairService: truncateRetainedUtf8(parsed.commands.repairService, MAX_DIAGNOSTIC_VALUE_BYTES),
|
|
75
82
|
installShim: truncateRetainedUtf8(parsed.commands.installShim, MAX_DIAGNOSTIC_VALUE_BYTES),
|
|
76
83
|
restoreNative: truncateRetainedUtf8(parsed.commands.restoreNative, MAX_DIAGNOSTIC_VALUE_BYTES),
|
|
77
84
|
},
|
|
@@ -103,6 +110,17 @@ function refreshInBackground(config: Pick<OcxConfig, "codexAutoStart">): void {
|
|
|
103
110
|
export async function getCachedStartupHealth(config: Pick<OcxConfig, "codexAutoStart">): Promise<StartupHealth> {
|
|
104
111
|
if (cached && Date.now() - cached.timestamp < CACHE_TTL_MS) return cached.value;
|
|
105
112
|
refreshInBackground(config);
|
|
113
|
+
// An expired or empty read is an explicit protection check. Wait for the
|
|
114
|
+
// isolated probe instead of presenting a synthetic failure while that probe
|
|
115
|
+
// is still running. The probe remains child-process isolated and hard-capped
|
|
116
|
+
// at 5s; stale state is returned only if that bounded probe cannot settle.
|
|
117
|
+
if (inflight) {
|
|
118
|
+
const settled = await Promise.race([
|
|
119
|
+
inflight,
|
|
120
|
+
new Promise<null>(resolve => setTimeout(() => resolve(null), INITIAL_PROBE_WAIT_MS)),
|
|
121
|
+
]);
|
|
122
|
+
if (settled) return settled;
|
|
123
|
+
}
|
|
106
124
|
return cached ? markStartupHealthDiagnosticStale(cached.value) : conservativeFallback(config);
|
|
107
125
|
}
|
|
108
126
|
|
package/src/server/system-env.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
-
import { readFileSync, writeFileSync, unlinkSync, mkdirSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
2
|
+
import { accessSync, constants, readFileSync, writeFileSync, unlinkSync, mkdirSync, statSync } from "node:fs";
|
|
3
|
+
import { delimiter, join } from "node:path";
|
|
4
4
|
import { getConfigDir } from "../config";
|
|
5
5
|
import { resolveAutoContext, type AutoContextMode } from "../claude/context-windows";
|
|
6
6
|
import { PROXY_MARKER, defaultAuthDetectDeps, detectClaudeAuth, ownAdmissionTokens } from "../claude/auth-detect";
|
|
7
7
|
import { resolveClaudeAuthMode } from "../claude/auth-mode";
|
|
8
8
|
import type { OcxConfig } from "../types";
|
|
9
9
|
import { recordOwnedConfigPath } from "../lib/config-ownership";
|
|
10
|
+
import { providerContextCap } from "../providers/context-cap";
|
|
11
|
+
import { OPENAI_CODEX_PROVIDER_ID } from "../providers/openai-tiers";
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Does the opencodex dummy marker belong in the system environment?
|
|
@@ -116,15 +118,84 @@ export function uninstallShellHook(): { removed: boolean; reason?: string } {
|
|
|
116
118
|
try {
|
|
117
119
|
const content = readFileSync(zshrcPath, "utf8");
|
|
118
120
|
if (!content.includes(SHELL_HOOK_MARKER)) return { removed: false, reason: "not installed" };
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
+
// Match CR?LF, not LF alone. A .zshrc with CRLF line endings — ordinary on a home
|
|
122
|
+
// directory an editor or another OS has touched — did not match, so the file was
|
|
123
|
+
// rewritten unchanged and the caller was told the hook was removed. Reporting success
|
|
124
|
+
// while the hook still sources on every new shell is the worse of the two failures.
|
|
125
|
+
const cleaned = content.replace(/\r?\n?# opencodex claude-env hook\r?\n\[.*claude-env\.sh.*(?:\r?\n)?/g, "\n");
|
|
126
|
+
// Verify instead of assuming: if the marker survives, the block is shaped in a way this
|
|
127
|
+
// pattern does not own, and the honest answer is failure rather than a silent no-op.
|
|
128
|
+
if (cleaned.includes(SHELL_HOOK_MARKER)) {
|
|
129
|
+
return { removed: false, reason: "hook block present but not in the expected shape; remove it manually" };
|
|
130
|
+
}
|
|
121
131
|
writeFileSync(zshrcPath, cleaned, { encoding: "utf8", mode: 0o644 });
|
|
122
132
|
return { removed: true };
|
|
123
|
-
} catch {
|
|
133
|
+
} catch (error) {
|
|
134
|
+
if (error && typeof error === "object" && (error as { code?: unknown }).code === "ENOENT") {
|
|
135
|
+
return { removed: false, reason: "not installed" };
|
|
136
|
+
}
|
|
124
137
|
return { removed: false, reason: "read/write failed" };
|
|
125
138
|
}
|
|
126
139
|
}
|
|
127
140
|
|
|
141
|
+
/** Whether a real `claude` executable is discoverable from this process's PATH. */
|
|
142
|
+
export function claudeCodeCliInstalled(pathValue = process.env.PATH): boolean {
|
|
143
|
+
if (!pathValue) return false;
|
|
144
|
+
for (const directory of pathValue.split(delimiter)) {
|
|
145
|
+
// An empty PATH segment means the current directory. Do not let the proxy treat a
|
|
146
|
+
// workspace-local file as a durable user installation.
|
|
147
|
+
if (!directory) continue;
|
|
148
|
+
const candidate = join(directory, "claude");
|
|
149
|
+
try {
|
|
150
|
+
if (!statSync(candidate).isFile()) continue;
|
|
151
|
+
accessSync(candidate, constants.X_OK);
|
|
152
|
+
return true;
|
|
153
|
+
} catch {
|
|
154
|
+
// Keep scanning PATH after missing, non-file, and non-executable entries.
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Keep the shell hook aligned with the integration that can actually consume it.
|
|
162
|
+
* Claude Desktop uses its own profile and does not source `.zshrc`; this hook exists
|
|
163
|
+
* only for plain Claude Code CLI launches.
|
|
164
|
+
*
|
|
165
|
+
* Reconciliation is PATH-sensitive by construction: "Claude Code is installed" is answered
|
|
166
|
+
* from the PATH of whichever process calls this. A launchd/service context with a stripped
|
|
167
|
+
* PATH can therefore fail to see a `claude` the user's interactive shell finds, and this will
|
|
168
|
+
* remove the hook. That is the intended failure direction — removing an OpenCodex-owned block
|
|
169
|
+
* is reversible on the next foreground `ocx start`, whereas leaving a hook pointing at an
|
|
170
|
+
* uninstalled CLI is the stale state this reconciliation exists to clear. Only the block
|
|
171
|
+
* carrying our own marker is ever touched; user lines are preserved.
|
|
172
|
+
*/
|
|
173
|
+
export function reconcileShellHook(systemEnvInjected: boolean): {
|
|
174
|
+
changed: boolean;
|
|
175
|
+
state: "installed" | "absent" | "failed";
|
|
176
|
+
reason?: string;
|
|
177
|
+
} {
|
|
178
|
+
if (process.platform !== "darwin") return { changed: false, state: "absent", reason: "not macOS" };
|
|
179
|
+
if (systemEnvInjected && claudeCodeCliInstalled()) {
|
|
180
|
+
const result = installShellHook();
|
|
181
|
+
if (result.installed) return { changed: true, state: "installed" };
|
|
182
|
+
if (result.reason === "already installed") {
|
|
183
|
+
return { changed: false, state: "installed", reason: result.reason };
|
|
184
|
+
}
|
|
185
|
+
return { changed: false, state: "failed", reason: result.reason ?? "install failed" };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const result = uninstallShellHook();
|
|
189
|
+
if (!result.removed && result.reason !== "not installed") {
|
|
190
|
+
return { changed: false, state: "failed", reason: result.reason ?? "remove failed" };
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
changed: result.removed,
|
|
194
|
+
state: "absent",
|
|
195
|
+
reason: systemEnvInjected ? "Claude Code not installed" : "system environment inactive",
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
128
199
|
const SYSTEM_ENV_NAMES = [
|
|
129
200
|
"ANTHROPIC_BASE_URL",
|
|
130
201
|
"CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY",
|
|
@@ -235,12 +306,12 @@ function rollbackInjectedKeys(port: number, injectedKeys: string[]): void {
|
|
|
235
306
|
async function computeEffectiveModelEnv(config: OcxConfig, auto?: AutoContextMode): Promise<{ modelEnv: Record<string, string>; windows: Record<string, number> }> {
|
|
236
307
|
const { boundedContextWindows, buildClaudeContextWindows, effectiveModelEnv } = await import("../claude/context-windows");
|
|
237
308
|
const windows = await boundedContextWindows(async () => {
|
|
238
|
-
const { gatherRoutedModels, visibleNativeSlugs } = await import("../codex/catalog");
|
|
309
|
+
const { gatherRoutedModels, nativeContextLimits, visibleNativeSlugs } = await import("../codex/catalog");
|
|
239
310
|
try {
|
|
240
|
-
return buildClaudeContextWindows([...visibleNativeSlugs(config)], await gatherRoutedModels(config));
|
|
311
|
+
return buildClaudeContextWindows([...visibleNativeSlugs(config)], await gatherRoutedModels(config), nativeContextLimits(config));
|
|
241
312
|
} catch (error) {
|
|
242
313
|
if (error && typeof error === "object" && (error as { code?: unknown }).code === "catalog_busy") {
|
|
243
|
-
return buildClaudeContextWindows([...visibleNativeSlugs(config)], []);
|
|
314
|
+
return buildClaudeContextWindows([...visibleNativeSlugs(config)], [], nativeContextLimits(config));
|
|
244
315
|
}
|
|
245
316
|
throw error;
|
|
246
317
|
}
|
|
@@ -335,7 +406,7 @@ export async function injectSystemEnv(port: number, config: OcxConfig): Promise<
|
|
|
335
406
|
// without a token — keep it in sync with this proxy's /v1/models. Best-effort.
|
|
336
407
|
try {
|
|
337
408
|
const { refreshGatewayModelCacheFromProxy } = await import("../claude/gateway-cache");
|
|
338
|
-
await refreshGatewayModelCacheFromProxy(port);
|
|
409
|
+
await refreshGatewayModelCacheFromProxy(port, { admissionConfig: config });
|
|
339
410
|
} catch { /* best-effort */ }
|
|
340
411
|
|
|
341
412
|
// Roster agent definitions (devlog 070): same launch-time sync for plain `claude`.
|
package/src/server/ws-bridge.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { ServerWebSocket } from "bun";
|
|
2
|
+
import { responsesJsonEventSequence } from "./responses-json-events";
|
|
2
3
|
import { FORWARD_HEADERS } from "../adapters/openai-responses";
|
|
3
4
|
import type { CodexAuthContext } from "../codex/auth-context";
|
|
4
5
|
import { headersForCodexAuthContext } from "../codex/auth-context";
|
|
5
6
|
import type { ResponsesTerminalStatus } from "../bridge";
|
|
6
7
|
import type { DataPlaneAdmission } from "./auth-cors";
|
|
7
|
-
import type { AdmissionReservation } from "../lib/admission";
|
|
8
|
+
import type { AdmissionLease, AdmissionReservation } from "../lib/admission";
|
|
9
|
+
import { BoundedSseFrameBuffer } from "./sse-frame-buffer";
|
|
8
10
|
|
|
9
11
|
const OPEN = 1;
|
|
10
12
|
type ResponsesTerminalReporter = (status: ResponsesTerminalStatus) => void;
|
|
@@ -38,7 +40,15 @@ export interface WsData {
|
|
|
38
40
|
liveUpstreamUrl?: string;
|
|
39
41
|
liveUpstreamHeaders?: Record<string, string>;
|
|
40
42
|
livePending?: Array<string | Buffer>;
|
|
43
|
+
/** Total encoded bytes retained in livePending while the upstream connects. */
|
|
44
|
+
livePendingBytes?: number;
|
|
41
45
|
liveOpened?: boolean;
|
|
46
|
+
/** Once teardown starts, ignore new client frames until the upstream closes. */
|
|
47
|
+
liveClosing?: boolean;
|
|
48
|
+
/** Schedules one bounded close retry without surrendering native-main ownership. */
|
|
49
|
+
liveCloseFallback?: ReturnType<typeof setTimeout>;
|
|
50
|
+
/** Turn/account ownership retained for the complete sideband socket lifetime. */
|
|
51
|
+
liveTurnAdmissionLease?: AdmissionLease;
|
|
42
52
|
admissionLease?: AdmissionReservation<ServerWebSocket<WsData>>;
|
|
43
53
|
}
|
|
44
54
|
|
|
@@ -156,15 +166,6 @@ function parseSseBlock(block: string): string | null {
|
|
|
156
166
|
return data.length > 0 ? data.join("\n") : null;
|
|
157
167
|
}
|
|
158
168
|
|
|
159
|
-
function nextSseBlock(buffer: string): { block: string; rest: string } | null {
|
|
160
|
-
const match = buffer.match(/\r?\n\r?\n/);
|
|
161
|
-
if (!match || match.index === undefined) return null;
|
|
162
|
-
return {
|
|
163
|
-
block: buffer.slice(0, match.index),
|
|
164
|
-
rest: buffer.slice(match.index + match[0].length),
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
|
|
168
169
|
function payloadType(payload: string): string | null {
|
|
169
170
|
try {
|
|
170
171
|
const json = JSON.parse(payload) as { type?: unknown };
|
|
@@ -224,7 +225,7 @@ export async function pumpResponsesSseToWebSocket(
|
|
|
224
225
|
ws.data.cancel = cancel;
|
|
225
226
|
|
|
226
227
|
const decoder = new TextDecoder();
|
|
227
|
-
|
|
228
|
+
const framer = new BoundedSseFrameBuffer();
|
|
228
229
|
let terminalSeen = false;
|
|
229
230
|
|
|
230
231
|
const handlePayload = (payload: string): boolean => {
|
|
@@ -259,17 +260,14 @@ export async function pumpResponsesSseToWebSocket(
|
|
|
259
260
|
while (!terminalSeen) {
|
|
260
261
|
const { done, value } = await reader.read();
|
|
261
262
|
if (done) break;
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
while ((next = nextSseBlock(buffer))) {
|
|
265
|
-
buffer = next.rest;
|
|
266
|
-
const payload = parseSseBlock(next.block);
|
|
263
|
+
for (const frame of framer.feed(value)) {
|
|
264
|
+
const payload = parseSseBlock(decoder.decode(frame.block));
|
|
267
265
|
if (payload && handlePayload(payload)) break;
|
|
268
266
|
}
|
|
269
267
|
}
|
|
270
|
-
|
|
271
|
-
if (!terminalSeen &&
|
|
272
|
-
const payload = parseSseBlock(
|
|
268
|
+
const tail = framer.finish();
|
|
269
|
+
if (!terminalSeen && tail.byteLength > 0) {
|
|
270
|
+
const payload = parseSseBlock(decoder.decode(tail));
|
|
273
271
|
if (payload) handlePayload(payload);
|
|
274
272
|
}
|
|
275
273
|
if (!terminalSeen && isCurrent() && !clientCancelled) {
|
|
@@ -277,11 +275,27 @@ export async function pumpResponsesSseToWebSocket(
|
|
|
277
275
|
sendProtocolError(ws, 502, "Upstream stream ended before response terminal event");
|
|
278
276
|
}
|
|
279
277
|
} catch (err) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
278
|
+
framer.dispose();
|
|
279
|
+
if (err instanceof WsSendDroppedError) throw err;
|
|
280
|
+
if (!terminalSeen
|
|
281
|
+
&& isCurrent()
|
|
282
|
+
&& ws.readyState === OPEN
|
|
283
|
+
&& !(err instanceof WsSendDroppedError)) {
|
|
284
|
+
reportTerminal("incomplete");
|
|
285
|
+
try {
|
|
286
|
+
sendProtocolError(ws, 502, err instanceof Error ? err.message : String(err));
|
|
287
|
+
} catch (sendErr) {
|
|
288
|
+
// If delivery is already dropped, there is no useful error frame left
|
|
289
|
+
// to send. Swallow only that expected transport signal; other failures
|
|
290
|
+
// still surface to the caller after the upstream reader is released.
|
|
291
|
+
if (!(sendErr instanceof WsSendDroppedError)) throw sendErr;
|
|
292
|
+
}
|
|
283
293
|
}
|
|
284
294
|
} finally {
|
|
295
|
+
framer.dispose();
|
|
296
|
+
// Framing errors can occur while the upstream body is still live. Always
|
|
297
|
+
// release the reader, even when terminal/send paths already cancelled it.
|
|
298
|
+
void reader.cancel().catch(() => {});
|
|
285
299
|
if (ws.data.cancel === cancel) ws.data.cancel = undefined;
|
|
286
300
|
}
|
|
287
301
|
}
|
|
@@ -301,25 +315,12 @@ export function sendResponsesJsonAsEvents(
|
|
|
301
315
|
}
|
|
302
316
|
sendTextFrame(ws, text);
|
|
303
317
|
};
|
|
304
|
-
const output = Array.isArray(response.output) ? response.output : [];
|
|
305
|
-
sendObservedFrame({
|
|
306
|
-
type: "response.created",
|
|
307
|
-
response: { ...response, status: "in_progress", output: [] },
|
|
308
|
-
});
|
|
309
|
-
output.forEach((item, outputIndex) => {
|
|
310
|
-
sendObservedFrame({
|
|
311
|
-
type: "response.output_item.done",
|
|
312
|
-
output_index: outputIndex,
|
|
313
|
-
item,
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
318
|
const finalStatus = response.status === "failed" || response.status === "incomplete"
|
|
317
319
|
? response.status
|
|
318
320
|
: "completed";
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
});
|
|
321
|
+
for (const frame of responsesJsonEventSequence(response)) {
|
|
322
|
+
sendObservedFrame(frame);
|
|
323
|
+
}
|
|
323
324
|
onTerminal?.(finalStatus);
|
|
324
325
|
}
|
|
325
326
|
|