@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
package/src/server/relay.ts
CHANGED
|
@@ -6,17 +6,21 @@ import {
|
|
|
6
6
|
addFinalRequestLog,
|
|
7
7
|
httpStatusForRequestLogTerminal,
|
|
8
8
|
inspectResponseLogJson,
|
|
9
|
-
inspectResponseLogSsePayload,
|
|
10
9
|
inspectResponseLogSsePayloadParsed,
|
|
11
10
|
recordFirstOutput,
|
|
12
11
|
type RequestLogContext,
|
|
13
12
|
type RequestLogEntry,
|
|
14
13
|
} from "./request-log";
|
|
14
|
+
import {
|
|
15
|
+
BoundedSseFrameBuffer,
|
|
16
|
+
joinSseFrameBytes,
|
|
17
|
+
MAX_CLIENT_SSE_FRAME_BYTES,
|
|
18
|
+
} from "./sse-frame-buffer";
|
|
15
19
|
|
|
16
20
|
const nativePassthroughSseResponses = new WeakSet<Response>();
|
|
17
21
|
const eagerRelaySseResponses = new WeakSet<Response>();
|
|
18
22
|
|
|
19
|
-
export const MAX_INSPECTION_SSE_FRAME_BYTES =
|
|
23
|
+
export const MAX_INSPECTION_SSE_FRAME_BYTES = MAX_CLIENT_SSE_FRAME_BYTES;
|
|
20
24
|
export const MAX_COMPLETED_OUTPUT_ITEMS = 256;
|
|
21
25
|
export const MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES = 8 * 1024 * 1024;
|
|
22
26
|
export const MAX_TAIL_ERROR_MESSAGE_CHARS = 512;
|
|
@@ -95,6 +99,74 @@ export function buildFailedTailPayload(err: unknown): string {
|
|
|
95
99
|
});
|
|
96
100
|
}
|
|
97
101
|
|
|
102
|
+
export type SseTerminalOutputBoundary = {
|
|
103
|
+
feed(chunk: Uint8Array): Uint8Array;
|
|
104
|
+
finish(): Uint8Array;
|
|
105
|
+
terminalSeen(): boolean;
|
|
106
|
+
doneSeen(): boolean;
|
|
107
|
+
dispose(): void;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Frame-aware client output boundary shared by both native Responses relays.
|
|
112
|
+
* It buffers only the current incomplete SSE block under the same hard byte
|
|
113
|
+
* cap as inspection, forwards complete blocks through the first Responses
|
|
114
|
+
* terminal, and drops every later block/byte.
|
|
115
|
+
*/
|
|
116
|
+
export function createSseTerminalOutputBoundary(): SseTerminalOutputBoundary {
|
|
117
|
+
const decoder = new TextDecoder();
|
|
118
|
+
const framer = new BoundedSseFrameBuffer(MAX_INSPECTION_SSE_FRAME_BYTES);
|
|
119
|
+
let terminal = false;
|
|
120
|
+
let done = false;
|
|
121
|
+
let disposed = false;
|
|
122
|
+
|
|
123
|
+
const processFrames = (
|
|
124
|
+
frames: ReturnType<BoundedSseFrameBuffer["feed"]>,
|
|
125
|
+
): Uint8Array => {
|
|
126
|
+
if (disposed || terminal || frames.length === 0) return new Uint8Array(0);
|
|
127
|
+
const output: Uint8Array[] = [];
|
|
128
|
+
let responsesTerminal = false;
|
|
129
|
+
for (const frame of frames) {
|
|
130
|
+
const payload = sseDataPayload(decoder.decode(frame.block));
|
|
131
|
+
const isDone = payload === "[DONE]";
|
|
132
|
+
// Preserve every frame through the first Responses terminal. A [DONE]
|
|
133
|
+
// frame is also preserved when it immediately follows that terminal in
|
|
134
|
+
// the same upstream chunk; every later non-DONE frame is dropped.
|
|
135
|
+
if (!responsesTerminal || isDone) output.push(frame.block, frame.delimiter);
|
|
136
|
+
if (isDone) {
|
|
137
|
+
done = true;
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (!responsesTerminal && payload && terminalStatusFromSsePayload(payload)) {
|
|
141
|
+
responsesTerminal = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (responsesTerminal) {
|
|
145
|
+
terminal = true;
|
|
146
|
+
framer.dispose();
|
|
147
|
+
}
|
|
148
|
+
return joinSseFrameBytes(output);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
feed(chunk) {
|
|
153
|
+
if (disposed || terminal) return new Uint8Array(0);
|
|
154
|
+
return processFrames(framer.feed(chunk));
|
|
155
|
+
},
|
|
156
|
+
finish() {
|
|
157
|
+
if (disposed || terminal) return new Uint8Array(0);
|
|
158
|
+
return framer.finish();
|
|
159
|
+
},
|
|
160
|
+
terminalSeen: () => terminal,
|
|
161
|
+
doneSeen: () => done,
|
|
162
|
+
dispose() {
|
|
163
|
+
if (disposed) return;
|
|
164
|
+
disposed = true;
|
|
165
|
+
framer.dispose();
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
98
170
|
/**
|
|
99
171
|
* Relay a passthrough SSE body like relayWithAbort, but convert a MID-STREAM failure (upstream
|
|
100
172
|
* reset after headers) into a clean terminal: any partial block is closed off, then a synthetic
|
|
@@ -110,18 +182,64 @@ export function relaySseWithFailedTail(
|
|
|
110
182
|
): ReadableStream<Uint8Array> {
|
|
111
183
|
const reader = body.getReader();
|
|
112
184
|
const encoder = new TextEncoder();
|
|
185
|
+
const terminalBoundary = createSseTerminalOutputBoundary();
|
|
186
|
+
let closed = false;
|
|
187
|
+
const relayChunk = (
|
|
188
|
+
controller: ReadableStreamDefaultController<Uint8Array>,
|
|
189
|
+
value: Uint8Array,
|
|
190
|
+
): "terminal" | "output" | "buffered" => {
|
|
191
|
+
const outbound = terminalBoundary.feed(value);
|
|
192
|
+
if (outbound.byteLength > 0) controller.enqueue(outbound);
|
|
193
|
+
if (!terminalBoundary.terminalSeen()) return outbound.byteLength > 0 ? "output" : "buffered";
|
|
194
|
+
|
|
195
|
+
// A Responses terminal frame is the protocol boundary. Some compatible
|
|
196
|
+
// gateways leave the HTTP connection open after response.completed, which
|
|
197
|
+
// otherwise leaves Codex waiting forever even though the model turn is done.
|
|
198
|
+
// Preserve through the terminal block only, add the conventional sentinel
|
|
199
|
+
// when there was no real [DONE] data event, then stop reading upstream.
|
|
200
|
+
if (!terminalBoundary.doneSeen()) {
|
|
201
|
+
controller.enqueue(encoder.encode("data: [DONE]\n\n"));
|
|
202
|
+
}
|
|
203
|
+
closed = true;
|
|
204
|
+
controller.close();
|
|
205
|
+
const reason = "Responses terminal event received";
|
|
206
|
+
// Notify the tee inspection branch as well. It has already received the
|
|
207
|
+
// same terminal-bearing upstream chunk, so its bounded drain records the
|
|
208
|
+
// real terminal and then releases the turn/upstream keep-alive connection.
|
|
209
|
+
onClientGone?.(reason);
|
|
210
|
+
reader.cancel(reason).catch(() => {});
|
|
211
|
+
terminalBoundary.dispose();
|
|
212
|
+
return "terminal";
|
|
213
|
+
};
|
|
113
214
|
return new ReadableStream<Uint8Array>({
|
|
114
215
|
async pull(controller) {
|
|
115
216
|
try {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
217
|
+
for (;;) {
|
|
218
|
+
const { done, value } = await reader.read();
|
|
219
|
+
if (done) {
|
|
220
|
+
const tail = terminalBoundary.finish();
|
|
221
|
+
if (tail.byteLength > 0) controller.enqueue(tail);
|
|
222
|
+
terminalBoundary.dispose();
|
|
223
|
+
controller.close();
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const result = relayChunk(controller, value);
|
|
227
|
+
if (result !== "buffered") return;
|
|
120
228
|
}
|
|
121
|
-
controller.enqueue(value);
|
|
122
229
|
} catch (err) {
|
|
230
|
+
let partial: Uint8Array = new Uint8Array(0);
|
|
231
|
+
try {
|
|
232
|
+
partial = terminalBoundary.finish();
|
|
233
|
+
} catch {
|
|
234
|
+
// A near-cap ambiguous delimiter tail may itself overflow at EOF.
|
|
235
|
+
// Preserve the original read/framing failure and continue emitting
|
|
236
|
+
// the bounded failed tail instead of letting cleanup throw again.
|
|
237
|
+
}
|
|
238
|
+
terminalBoundary.dispose();
|
|
239
|
+
if (closed) return;
|
|
123
240
|
const payload = buildFailedTailPayload(err);
|
|
124
241
|
try {
|
|
242
|
+
if (partial.byteLength > 0) controller.enqueue(partial);
|
|
125
243
|
// Leading blank line terminates a partial SSE block so the failed frame parses cleanly.
|
|
126
244
|
controller.enqueue(encoder.encode(`\n\nevent: response.failed\ndata: ${payload}\n\ndata: [DONE]\n\n`));
|
|
127
245
|
controller.close();
|
|
@@ -130,6 +248,7 @@ export function relaySseWithFailedTail(
|
|
|
130
248
|
}
|
|
131
249
|
},
|
|
132
250
|
cancel(reason) {
|
|
251
|
+
terminalBoundary.dispose();
|
|
133
252
|
if (onClientGone) onClientGone(reason);
|
|
134
253
|
else upstream.abort(reason);
|
|
135
254
|
reader.cancel(reason).catch(() => {});
|
|
@@ -137,11 +256,12 @@ export function relaySseWithFailedTail(
|
|
|
137
256
|
});
|
|
138
257
|
}
|
|
139
258
|
|
|
140
|
-
export function nextSseBlock(buffer: string): { block: string; rest: string } | null {
|
|
259
|
+
export function nextSseBlock(buffer: string): { block: string; delimiter: string; rest: string } | null {
|
|
141
260
|
const match = buffer.match(/\r?\n\r?\n/);
|
|
142
261
|
if (!match || match.index === undefined) return null;
|
|
143
262
|
return {
|
|
144
263
|
block: buffer.slice(0, match.index),
|
|
264
|
+
delimiter: match[0],
|
|
145
265
|
rest: buffer.slice(match.index + match[0].length),
|
|
146
266
|
};
|
|
147
267
|
}
|
|
@@ -245,53 +365,52 @@ export function trackSseForRequestLog(
|
|
|
245
365
|
onFirstOutput?: () => void,
|
|
246
366
|
): ReadableStream<Uint8Array> {
|
|
247
367
|
const reader = body.getReader();
|
|
248
|
-
const decoder = new TextDecoder();
|
|
249
|
-
let buffer = "";
|
|
250
368
|
let terminalReported = false;
|
|
251
|
-
|
|
369
|
+
let cancelled = false;
|
|
252
370
|
|
|
253
371
|
const reportTerminal = (status: ResponsesTerminalStatus) => {
|
|
254
372
|
if (terminalReported) return;
|
|
255
373
|
terminalReported = true;
|
|
256
374
|
onTerminal(status);
|
|
257
375
|
};
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
const inspectChunk = (value: Uint8Array) => {
|
|
268
|
-
buffer += decoder.decode(value, { stream: true });
|
|
269
|
-
let next: { block: string; rest: string } | null;
|
|
270
|
-
while ((next = nextSseBlock(buffer))) {
|
|
271
|
-
buffer = next.rest;
|
|
272
|
-
inspectPayload(sseDataPayload(next.block));
|
|
273
|
-
}
|
|
274
|
-
};
|
|
376
|
+
// Reuse the byte-bounded inspector so translated responses cannot retain an
|
|
377
|
+
// unterminated upstream frame or parse the same event once per observer.
|
|
378
|
+
const inspector = createSseInspector({
|
|
379
|
+
onTerminal: reportTerminal,
|
|
380
|
+
logCtx,
|
|
381
|
+
onFirstOutput,
|
|
382
|
+
});
|
|
275
383
|
|
|
276
384
|
return new ReadableStream<Uint8Array>({
|
|
277
385
|
async pull(controller) {
|
|
278
386
|
try {
|
|
279
387
|
const { done, value } = await reader.read();
|
|
280
388
|
if (done) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
389
|
+
if (!cancelled) {
|
|
390
|
+
inspector.finish();
|
|
391
|
+
if (!terminalReported) reportTerminal("incomplete");
|
|
392
|
+
}
|
|
393
|
+
inspector.dispose();
|
|
284
394
|
controller.close();
|
|
285
395
|
return;
|
|
286
396
|
}
|
|
287
|
-
|
|
397
|
+
inspector.feed(value);
|
|
288
398
|
controller.enqueue(value);
|
|
289
399
|
} catch (err) {
|
|
290
|
-
|
|
400
|
+
// The upstream read rejected: the 200 body died mid-flight. Client
|
|
401
|
+
// cancellation is the caller's separate 499 path, so a cancel-drained
|
|
402
|
+
// pending read (cancelled=true) must not carry the truncation marker.
|
|
403
|
+
if (!cancelled && !terminalReported && logCtx?.activeAttempt) {
|
|
404
|
+
logCtx.activeAttempt.streamAborted = true;
|
|
405
|
+
}
|
|
406
|
+
if (!cancelled && !terminalReported) reportTerminal("incomplete");
|
|
407
|
+
inspector.dispose();
|
|
291
408
|
try { controller.error(err); } catch { /* already torn down */ }
|
|
292
409
|
}
|
|
293
410
|
},
|
|
294
411
|
cancel(reason) {
|
|
412
|
+
cancelled = true;
|
|
413
|
+
inspector.dispose();
|
|
295
414
|
onCancel();
|
|
296
415
|
reader.cancel(reason).catch(() => {});
|
|
297
416
|
},
|
|
@@ -402,38 +521,23 @@ export function relaySseWithHeartbeat(
|
|
|
402
521
|
): ReadableStream<Uint8Array> | null {
|
|
403
522
|
if (!body) return null;
|
|
404
523
|
const reader = body.getReader();
|
|
405
|
-
const decoder = new TextDecoder();
|
|
406
524
|
const heartbeat = new TextEncoder().encode(": opencodex keepalive\n\n");
|
|
407
525
|
let timer: ReturnType<typeof setInterval> | undefined;
|
|
408
526
|
let closed = false;
|
|
409
527
|
let clientCancelled = false;
|
|
410
528
|
let terminalReported = false;
|
|
411
|
-
let buffer = "";
|
|
412
529
|
|
|
413
530
|
const reportTerminal = (status: ResponsesTerminalStatus) => {
|
|
414
531
|
if (terminalReported || clientCancelled || closed) return;
|
|
415
532
|
terminalReported = true;
|
|
416
533
|
onTerminal?.(status);
|
|
417
534
|
};
|
|
418
|
-
|
|
419
|
-
const inspectPayload = (payload: string | null) => {
|
|
420
|
-
if (!payload) return;
|
|
421
|
-
const status = terminalStatusFromSsePayload(payload);
|
|
422
|
-
if (status) reportTerminal(status);
|
|
423
|
-
};
|
|
424
|
-
|
|
425
|
-
const inspectChunk = (value: Uint8Array) => {
|
|
426
|
-
buffer += decoder.decode(value, { stream: true });
|
|
427
|
-
let next: { block: string; rest: string } | null;
|
|
428
|
-
while ((next = nextSseBlock(buffer))) {
|
|
429
|
-
buffer = next.rest;
|
|
430
|
-
inspectPayload(sseDataPayload(next.block));
|
|
431
|
-
}
|
|
432
|
-
};
|
|
535
|
+
const inspector = createSseInspector({ onTerminal: reportTerminal });
|
|
433
536
|
|
|
434
537
|
const cleanup = () => {
|
|
435
538
|
if (closed) return;
|
|
436
539
|
closed = true;
|
|
540
|
+
inspector.dispose();
|
|
437
541
|
if (timer) clearInterval(timer);
|
|
438
542
|
timer = undefined;
|
|
439
543
|
options?.onDone?.();
|
|
@@ -455,14 +559,13 @@ export function relaySseWithHeartbeat(
|
|
|
455
559
|
try {
|
|
456
560
|
const { done, value } = await reader.read();
|
|
457
561
|
if (done) {
|
|
458
|
-
|
|
459
|
-
if (buffer.trim()) inspectPayload(sseDataPayload(buffer));
|
|
562
|
+
inspector.finish();
|
|
460
563
|
if (!terminalReported && !clientCancelled) reportTerminal("incomplete");
|
|
461
564
|
cleanup();
|
|
462
565
|
controller.close();
|
|
463
566
|
return;
|
|
464
567
|
}
|
|
465
|
-
|
|
568
|
+
inspector.feed(value);
|
|
466
569
|
controller.enqueue(value);
|
|
467
570
|
} catch (err) {
|
|
468
571
|
if (!clientCancelled) reportTerminal("incomplete");
|
|
@@ -500,7 +603,20 @@ export type SseInspectorHandlers = {
|
|
|
500
603
|
onTerminal?: (status: ResponsesTerminalStatus, httpStatusOverride?: number) => void;
|
|
501
604
|
logCtx?: RequestLogContext;
|
|
502
605
|
onCompletedResponse?: (response: { id?: unknown; output?: unknown; status?: unknown }) => void;
|
|
606
|
+
/**
|
|
607
|
+
* Every parsed SSE payload, delivered BEFORE any onCompletedResponse derived from that same
|
|
608
|
+
* payload. A caller that must decide on the whole turn -- not just its terminal snapshot --
|
|
609
|
+
* needs to see the incremental events, because a stream can announce an item and then close
|
|
610
|
+
* with an empty `output`.
|
|
611
|
+
*/
|
|
612
|
+
onParsedPayload?: (payload: unknown) => void;
|
|
503
613
|
onFirstOutput?: () => void;
|
|
614
|
+
/**
|
|
615
|
+
* Provider-scoped compatibility: persist the completed snapshot under the
|
|
616
|
+
* first response id exposed to the client when an upstream changes ids
|
|
617
|
+
* between `response.created` and `response.completed`.
|
|
618
|
+
*/
|
|
619
|
+
pinCompletedResponseIdToFirstSeen?: boolean;
|
|
504
620
|
};
|
|
505
621
|
|
|
506
622
|
type CompletedOutputItem = { item: unknown; sourceBytes: number };
|
|
@@ -530,17 +646,6 @@ function delimiterLengthAt(
|
|
|
530
646
|
return byteAt(index + 3) === 10 ? 4 : 0;
|
|
531
647
|
}
|
|
532
648
|
|
|
533
|
-
function joinedBytes(slices: readonly Uint8Array[], byteLength: number): Uint8Array {
|
|
534
|
-
if (slices.length === 1 && slices[0]!.byteLength === byteLength) return slices[0]!;
|
|
535
|
-
const joined = new Uint8Array(byteLength);
|
|
536
|
-
let offset = 0;
|
|
537
|
-
for (const slice of slices) {
|
|
538
|
-
joined.set(slice, offset);
|
|
539
|
-
offset += slice.byteLength;
|
|
540
|
-
}
|
|
541
|
-
return joined;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
649
|
/**
|
|
545
650
|
* Per-chunk SSE inspection state machine shared by consumeForInspection,
|
|
546
651
|
* consumeForResponseLogMetadata, and the eager bounded relay (relay-eager.ts).
|
|
@@ -561,8 +666,8 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
|
|
|
561
666
|
let reported = false;
|
|
562
667
|
let sawTerminal = false;
|
|
563
668
|
let disposed = false;
|
|
564
|
-
let delimiterTail = new Uint8Array(0);
|
|
565
|
-
let
|
|
669
|
+
let delimiterTail: Uint8Array = new Uint8Array(0);
|
|
670
|
+
let candidate: Uint8Array = new Uint8Array(0);
|
|
566
671
|
let candidateBytes = 0;
|
|
567
672
|
let discardingOversizedFrame = false;
|
|
568
673
|
const reportFirstOutput = createFirstOutputReporter(handlers.onFirstOutput);
|
|
@@ -572,10 +677,11 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
|
|
|
572
677
|
: null;
|
|
573
678
|
let aggregateItemBytes = 0;
|
|
574
679
|
let reconstructionTainted = false;
|
|
680
|
+
let firstResponseId: string | undefined;
|
|
575
681
|
|
|
576
682
|
const clearFrameState = (): void => {
|
|
577
683
|
delimiterTail = new Uint8Array(0);
|
|
578
|
-
|
|
684
|
+
candidate = new Uint8Array(0);
|
|
579
685
|
candidateBytes = 0;
|
|
580
686
|
discardingOversizedFrame = false;
|
|
581
687
|
};
|
|
@@ -592,6 +698,31 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
|
|
|
592
698
|
decoder = null;
|
|
593
699
|
clearFrameState();
|
|
594
700
|
clearCompletedItems();
|
|
701
|
+
firstResponseId = undefined;
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
const ensureCandidateCapacity = (requiredBytes: number): void => {
|
|
705
|
+
if (candidate.byteLength >= requiredBytes) return;
|
|
706
|
+
let capacity = candidate.byteLength === 0
|
|
707
|
+
? Math.min(MAX_INSPECTION_SSE_FRAME_BYTES, Math.max(requiredBytes, 4096))
|
|
708
|
+
: candidate.byteLength;
|
|
709
|
+
while (capacity < requiredBytes) {
|
|
710
|
+
capacity = Math.min(
|
|
711
|
+
MAX_INSPECTION_SSE_FRAME_BYTES,
|
|
712
|
+
Math.max(requiredBytes, capacity * 2),
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
const grown = new Uint8Array(capacity);
|
|
716
|
+
if (candidateBytes > 0) grown.set(candidate.subarray(0, candidateBytes));
|
|
717
|
+
candidate = grown;
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
const takeCandidate = (): Uint8Array => {
|
|
721
|
+
if (candidateBytes === 0) return new Uint8Array(0);
|
|
722
|
+
const frame = candidate.slice(0, candidateBytes);
|
|
723
|
+
candidate = new Uint8Array(0);
|
|
724
|
+
candidateBytes = 0;
|
|
725
|
+
return frame;
|
|
595
726
|
};
|
|
596
727
|
|
|
597
728
|
const retainCandidateSlice = (slice: Uint8Array): void => {
|
|
@@ -602,7 +733,7 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
|
|
|
602
733
|
Math.min(nextBytes, MAX_INSPECTION_SSE_FRAME_BYTES),
|
|
603
734
|
);
|
|
604
735
|
if (nextBytes > MAX_INSPECTION_SSE_FRAME_BYTES) {
|
|
605
|
-
|
|
736
|
+
candidate = new Uint8Array(0);
|
|
606
737
|
candidateBytes = 0;
|
|
607
738
|
discardingOversizedFrame = true;
|
|
608
739
|
inspectionCounters.frameCapOverflows += 1;
|
|
@@ -612,10 +743,8 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
|
|
|
612
743
|
reconstructionTainted = true;
|
|
613
744
|
return;
|
|
614
745
|
}
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
// chunk whose preceding frames have already been consumed.
|
|
618
|
-
candidateSlices.push(slice.slice());
|
|
746
|
+
ensureCandidateCapacity(nextBytes);
|
|
747
|
+
candidate.set(slice, candidateBytes);
|
|
619
748
|
candidateBytes = nextBytes;
|
|
620
749
|
};
|
|
621
750
|
|
|
@@ -664,6 +793,11 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
|
|
|
664
793
|
if (!reported && handlers.logCtx) {
|
|
665
794
|
inspectResponseLogSsePayloadParsed(handlers.logCtx, payload, parsed);
|
|
666
795
|
}
|
|
796
|
+
// Before any terminal handling: a consumer deciding on the whole turn must observe this
|
|
797
|
+
// payload even when the terminal snapshot that follows no longer mentions it.
|
|
798
|
+
if (handlers.onParsedPayload && parsed !== undefined) {
|
|
799
|
+
try { handlers.onParsedPayload(parsed); } catch { /* inspection must never throw into the pump */ }
|
|
800
|
+
}
|
|
667
801
|
reportFirstOutput.parsed(parsed);
|
|
668
802
|
const status = terminalStatusFromParsed(parsed);
|
|
669
803
|
if (status) sawTerminal = true;
|
|
@@ -686,6 +820,17 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
|
|
|
686
820
|
const parsedEvent = parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
687
821
|
? parsed as ParsedSseEvent
|
|
688
822
|
: null;
|
|
823
|
+
const responseRecord = parsedEvent
|
|
824
|
+
&& typeof parsedEvent.response === "object"
|
|
825
|
+
&& parsedEvent.response !== null
|
|
826
|
+
&& !Array.isArray(parsedEvent.response)
|
|
827
|
+
? parsedEvent.response as { id?: unknown }
|
|
828
|
+
: null;
|
|
829
|
+
if (handlers.pinCompletedResponseIdToFirstSeen
|
|
830
|
+
&& responseRecord
|
|
831
|
+
&& typeof responseRecord.id === "string") {
|
|
832
|
+
firstResponseId ??= responseRecord.id;
|
|
833
|
+
}
|
|
689
834
|
const doneItem = parsedEvent?.type === "response.output_item.done" ? parsedEvent.item : undefined;
|
|
690
835
|
if (parsedEvent
|
|
691
836
|
&& doneItem !== undefined
|
|
@@ -700,6 +845,11 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
|
|
|
700
845
|
|
|
701
846
|
let response = completedResponseFromParsedEvent(parsedEvent);
|
|
702
847
|
if (response) {
|
|
848
|
+
if (handlers.pinCompletedResponseIdToFirstSeen
|
|
849
|
+
&& firstResponseId !== undefined
|
|
850
|
+
&& response.id !== firstResponseId) {
|
|
851
|
+
response = { ...response, id: firstResponseId };
|
|
852
|
+
}
|
|
703
853
|
// Authoritative output is a NON-EMPTY ARRAY only. Anything else
|
|
704
854
|
// (missing, null, scalar, object) keeps the historical backfill
|
|
705
855
|
// behavior so a malformed terminal cannot reach rememberResponseState
|
|
@@ -735,9 +885,7 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
|
|
|
735
885
|
return;
|
|
736
886
|
}
|
|
737
887
|
const sourceBytes = candidateBytes;
|
|
738
|
-
const frame =
|
|
739
|
-
candidateSlices = [];
|
|
740
|
-
candidateBytes = 0;
|
|
888
|
+
const frame = takeCandidate();
|
|
741
889
|
if (reported && !handlers.onCompletedResponse) return;
|
|
742
890
|
const decoded = decoder!.decode(frame);
|
|
743
891
|
scanPayload(sseDataPayload(decoded), sourceBytes);
|
|
@@ -794,7 +942,7 @@ export function createSseInspector(handlers: SseInspectorHandlers): SseInspector
|
|
|
794
942
|
delimiterTail = new Uint8Array(0);
|
|
795
943
|
if (!discardingOversizedFrame && candidateBytes > 0 && !reported) {
|
|
796
944
|
const sourceBytes = candidateBytes;
|
|
797
|
-
const decoded = decoder!.decode(
|
|
945
|
+
const decoded = decoder!.decode(takeCandidate());
|
|
798
946
|
scanPayload(decoded.trim() ? sseDataPayload(decoded) : null, sourceBytes);
|
|
799
947
|
}
|
|
800
948
|
} finally {
|
|
@@ -815,6 +963,10 @@ export type InspectionConsumerOptions = {
|
|
|
815
963
|
drainBounds?: Partial<InspectionDrainBounds>;
|
|
816
964
|
upstream?: AbortController;
|
|
817
965
|
now?: () => number;
|
|
966
|
+
/** Forward provider-scoped response-id pinning to the owned inspector. */
|
|
967
|
+
pinCompletedResponseIdToFirstSeen?: boolean;
|
|
968
|
+
/** Observe every parsed SSE payload on the inspection side; see SseInspectorHandlers. */
|
|
969
|
+
onParsedPayload?: (payload: unknown) => void;
|
|
818
970
|
/** Test seam for proving both public consumers dispose their owned inspector. */
|
|
819
971
|
inspectorFactory?: (handlers: SseInspectorHandlers) => SseInspector;
|
|
820
972
|
};
|
|
@@ -970,7 +1122,9 @@ export function consumeForInspection(
|
|
|
970
1122
|
onTerminal,
|
|
971
1123
|
logCtx,
|
|
972
1124
|
onCompletedResponse,
|
|
1125
|
+
onParsedPayload: options?.onParsedPayload,
|
|
973
1126
|
onFirstOutput,
|
|
1127
|
+
pinCompletedResponseIdToFirstSeen: options?.pinCompletedResponseIdToFirstSeen,
|
|
974
1128
|
});
|
|
975
1129
|
startBoundedInspectionPump({
|
|
976
1130
|
...options,
|
|
@@ -993,6 +1147,10 @@ export function consumeForInspection(
|
|
|
993
1147
|
if (logCtx) {
|
|
994
1148
|
logCtx.transportPhase = "mid_stream";
|
|
995
1149
|
logCtx.terminalSource = "synthetic";
|
|
1150
|
+
// A truncated 200 body must not meter as a success the client never
|
|
1151
|
+
// received; the router's equivalent turn carries 502 + streamAborted
|
|
1152
|
+
// (codex-router #139).
|
|
1153
|
+
if (logCtx.activeAttempt) logCtx.activeAttempt.streamAborted = true;
|
|
996
1154
|
}
|
|
997
1155
|
onTerminal("failed", 502);
|
|
998
1156
|
}
|
|
@@ -1015,7 +1173,9 @@ export function consumeForResponseLogMetadata(
|
|
|
1015
1173
|
const inspector = (options?.inspectorFactory ?? createSseInspector)({
|
|
1016
1174
|
logCtx,
|
|
1017
1175
|
onCompletedResponse,
|
|
1176
|
+
onParsedPayload: options?.onParsedPayload,
|
|
1018
1177
|
onFirstOutput,
|
|
1178
|
+
pinCompletedResponseIdToFirstSeen: options?.pinCompletedResponseIdToFirstSeen,
|
|
1019
1179
|
});
|
|
1020
1180
|
startBoundedInspectionPump({ ...options, reader, inspector, signal, onDone });
|
|
1021
1181
|
}
|