@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
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import type { AdapterEvent, OcxConfig, OcxUsage } from "../../types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Empty-completion guard for Responses turns (port of codex-router's
|
|
5
|
+
* empty-completion-guard + single retry, PR #145).
|
|
6
|
+
*
|
|
7
|
+
* Failure mode: the upstream answers 200 and completes the turn but never
|
|
8
|
+
* produced output text or a tool call (a reasoning-only stream that ends with
|
|
9
|
+
* nothing is the canonical shape). The client has no code path for "the model
|
|
10
|
+
* said nothing", so it silently records the turn as done — the "random stop"
|
|
11
|
+
* nobody can explain. The guard holds pre-content events (reasoning deltas
|
|
12
|
+
* are deliberately NOT content), and when a terminal event arrives with no
|
|
13
|
+
* content it suppresses the terminal and retries the IDENTICAL turn once
|
|
14
|
+
* (same request bytes, same headers). If the retry is also empty — or fails
|
|
15
|
+
* upstream — the client sees a stated failure instead of a second silent
|
|
16
|
+
* success.
|
|
17
|
+
*
|
|
18
|
+
* The retry is explicitly enabled by top-level config. The environment switch
|
|
19
|
+
* is a disable-only emergency override: OCX_EMPTY_COMPLETION_RETRY=0 restores
|
|
20
|
+
* the previous relay behavior without editing the persisted config.
|
|
21
|
+
*/
|
|
22
|
+
export const EMPTY_COMPLETION_RETRY_ENV = "OCX_EMPTY_COMPLETION_RETRY";
|
|
23
|
+
|
|
24
|
+
/** Retained pre-content events are bounded independently by count and encoded size. */
|
|
25
|
+
export const EMPTY_COMPLETION_MAX_BUFFERED_EVENTS = 1_024;
|
|
26
|
+
export const EMPTY_COMPLETION_MAX_BUFFERED_BYTES = 1_048_576;
|
|
27
|
+
|
|
28
|
+
export function emptyCompletionRetryEnabled(
|
|
29
|
+
config: Pick<OcxConfig, "emptyCompletionRetry">,
|
|
30
|
+
env: Record<string, string | undefined> = process.env,
|
|
31
|
+
): boolean {
|
|
32
|
+
return config.emptyCompletionRetry === true && env[EMPTY_COMPLETION_RETRY_ENV] !== "0";
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Surfaced when the single retry was also empty or failed upstream. */
|
|
36
|
+
export const EMPTY_COMPLETION_RETRY_FAILED_CODE = "empty_completion_retry_failed";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Terminal stop reasons the bridge renders as a visible `response.incomplete`
|
|
40
|
+
* (max_tokens / content_filter). Those are already a stated failure, not the
|
|
41
|
+
* silent empty success this guard exists to catch, and retrying the identical
|
|
42
|
+
* request would burn tokens for the same truncated result.
|
|
43
|
+
*/
|
|
44
|
+
const VISIBLE_INCOMPLETE_STOP_REASONS = new Set(["max_tokens", "content_filter"]);
|
|
45
|
+
const UTF8_ENCODER = new TextEncoder();
|
|
46
|
+
|
|
47
|
+
function retainedEventBytes(event: AdapterEvent): number {
|
|
48
|
+
return UTF8_ENCODER.encode(JSON.stringify(event)).byteLength;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function isReasoningEvent(event: AdapterEvent): boolean {
|
|
52
|
+
return event.type === "thinking_delta"
|
|
53
|
+
|| event.type === "thinking_signature"
|
|
54
|
+
|| event.type === "redacted_thinking"
|
|
55
|
+
|| event.type === "kiro_redacted_reasoning"
|
|
56
|
+
|| event.type === "reasoning_raw_delta";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isTerminalEvent(
|
|
60
|
+
event: AdapterEvent,
|
|
61
|
+
): event is Extract<AdapterEvent, { type: "done" | "incomplete" | "error" }> {
|
|
62
|
+
return event.type === "done" || event.type === "incomplete" || event.type === "error";
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Content means something the client can act on: output text or a tool call
|
|
67
|
+
* (web-search cells included). Reasoning deltas are deliberately not content —
|
|
68
|
+
* a turn that streams only reasoning and then completes with nothing is
|
|
69
|
+
* exactly the empty completion this guard exists to catch. Empty text deltas
|
|
70
|
+
* (some batch adapters always carry `""`) are not content either.
|
|
71
|
+
*/
|
|
72
|
+
export function isContentEvent(event: AdapterEvent): boolean {
|
|
73
|
+
switch (event.type) {
|
|
74
|
+
case "text_delta":
|
|
75
|
+
return event.text.length > 0;
|
|
76
|
+
case "tool_call_start":
|
|
77
|
+
case "tool_call_delta":
|
|
78
|
+
case "tool_call_end":
|
|
79
|
+
case "web_search_call_begin":
|
|
80
|
+
case "web_search_call_end":
|
|
81
|
+
return true;
|
|
82
|
+
default:
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function emptyCompletionRetryFailedEvent(
|
|
88
|
+
usage?: OcxUsage,
|
|
89
|
+
retryFailedUpstream = false,
|
|
90
|
+
): Extract<AdapterEvent, { type: "error" }> {
|
|
91
|
+
return {
|
|
92
|
+
type: "error",
|
|
93
|
+
status: 502,
|
|
94
|
+
errorType: "upstream_error",
|
|
95
|
+
code: EMPTY_COMPLETION_RETRY_FAILED_CODE,
|
|
96
|
+
message: retryFailedUpstream
|
|
97
|
+
? "The model returned an empty completion and the retry failed upstream."
|
|
98
|
+
: "The model returned an empty completion. opencodex retried once and the completion was empty again.",
|
|
99
|
+
...(usage ? { usage } : {}),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Sum two usage snapshots. Same semantics as terminal-guard's mergeUsage and
|
|
105
|
+
* request-log's aggregateAttemptUsage: token totals add across the attempts;
|
|
106
|
+
* `estimated` wins when either attempt only estimated.
|
|
107
|
+
*/
|
|
108
|
+
export function mergeUsage(
|
|
109
|
+
first: OcxUsage | undefined,
|
|
110
|
+
second: OcxUsage | undefined,
|
|
111
|
+
): OcxUsage | undefined {
|
|
112
|
+
if (!first) return second;
|
|
113
|
+
if (!second) return first;
|
|
114
|
+
const sumOptional = (key: keyof OcxUsage): number | undefined => {
|
|
115
|
+
const left = first[key];
|
|
116
|
+
const right = second[key];
|
|
117
|
+
return typeof left === "number" || typeof right === "number"
|
|
118
|
+
? (typeof left === "number" ? left : 0) + (typeof right === "number" ? right : 0)
|
|
119
|
+
: undefined;
|
|
120
|
+
};
|
|
121
|
+
const cachedInputTokens = sumOptional("cachedInputTokens");
|
|
122
|
+
const cacheReadInputTokens = sumOptional("cacheReadInputTokens");
|
|
123
|
+
const cacheCreationInputTokens = sumOptional("cacheCreationInputTokens");
|
|
124
|
+
const reasoningOutputTokens = sumOptional("reasoningOutputTokens");
|
|
125
|
+
const contextTotalTokens = second.contextTotalTokens ?? first.contextTotalTokens;
|
|
126
|
+
const inputTokens = first.inputTokens + second.inputTokens;
|
|
127
|
+
const outputTokens = first.outputTokens + second.outputTokens;
|
|
128
|
+
return {
|
|
129
|
+
inputTokens,
|
|
130
|
+
outputTokens,
|
|
131
|
+
totalTokens: inputTokens + outputTokens,
|
|
132
|
+
...(contextTotalTokens !== undefined ? { contextTotalTokens } : {}),
|
|
133
|
+
...(cachedInputTokens !== undefined ? { cachedInputTokens } : {}),
|
|
134
|
+
...(cacheReadInputTokens !== undefined ? { cacheReadInputTokens } : {}),
|
|
135
|
+
...(cacheCreationInputTokens !== undefined ? { cacheCreationInputTokens } : {}),
|
|
136
|
+
...(reasoningOutputTokens !== undefined ? { reasoningOutputTokens } : {}),
|
|
137
|
+
...(first.estimated || second.estimated ? { estimated: true } : {}),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export interface EmptyCompletionGuardOptions {
|
|
142
|
+
firstEvents: AsyncIterable<AdapterEvent>;
|
|
143
|
+
/**
|
|
144
|
+
* Re-run the IDENTICAL turn: same request body, same headers, same signal.
|
|
145
|
+
* Receives no arguments — the request must not be modified between attempts.
|
|
146
|
+
*/
|
|
147
|
+
continuation: () => AsyncIterable<AdapterEvent> | Promise<AsyncIterable<AdapterEvent>>;
|
|
148
|
+
/** How many times an empty completion is retried; default 1 (the router's single retry). */
|
|
149
|
+
maxRetries?: number;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Watch an adapter event stream for the empty-completion failure mode. Events
|
|
154
|
+
* are held until the turn produces content or ends: reasoning and other
|
|
155
|
+
* pre-content events stay buffered (released in order on first content), the
|
|
156
|
+
* terminal is withheld, and an empty terminal triggers one identical-turn
|
|
157
|
+
* retry through `continuation`. Usage is merged across attempts so the bridge
|
|
158
|
+
* and request log meter the whole turn, not just the attempt that succeeded.
|
|
159
|
+
*
|
|
160
|
+
* Heartbeats always pass through untouched: they feed the bridge's stall
|
|
161
|
+
* watchdog, so holding them behind the content gate would trip false
|
|
162
|
+
* upstream_stall_timeout failures on slow reasoning-only turns.
|
|
163
|
+
*/
|
|
164
|
+
export async function* guardEmptyCompletionEventStream(
|
|
165
|
+
options: EmptyCompletionGuardOptions,
|
|
166
|
+
): AsyncGenerator<AdapterEvent> {
|
|
167
|
+
const maxRetries = Math.max(0, Math.floor(options.maxRetries ?? 1));
|
|
168
|
+
let source = options.firstEvents;
|
|
169
|
+
let held: AdapterEvent[] = [];
|
|
170
|
+
let heldBytes = 0;
|
|
171
|
+
let sawContent = false;
|
|
172
|
+
let passthrough = false;
|
|
173
|
+
let retries = 0;
|
|
174
|
+
let usage: OcxUsage | undefined;
|
|
175
|
+
|
|
176
|
+
const withUsage = (event: AdapterEvent & { usage?: OcxUsage }): AdapterEvent => {
|
|
177
|
+
const merged = mergeUsage(usage, event.usage);
|
|
178
|
+
return merged ? { ...event, ...(merged ? { usage: merged } : {}) } : event;
|
|
179
|
+
};
|
|
180
|
+
const releaseHeld = (): AdapterEvent[] => {
|
|
181
|
+
const released = held;
|
|
182
|
+
held = [];
|
|
183
|
+
heldBytes = 0;
|
|
184
|
+
return released;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
while (true) {
|
|
188
|
+
let terminalSeen = false;
|
|
189
|
+
for await (const event of source) {
|
|
190
|
+
if (event.type === "heartbeat") {
|
|
191
|
+
yield event;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (sawContent || passthrough) {
|
|
195
|
+
// Buffered content is already flowing; everything downstream passes
|
|
196
|
+
// through. Every terminal carries usage merged across every attempt.
|
|
197
|
+
yield isTerminalEvent(event) ? withUsage(event) : event;
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (isContentEvent(event)) {
|
|
201
|
+
sawContent = true;
|
|
202
|
+
yield* releaseHeld();
|
|
203
|
+
yield event;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (event.type === "done") {
|
|
207
|
+
usage = mergeUsage(usage, event.usage);
|
|
208
|
+
if (event.stopReason !== undefined && VISIBLE_INCOMPLETE_STOP_REASONS.has(event.stopReason)) {
|
|
209
|
+
// Rendered as response.incomplete: a stated failure, not the silent
|
|
210
|
+
// empty success this guard exists to catch.
|
|
211
|
+
yield* releaseHeld();
|
|
212
|
+
yield { ...event, ...(usage ? { usage } : {}) };
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (retries < maxRetries) {
|
|
216
|
+
// Suppress the terminal: the client must never see a completed event
|
|
217
|
+
// for a turn that produced nothing. Retry the identical turn.
|
|
218
|
+
retries += 1;
|
|
219
|
+
try {
|
|
220
|
+
source = await options.continuation();
|
|
221
|
+
} catch {
|
|
222
|
+
yield emptyCompletionRetryFailedEvent(usage, true);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
terminalSeen = true;
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
// The retry was also empty: a stated failure, not a second silent
|
|
229
|
+
// success.
|
|
230
|
+
yield emptyCompletionRetryFailedEvent(usage);
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
if (event.type === "error") {
|
|
234
|
+
if (retries > 0 && event.status !== 499) {
|
|
235
|
+
// The retry failed upstream. Its body cannot reach the client (the
|
|
236
|
+
// 200 head went out with the first attempt), so state the failure in
|
|
237
|
+
// the stream's own error framing — same move as the router's
|
|
238
|
+
// empty_completion_retry_failed. Client cancels (499) pass through.
|
|
239
|
+
yield emptyCompletionRetryFailedEvent(mergeUsage(usage, event.usage), true);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
yield* releaseHeld();
|
|
243
|
+
yield withUsage(event);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (event.type === "incomplete") {
|
|
247
|
+
// A structured incomplete is already a visible failure; never convert
|
|
248
|
+
// it into an empty completion.
|
|
249
|
+
yield* releaseHeld();
|
|
250
|
+
yield withUsage(event);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
const eventBytes = retainedEventBytes(event);
|
|
254
|
+
if (held.length + 1 > EMPTY_COMPLETION_MAX_BUFFERED_EVENTS
|
|
255
|
+
|| heldBytes + eventBytes > EMPTY_COMPLETION_MAX_BUFFERED_BYTES) {
|
|
256
|
+
// Preserve data rather than retaining without bound: release the prefix,
|
|
257
|
+
// emit this event, and stop attempting an empty-completion retry for the turn.
|
|
258
|
+
yield* releaseHeld();
|
|
259
|
+
yield event;
|
|
260
|
+
passthrough = true;
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
held.push(event);
|
|
264
|
+
heldBytes += eventBytes;
|
|
265
|
+
// The bridge watchdog sees only yielded events. Feed it while reasoning is
|
|
266
|
+
// held so a long reasoning-only prefix remains live without exposing it early.
|
|
267
|
+
if (isReasoningEvent(event)) yield { type: "heartbeat" };
|
|
268
|
+
}
|
|
269
|
+
if (!terminalSeen) {
|
|
270
|
+
// The source ended without a terminal event (truncated stream). Release
|
|
271
|
+
// what was held so the bridge can mark the stream incomplete.
|
|
272
|
+
yield* releaseHeld();
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
@@ -145,6 +145,10 @@ function isStructurallyValidFernetToken(token: string): boolean {
|
|
|
145
145
|
return ciphertextLength >= 16 && ciphertextLength % 16 === 0;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
export function structurallyValidFernetTokens(payload: string): string[] {
|
|
149
|
+
return fernetTokenRuns(payload).map(run => run.token);
|
|
150
|
+
}
|
|
151
|
+
|
|
148
152
|
/** Maximal, boundary-delimited and structurally valid Fernet runs embedded in a slot. */
|
|
149
153
|
function fernetTokenRuns(payload: string): FernetTokenRun[] {
|
|
150
154
|
const runs: FernetTokenRun[] = [];
|
|
@@ -261,48 +265,67 @@ export function hasEncryptedContentPart(content: unknown): boolean {
|
|
|
261
265
|
export function sanitizeEncryptedContentInPlace(input: unknown): number {
|
|
262
266
|
if (!Array.isArray(input)) return 0;
|
|
263
267
|
let rewritten = 0;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
268
|
+
type VisitFrame =
|
|
269
|
+
| { kind: "visit"; node: unknown }
|
|
270
|
+
| { kind: "array"; node: unknown[]; index: number }
|
|
271
|
+
| { kind: "object"; values: unknown[]; index: number }
|
|
272
|
+
| { kind: "agent"; message: Record<string, unknown>; rewrittenBefore: number };
|
|
273
|
+
const stack: VisitFrame[] = [{ kind: "visit", node: input }];
|
|
274
|
+
|
|
275
|
+
while (stack.length > 0) {
|
|
276
|
+
const frame = stack.pop()!;
|
|
277
|
+
if (frame.kind === "visit") {
|
|
278
|
+
if (Array.isArray(frame.node)) {
|
|
279
|
+
stack.push({ kind: "array", node: frame.node, index: 0 });
|
|
280
|
+
} else if (frame.node && typeof frame.node === "object") {
|
|
281
|
+
stack.push({ kind: "object", values: Object.values(frame.node), index: 0 });
|
|
282
|
+
}
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (frame.kind === "array") {
|
|
287
|
+
if (frame.index >= frame.node.length) continue;
|
|
288
|
+
const child = frame.node[frame.index] as unknown;
|
|
289
|
+
if (
|
|
290
|
+
child && typeof child === "object"
|
|
291
|
+
&& (child as { type?: unknown }).type === "encrypted_content"
|
|
292
|
+
&& typeof (child as { encrypted_content?: unknown }).encrypted_content === "string"
|
|
293
|
+
) {
|
|
294
|
+
const payload = (child as { encrypted_content: string }).encrypted_content;
|
|
295
|
+
if (!looksLikeBackendCiphertext(payload)) {
|
|
296
|
+
const parts = encryptedSlotParts(payload);
|
|
297
|
+
frame.node.splice(frame.index, 1, ...parts);
|
|
298
|
+
rewritten += 1;
|
|
299
|
+
stack.push({ kind: "array", node: frame.node, index: frame.index + parts.length });
|
|
300
|
+
continue;
|
|
296
301
|
}
|
|
297
302
|
}
|
|
298
|
-
|
|
303
|
+
stack.push({ kind: "array", node: frame.node, index: frame.index + 1 });
|
|
304
|
+
if (child && typeof child === "object" && (child as { type?: unknown }).type === "agent_message") {
|
|
305
|
+
stack.push({ kind: "agent", message: child as Record<string, unknown>, rewrittenBefore: rewritten });
|
|
306
|
+
}
|
|
307
|
+
stack.push({ kind: "visit", node: child });
|
|
308
|
+
continue;
|
|
299
309
|
}
|
|
300
|
-
|
|
301
|
-
|
|
310
|
+
|
|
311
|
+
if (frame.kind === "object") {
|
|
312
|
+
if (frame.index >= frame.values.length) continue;
|
|
313
|
+
stack.push({ kind: "object", values: frame.values, index: frame.index + 1 });
|
|
314
|
+
stack.push({ kind: "visit", node: frame.values[frame.index] });
|
|
315
|
+
continue;
|
|
302
316
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
317
|
+
|
|
318
|
+
if (
|
|
319
|
+
rewritten > frame.rewrittenBefore
|
|
320
|
+
&& frame.message.type === "agent_message"
|
|
321
|
+
&& !hasEncryptedContentPart(frame.message.content)
|
|
322
|
+
) {
|
|
323
|
+
frame.message.type = "message";
|
|
324
|
+
frame.message.role = "user";
|
|
325
|
+
delete frame.message.id;
|
|
326
|
+
delete frame.message.author;
|
|
327
|
+
delete frame.message.recipient;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
306
330
|
return rewritten;
|
|
307
331
|
}
|
|
308
|
-
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { Server } from "bun";
|
|
2
|
+
import {
|
|
3
|
+
codexWsUpstreamFetch,
|
|
4
|
+
currentBunRuntimeIdentity,
|
|
5
|
+
shouldUseCodexWsUpstream,
|
|
6
|
+
type BunRuntimeGateInput,
|
|
7
|
+
} from "./ws-upstream";
|
|
2
8
|
import { bridgeToResponsesSSE, buildResponseJSON, formatErrorResponse, type ResponsesTerminalStatus } from "../../bridge";
|
|
3
9
|
import {
|
|
4
10
|
getConfigPath,
|
|
@@ -96,7 +102,10 @@ import {
|
|
|
96
102
|
} from "../relay";
|
|
97
103
|
import { hasResponsesItemIdRepair, relaySseWithResponsesItemIdRepair } from "../responses-item-id-repair";
|
|
98
104
|
import type { EffectiveSubagentRoster, SpawnAgentSurface } from "../../codex/catalog";
|
|
105
|
+
import { waitForProviderRequestSlot } from "../../providers/request-pacing";
|
|
106
|
+
import { withUpstreamHttpVersion } from "../../lib/upstream-http-version";
|
|
99
107
|
|
|
108
|
+
export { withUpstreamHttpVersion } from "../../lib/upstream-http-version";
|
|
100
109
|
|
|
101
110
|
export function disableResponsesRequestTimeout(req: Request, server: Pick<Server<WsData>, "timeout"> | undefined): boolean {
|
|
102
111
|
if (!server) return false;
|
|
@@ -118,10 +127,69 @@ export function safeHostLabel(url: string): string {
|
|
|
118
127
|
}
|
|
119
128
|
}
|
|
120
129
|
|
|
130
|
+
/** Canonical origin (scheme + host) for failure-attribution keys: http and
|
|
131
|
+
* https for the same host must not share one ledger entry (#914 review). */
|
|
132
|
+
export function safeOriginLabel(url: string): string {
|
|
133
|
+
try {
|
|
134
|
+
return new URL(url).origin.toLowerCase();
|
|
135
|
+
} catch {
|
|
136
|
+
return "upstream";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
121
140
|
|
|
122
141
|
|
|
123
|
-
export
|
|
124
|
-
|
|
142
|
+
export interface PaceAwareFetch {
|
|
143
|
+
waitForPacing?: (signal?: AbortSignal) => Promise<void>;
|
|
144
|
+
unpacedFetch?: typeof globalThis.fetch;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export type ProviderFetch = typeof globalThis.fetch & PaceAwareFetch;
|
|
148
|
+
|
|
149
|
+
export interface ProviderFetchOptions {
|
|
150
|
+
providerName?: string;
|
|
151
|
+
modelId?: string;
|
|
152
|
+
/** One pacing slot was acquired immediately before this fetch wrapper was created. */
|
|
153
|
+
pacingSlotAcquired?: boolean;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function providerFetch(
|
|
157
|
+
provider: OcxProviderConfig,
|
|
158
|
+
runtime: BunRuntimeGateInput = currentBunRuntimeIdentity(),
|
|
159
|
+
options: ProviderFetchOptions = {},
|
|
160
|
+
): ProviderFetch {
|
|
161
|
+
const base = (provider as OcxProviderConfig & { fetch?: typeof globalThis.fetch }).fetch ?? globalThis.fetch;
|
|
162
|
+
// ChatGPT Codex backend: streaming turns ride the responses_websockets
|
|
163
|
+
// transport (measured ~3s faster TTFT than the SSE POST queue); everything
|
|
164
|
+
// else keeps the provider's HTTP fetch. See ws-upstream.ts for the details.
|
|
165
|
+
const unpaced = async (input: Parameters<typeof globalThis.fetch>[0], init?: RequestInit) => {
|
|
166
|
+
if (typeof input === "string" && init && shouldUseCodexWsUpstream(input, init, runtime)) {
|
|
167
|
+
return codexWsUpstreamFetch(input, init, base, runtime);
|
|
168
|
+
}
|
|
169
|
+
return base(input, withUpstreamHttpVersion(input, init, provider));
|
|
170
|
+
};
|
|
171
|
+
let pacingSlotAcquired = options.pacingSlotAcquired === true;
|
|
172
|
+
const waitForPacing = (signal?: AbortSignal) => {
|
|
173
|
+
if (pacingSlotAcquired) {
|
|
174
|
+
pacingSlotAcquired = false;
|
|
175
|
+
return Promise.resolve();
|
|
176
|
+
}
|
|
177
|
+
return options.providerName
|
|
178
|
+
? waitForProviderRequestSlot(options.providerName, provider, options.modelId, signal)
|
|
179
|
+
: Promise.resolve();
|
|
180
|
+
};
|
|
181
|
+
const wrapped = async (input: Parameters<typeof globalThis.fetch>[0], init?: RequestInit) => {
|
|
182
|
+
await waitForPacing(init?.signal ?? undefined);
|
|
183
|
+
return unpaced(input, init);
|
|
184
|
+
};
|
|
185
|
+
const preconnect = (...args: Parameters<typeof globalThis.fetch.preconnect>): void => {
|
|
186
|
+
base.preconnect?.(...args);
|
|
187
|
+
};
|
|
188
|
+
return Object.assign(wrapped, {
|
|
189
|
+
preconnect,
|
|
190
|
+
waitForPacing,
|
|
191
|
+
unpacedFetch: Object.assign(unpaced, { preconnect }),
|
|
192
|
+
});
|
|
125
193
|
}
|
|
126
194
|
|
|
127
195
|
|
|
@@ -133,7 +201,11 @@ export async function fetchWithHeaderTimeout(
|
|
|
133
201
|
timeoutMs: number,
|
|
134
202
|
preferIdentityEncoding = false,
|
|
135
203
|
executor: typeof globalThis.fetch = globalThis.fetch,
|
|
204
|
+
manualRedirect = false,
|
|
136
205
|
): Promise<Response> {
|
|
206
|
+
const pacing = executor as ProviderFetch;
|
|
207
|
+
await pacing.waitForPacing?.(abortSignal);
|
|
208
|
+
const fetchExecutor = pacing.unpacedFetch ?? executor;
|
|
137
209
|
const timeout = new AbortController();
|
|
138
210
|
const timer = setTimeout(() => {
|
|
139
211
|
if (!timeout.signal.aborted) timeout.abort(new DOMException("Timeout elapsed", "TimeoutError"));
|
|
@@ -145,13 +217,16 @@ export async function fetchWithHeaderTimeout(
|
|
|
145
217
|
headers.set("accept-encoding", "identity");
|
|
146
218
|
}
|
|
147
219
|
try {
|
|
148
|
-
return await
|
|
220
|
+
return await fetchExecutor(url, {
|
|
149
221
|
...init,
|
|
150
222
|
headers,
|
|
223
|
+
// Credential-bearing sends opt into manual redirects so a 3xx is relayed
|
|
224
|
+
// as a Response instead of being followed into a rejection that is
|
|
225
|
+
// indistinguishable from a pre-connection failure (#914).
|
|
226
|
+
...(manualRedirect ? { redirect: "manual" as const } : {}),
|
|
151
227
|
signal: AbortSignal.any([abortSignal, timeout.signal]),
|
|
152
228
|
});
|
|
153
229
|
} finally {
|
|
154
230
|
clearTimeout(timer);
|
|
155
231
|
}
|
|
156
232
|
}
|
|
157
|
-
|