@yansigit/opencodex 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/LICENSE +21 -0
- package/README.md +303 -0
- package/assets/architecture.png +0 -0
- package/assets/banner.png +0 -0
- package/assets/claude-code-models.gif +0 -0
- package/assets/codex-app-picker.png +0 -0
- package/bin/ocx.mjs +587 -0
- package/bin/package-main.mjs +9 -0
- package/gui/dist/assets/index-BNJ7r4Gd.js +102 -0
- package/gui/dist/assets/index-CGoDO3uO.css +1 -0
- package/gui/dist/favicon.png +0 -0
- package/gui/dist/icons.svg +24 -0
- package/gui/dist/index.html +25 -0
- package/gui/dist/logo.png +0 -0
- package/gui/dist/provider-icons/alibaba-color.svg +1 -0
- package/gui/dist/provider-icons/antigravity-color.svg +1 -0
- package/gui/dist/provider-icons/claude-color.svg +1 -0
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -0
- package/gui/dist/provider-icons/cursor-color.svg +2 -0
- package/gui/dist/provider-icons/deepseek-color.svg +1 -0
- package/gui/dist/provider-icons/discord.svg +1 -0
- package/gui/dist/provider-icons/firepass-color.svg +1 -0
- package/gui/dist/provider-icons/fireworks-color.svg +1 -0
- package/gui/dist/provider-icons/gemini-color.svg +1 -0
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -0
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -0
- package/gui/dist/provider-icons/grok.svg +1 -0
- package/gui/dist/provider-icons/groq-color.svg +1 -0
- package/gui/dist/provider-icons/huggingface-color.svg +1 -0
- package/gui/dist/provider-icons/kimi-color.svg +1 -0
- package/gui/dist/provider-icons/kiro-color.svg +15 -0
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -0
- package/gui/dist/provider-icons/mistral-color.svg +1 -0
- package/gui/dist/provider-icons/moonshot-color.svg +1 -0
- package/gui/dist/provider-icons/nvidia-color.svg +1 -0
- package/gui/dist/provider-icons/ollama-color.svg +1 -0
- package/gui/dist/provider-icons/openai.svg +1 -0
- package/gui/dist/provider-icons/opencode.svg +2 -0
- package/gui/dist/provider-icons/openrouter-color.svg +1 -0
- package/gui/dist/provider-icons/pi.svg +21 -0
- package/gui/dist/provider-icons/qianfan-color.svg +1 -0
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -0
- package/gui/dist/provider-icons/telegram.svg +1 -0
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -0
- package/gui/dist/provider-icons/vllm-color.svg +1 -0
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -0
- package/package.json +108 -0
- package/src/AGENTS.md +28 -0
- package/src/adapters/anthropic-image-guard.ts +251 -0
- package/src/adapters/anthropic-image-normalize.ts +518 -0
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +1327 -0
- package/src/adapters/azure.ts +36 -0
- package/src/adapters/base.ts +121 -0
- package/src/adapters/client-fingerprint.ts +65 -0
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +601 -0
- package/src/adapters/cursor/arg-codec.ts +38 -0
- package/src/adapters/cursor/arg-normalize.ts +104 -0
- package/src/adapters/cursor/checkpoint-store.ts +303 -0
- package/src/adapters/cursor/cursor-errors.ts +288 -0
- package/src/adapters/cursor/discovery.ts +333 -0
- package/src/adapters/cursor/effort-map.ts +151 -0
- package/src/adapters/cursor/exec-policy.ts +88 -0
- package/src/adapters/cursor/framing.ts +250 -0
- package/src/adapters/cursor/gen/agent_pb.ts +15274 -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/kv-store.ts +52 -0
- package/src/adapters/cursor/live-models.ts +269 -0
- package/src/adapters/cursor/live-smoke-gate.ts +41 -0
- package/src/adapters/cursor/live-transport.ts +1653 -0
- package/src/adapters/cursor/mcp-config.ts +42 -0
- package/src/adapters/cursor/mcp-manager.ts +333 -0
- package/src/adapters/cursor/message-mapper.ts +49 -0
- package/src/adapters/cursor/native-exec-common.ts +76 -0
- package/src/adapters/cursor/native-exec-desktop.ts +184 -0
- package/src/adapters/cursor/native-exec-fs.ts +332 -0
- package/src/adapters/cursor/native-exec-mcp.ts +153 -0
- package/src/adapters/cursor/native-exec-network.ts +43 -0
- package/src/adapters/cursor/native-exec-shell.ts +547 -0
- package/src/adapters/cursor/native-exec-tools.ts +118 -0
- package/src/adapters/cursor/native-exec.ts +663 -0
- package/src/adapters/cursor/protobuf-events.ts +1381 -0
- package/src/adapters/cursor/protobuf-request.ts +1032 -0
- package/src/adapters/cursor/request-builder.ts +461 -0
- package/src/adapters/cursor/thread-continuity.ts +67 -0
- package/src/adapters/cursor/tool-definitions.ts +735 -0
- package/src/adapters/cursor/tool-result-normalize.ts +92 -0
- package/src/adapters/cursor/transport-retry.ts +132 -0
- package/src/adapters/cursor/transport.ts +79 -0
- package/src/adapters/cursor/types.ts +79 -0
- package/src/adapters/cursor.ts +322 -0
- package/src/adapters/google-antigravity-hosts.ts +48 -0
- package/src/adapters/google-antigravity-replay.ts +827 -0
- package/src/adapters/google-antigravity-tools.ts +105 -0
- package/src/adapters/google-antigravity-wire.ts +141 -0
- package/src/adapters/google-errors.ts +92 -0
- package/src/adapters/google-http.ts +460 -0
- package/src/adapters/google-tool-schema.ts +238 -0
- package/src/adapters/google-truncation.ts +24 -0
- package/src/adapters/google-wire-compiler.ts +232 -0
- package/src/adapters/google.ts +1377 -0
- package/src/adapters/identity.ts +77 -0
- package/src/adapters/image.ts +23 -0
- package/src/adapters/kiro-constants.ts +16 -0
- package/src/adapters/kiro-errors.ts +208 -0
- package/src/adapters/kiro-events.ts +197 -0
- package/src/adapters/kiro-images.ts +129 -0
- package/src/adapters/kiro-retry.ts +312 -0
- package/src/adapters/kiro-thinking.ts +112 -0
- package/src/adapters/kiro-tool-fallback.ts +36 -0
- package/src/adapters/kiro-tools.ts +224 -0
- package/src/adapters/kiro-truncation.ts +33 -0
- package/src/adapters/kiro-wire.ts +129 -0
- package/src/adapters/kiro.ts +1936 -0
- package/src/adapters/mimo-free.ts +280 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1980 -0
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +1911 -0
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/run-turn-queue.ts +114 -0
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +154 -0
- package/src/adapters/upstream-http-error.ts +48 -0
- package/src/adapters/xai-web-search.ts +185 -0
- package/src/bridge.ts +1986 -0
- package/src/chat/inbound.ts +319 -0
- package/src/chat/outbound.ts +821 -0
- package/src/claude/agents-inject.ts +266 -0
- package/src/claude/alias.ts +149 -0
- package/src/claude/auth-detect.ts +229 -0
- package/src/claude/auth-mode-migration.ts +32 -0
- package/src/claude/auth-mode.ts +62 -0
- package/src/claude/context-windows.ts +205 -0
- package/src/claude/desktop-3p-guard.ts +35 -0
- package/src/claude/desktop-3p-paths.ts +84 -0
- package/src/claude/desktop-3p.ts +615 -0
- package/src/claude/desktop-health.ts +26 -0
- package/src/claude/desktop-profile.ts +263 -0
- package/src/claude/gateway-cache.ts +107 -0
- package/src/claude/inbound-debug.ts +163 -0
- package/src/claude/inbound.ts +578 -0
- package/src/claude/model-info.ts +174 -0
- package/src/claude/outbound.ts +926 -0
- package/src/cli/access.ts +108 -0
- package/src/cli/account-api.ts +302 -0
- package/src/cli/account-auth.ts +250 -0
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +737 -0
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +299 -0
- package/src/cli/agent-driven.ts +70 -0
- package/src/cli/agent.ts +290 -0
- package/src/cli/catalog-prewarm.ts +27 -0
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +213 -0
- package/src/cli/claude.ts +355 -0
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +47 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +127 -0
- package/src/cli/config-command.ts +209 -0
- package/src/cli/debug.ts +228 -0
- package/src/cli/dispatch.ts +585 -0
- package/src/cli/doctor.ts +1202 -0
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +213 -0
- package/src/cli/help.ts +101 -0
- package/src/cli/index.ts +973 -0
- package/src/cli/init.ts +211 -0
- package/src/cli/integrations.ts +260 -0
- package/src/cli/interactive-confirm.ts +133 -0
- 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 +245 -0
- package/src/cli/models.ts +422 -0
- package/src/cli/observe.ts +206 -0
- package/src/cli/opencode.ts +588 -0
- package/src/cli/provider-replit.ts +232 -0
- package/src/cli/provider-runtime.ts +179 -0
- package/src/cli/provider.ts +492 -0
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +422 -0
- package/src/cli/replit-gateway-key-input.ts +138 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +328 -0
- package/src/cli/star-prompt.ts +211 -0
- package/src/cli/status-oauth.ts +78 -0
- package/src/cli/status.ts +328 -0
- package/src/cli/system-command.ts +112 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +199 -0
- package/src/cli/v2.ts +268 -0
- package/src/cli.ts +10 -0
- package/src/clients/config-export.ts +1704 -0
- package/src/codex/account-id.ts +34 -0
- package/src/codex/account-label.ts +47 -0
- package/src/codex/account-lifecycle.ts +172 -0
- package/src/codex/account-namespace-match.ts +63 -0
- package/src/codex/account-namespaces.ts +195 -0
- package/src/codex/account-pause.ts +20 -0
- package/src/codex/account-priority.ts +83 -0
- package/src/codex/account-runtime-state.ts +31 -0
- package/src/codex/account-store.ts +544 -0
- package/src/codex/account-usability.ts +43 -0
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/agent-roles-sync.ts +225 -0
- package/src/codex/agent-roles.ts +238 -0
- package/src/codex/app-server-processes.ts +1143 -0
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +2147 -0
- package/src/codex/auth-collision.ts +109 -0
- package/src/codex/auth-context.ts +665 -0
- package/src/codex/autostart-health.ts +156 -0
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +436 -0
- package/src/codex/catalog/bundled.ts +549 -0
- package/src/codex/catalog/effort.ts +446 -0
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +664 -0
- package/src/codex/catalog/native-models.ts +72 -0
- package/src/codex/catalog/parsing.ts +650 -0
- package/src/codex/catalog/provider-fetch.ts +2064 -0
- package/src/codex/catalog/sync.ts +1883 -0
- 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 +14 -0
- 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/data/upstream-models.json +830 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/exec-invocation.ts +22 -0
- package/src/codex/features.ts +1566 -0
- 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 +108 -0
- package/src/codex/history-provider.ts +979 -0
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +220 -0
- package/src/codex/home.ts +206 -0
- package/src/codex/inject-coordination.ts +290 -0
- package/src/codex/inject.ts +1733 -0
- package/src/codex/injected-marker.ts +106 -0
- 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 +225 -0
- 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 +56 -0
- package/src/codex/main-account.ts +68 -0
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +273 -0
- 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 +144 -0
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +242 -0
- package/src/codex/pool-rotation.ts +295 -0
- package/src/codex/project-config-warnings.ts +425 -0
- 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 +573 -0
- package/src/codex/refresh.ts +62 -0
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +1888 -0
- package/src/codex/runtime.ts +659 -0
- package/src/codex/shim.ts +2170 -0
- package/src/codex/subagent-defaults.ts +550 -0
- package/src/codex/subagent-model-fallback.ts +784 -0
- package/src/codex/sync.ts +319 -0
- 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 +298 -0
- package/src/codex/websocket-registry.ts +100 -0
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +160 -0
- package/src/combos/index.ts +45 -0
- package/src/combos/request.ts +94 -0
- package/src/combos/resolve.ts +232 -0
- package/src/combos/types.ts +398 -0
- package/src/config/provider-name.ts +24 -0
- package/src/config.ts +4041 -0
- package/src/fork/register.ts +3 -0
- package/src/generated/compatibility-version.json +3116 -0
- package/src/generated/model-metadata.ts +106 -0
- package/src/github/star-state.ts +203 -0
- package/src/grok/inject.ts +530 -0
- package/src/grok/inspect.ts +45 -0
- package/src/grok/status.ts +121 -0
- package/src/grok/sync.ts +66 -0
- package/src/images/artifacts.ts +516 -0
- package/src/images/fulfill-video.ts +163 -0
- package/src/images/fulfill.ts +149 -0
- package/src/images/index.ts +4 -0
- package/src/images/loop.ts +955 -0
- package/src/images/plan.ts +143 -0
- package/src/images/synthetic-tool.ts +133 -0
- package/src/images/types.ts +41 -0
- package/src/images/xai-client.ts +141 -0
- package/src/images/xai-video-client.ts +163 -0
- package/src/index.ts +22 -0
- 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/abort.ts +146 -0
- package/src/lib/admin-secrets.ts +25 -0
- package/src/lib/admission.ts +83 -0
- package/src/lib/app-owned-memory-stores.ts +195 -0
- package/src/lib/app-owned-memory.ts +265 -0
- package/src/lib/bounded-body.ts +346 -0
- package/src/lib/bun-binary-validator.d.mts +3 -0
- package/src/lib/bun-binary-validator.mjs +18 -0
- package/src/lib/bun-runtime.ts +184 -0
- package/src/lib/bun-stream-caps.ts +130 -0
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +364 -0
- package/src/lib/crash-guard.ts +344 -0
- package/src/lib/debug-log-buffer.ts +83 -0
- package/src/lib/debug-settings.ts +108 -0
- package/src/lib/debug.ts +31 -0
- package/src/lib/destination-policy.ts +380 -0
- package/src/lib/errors.ts +406 -0
- package/src/lib/eventstream-decoder.ts +253 -0
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/gcp-adc.ts +341 -0
- package/src/lib/injection-debug-log.ts +58 -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/open-url.ts +25 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/pinned-http.ts +270 -0
- package/src/lib/privacy.ts +20 -0
- package/src/lib/process-control.ts +168 -0
- package/src/lib/provider-outbound.ts +210 -0
- package/src/lib/provider-url.ts +14 -0
- package/src/lib/proxy-env.ts +18 -0
- package/src/lib/redact.ts +521 -0
- package/src/lib/retry-after.ts +55 -0
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/service-secrets.ts +25 -0
- package/src/lib/shadow-call.ts +61 -0
- package/src/lib/sidecar-tracker.ts +52 -0
- package/src/lib/sse-decoder.ts +364 -0
- package/src/lib/state-store-registrations.ts +119 -0
- package/src/lib/state-store-sweeper.ts +184 -0
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/test-home-guard.ts +90 -0
- package/src/lib/token-estimate.ts +86 -0
- package/src/lib/tool-argument-integers.ts +202 -0
- package/src/lib/translator-budget.ts +400 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +392 -0
- package/src/lib/win-exec.ts +115 -0
- package/src/lib/win-paths.ts +68 -0
- package/src/lib/windows-atomic-replace.ts +156 -0
- package/src/lib/windows-elevation.ts +773 -0
- package/src/lib/windows-secret-acl.ts +854 -0
- 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 +403 -0
- 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-routing.ts +594 -0
- package/src/oauth/anthropic.ts +188 -0
- package/src/oauth/antigravity-routing.ts +151 -0
- package/src/oauth/callback-server.ts +300 -0
- package/src/oauth/chatgpt.ts +161 -0
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +252 -0
- package/src/oauth/github-copilot.ts +428 -0
- package/src/oauth/google-antigravity.ts +262 -0
- package/src/oauth/health.ts +407 -0
- package/src/oauth/index.ts +1504 -0
- package/src/oauth/key-providers.ts +124 -0
- package/src/oauth/kimi.ts +227 -0
- package/src/oauth/kiro-credentials.ts +726 -0
- package/src/oauth/kiro.ts +621 -0
- package/src/oauth/local-token-detect.ts +130 -0
- package/src/oauth/log.ts +50 -0
- package/src/oauth/login-cli.ts +223 -0
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/pkce.ts +15 -0
- package/src/oauth/store.ts +728 -0
- package/src/oauth/token-guardian.ts +309 -0
- package/src/oauth/types.ts +62 -0
- package/src/oauth/xai.ts +241 -0
- package/src/providers/alibaba-region-backup.ts +75 -0
- package/src/providers/alibaba-region-migration.ts +156 -0
- package/src/providers/alibaba-region-startup.ts +36 -0
- package/src/providers/antigravity-models.ts +695 -0
- package/src/providers/antigravity-quota.ts +216 -0
- package/src/providers/api-keys.ts +140 -0
- package/src/providers/base-url-choices.ts +74 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +144 -0
- package/src/providers/context-cap.ts +82 -0
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/derive.ts +586 -0
- package/src/providers/fastwire.ts +501 -0
- package/src/providers/free-directory.ts +187 -0
- package/src/providers/github-copilot-transport.ts +56 -0
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +271 -0
- package/src/providers/kiro-models.ts +67 -0
- package/src/providers/label.ts +19 -0
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +449 -0
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/openai-sidecar.ts +243 -0
- package/src/providers/openai-tier-startup.ts +56 -0
- package/src/providers/openai-tiers.ts +423 -0
- package/src/providers/openai-virtual-models.ts +83 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/openrouter-routing.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +185 -0
- package/src/providers/quota.ts +2345 -0
- package/src/providers/registry.ts +2918 -0
- package/src/providers/replit/constants.ts +27 -0
- package/src/providers/replit/derive.ts +85 -0
- package/src/providers/replit/headers.ts +28 -0
- package/src/providers/replit/origin.ts +55 -0
- package/src/providers/replit/pair-install-response.ts +72 -0
- package/src/providers/replit/probe.ts +199 -0
- package/src/providers/replit/setup.ts +350 -0
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +103 -0
- 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 +148 -0
- package/src/reasoning-effort.ts +183 -0
- package/src/responses/compaction.ts +142 -0
- 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 +838 -0
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +60 -0
- package/src/responses/reasoning-replay-cache.ts +426 -0
- package/src/responses/schema.ts +165 -0
- package/src/responses/spill-store.ts +459 -0
- package/src/responses/state.ts +1433 -0
- package/src/responses/thought-signature-replay.ts +347 -0
- package/src/responses/tool-groups.ts +19 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/router.ts +761 -0
- 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 +53 -0
- package/src/server/auth-cors.ts +751 -0
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +442 -0
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +426 -0
- package/src/server/claude-messages.ts +1030 -0
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +190 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +152 -0
- package/src/server/image-retry.ts +42 -0
- package/src/server/images.ts +568 -0
- package/src/server/index.ts +1813 -0
- package/src/server/lifecycle.ts +498 -0
- package/src/server/live.ts +717 -0
- 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 +1433 -0
- package/src/server/management/api-access.ts +141 -0
- package/src/server/management/api-key-usage.ts +193 -0
- package/src/server/management/body.ts +41 -0
- package/src/server/management/combo-routes.ts +263 -0
- package/src/server/management/config-routes.ts +835 -0
- package/src/server/management/context.ts +113 -0
- 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 +586 -0
- package/src/server/management/model-routes.ts +560 -0
- 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 +637 -0
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +1033 -0
- package/src/server/management/replit-provider-routes.ts +86 -0
- 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 +385 -0
- package/src/server/management/shared.ts +286 -0
- package/src/server/management/sidebar-routes.ts +106 -0
- 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 +435 -0
- package/src/server/management/system-routes.ts +194 -0
- package/src/server/management/usage-summary-cache.ts +94 -0
- 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 +314 -0
- package/src/server/management-auth.ts +482 -0
- package/src/server/memory-watchdog.ts +156 -0
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/port-reclaim.ts +307 -0
- package/src/server/ports.ts +156 -0
- package/src/server/proxy-liveness.ts +328 -0
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +353 -0
- package/src/server/relay.ts +1209 -0
- package/src/server/request-decompress.ts +239 -0
- package/src/server/request-log-conversation.ts +168 -0
- package/src/server/request-log.ts +1259 -0
- 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 +551 -0
- package/src/server/responses/compact.ts +771 -0
- package/src/server/responses/core.ts +5389 -0
- package/src/server/responses/empty-completion-guard.ts +276 -0
- package/src/server/responses/encrypted-payload.ts +331 -0
- package/src/server/responses/fetch-helpers.ts +232 -0
- package/src/server/responses/input-admission.ts +185 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/passthrough-error.ts +78 -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 +251 -0
- package/src/server/responses/upstream-error.ts +53 -0
- package/src/server/responses/ws-upstream.ts +308 -0
- package/src/server/responses-custom-tool-repair.ts +282 -0
- package/src/server/responses-image-gen-repair.ts +132 -0
- package/src/server/responses-item-id-repair.ts +272 -0
- 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 +25 -0
- package/src/server/search.ts +201 -0
- package/src/server/sse-frame-buffer.ts +292 -0
- package/src/server/sse-payload-rewrite.ts +263 -0
- package/src/server/startup-action-control.ts +315 -0
- package/src/server/startup-health-cache.ts +131 -0
- package/src/server/system-env.ts +484 -0
- package/src/server/windows-tcp-drop.ts +184 -0
- package/src/server/windows-tray-control.ts +41 -0
- package/src/server/ws-bridge.ts +472 -0
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +3575 -0
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/stall-timeout.ts +20 -0
- package/src/storage/cleanup-job.ts +57 -0
- package/src/storage/cleanup.ts +3085 -0
- package/src/storage/policy-job.ts +457 -0
- package/src/storage/policy-scheduler.ts +40 -0
- package/src/storage/policy-worker.ts +59 -0
- package/src/storage/policy.ts +527 -0
- package/src/storage/restore-job.ts +299 -0
- package/src/storage/restore-worker.ts +58 -0
- package/src/storage/scanner.ts +238 -0
- package/src/storage/storage-mutation-coordinator.ts +139 -0
- package/src/storage/worker-lifecycle.ts +215 -0
- package/src/tray/assets/opencodex-tray-offline.ico +0 -0
- package/src/tray/assets/opencodex-tray-online.ico +0 -0
- package/src/tray/assets/opencodex-tray-warning.ico +0 -0
- package/src/tray/assets/opencodex-tray.png +0 -0
- package/src/tray/windows-tray.ps1 +364 -0
- package/src/tray/windows.ts +757 -0
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +876 -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 +106 -0
- package/src/update/badge.ts +72 -0
- package/src/update/index.ts +415 -0
- package/src/update/job.ts +1887 -0
- package/src/update/notify.ts +263 -0
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/npm-invocation.d.mts +23 -0
- package/src/update/npm-invocation.mjs +94 -0
- package/src/update/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +259 -0
- package/src/update/tray-update-plan.d.mts +18 -0
- package/src/update/tray-update-plan.mjs +38 -0
- package/src/usage/cost.ts +625 -0
- package/src/usage/debug.ts +97 -0
- package/src/usage/expected-prices.ts +416 -0
- package/src/usage/log.ts +1223 -0
- package/src/usage/summary.ts +753 -0
- package/src/usage/totals.ts +14 -0
- 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 +189 -0
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +131 -0
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +681 -0
- 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 +195 -0
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +88 -0
- package/src/web-search/executor.ts +113 -0
- package/src/web-search/format-result.ts +89 -0
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +331 -0
- package/src/web-search/loop.ts +896 -0
- package/src/web-search/parse.ts +315 -0
- package/src/web-search/progress-stream.ts +342 -0
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/synthetic-tool.ts +47 -0
- package/src/web-search/xai-executor.ts +219 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import type { Server } from "bun";
|
|
2
|
+
import {
|
|
3
|
+
codexWsUpstreamFetch,
|
|
4
|
+
currentBunRuntimeIdentity,
|
|
5
|
+
shouldUseCodexWsUpstream,
|
|
6
|
+
type BunRuntimeGateInput,
|
|
7
|
+
} from "./ws-upstream";
|
|
8
|
+
import { bridgeToResponsesSSE, buildResponseJSON, formatErrorResponse, type ResponsesTerminalStatus } from "../../bridge";
|
|
9
|
+
import {
|
|
10
|
+
getConfigPath,
|
|
11
|
+
multiAgentGuidanceEnabled,
|
|
12
|
+
resolveEnvValue,
|
|
13
|
+
} from "../../config";
|
|
14
|
+
import { parseRequest } from "../../responses/parser";
|
|
15
|
+
import { buildCompactV1Output, COMPACT_PROMPT, decodeCompactionSummary, extractCompactUserMessages } from "../../responses/compaction";
|
|
16
|
+
import { FORWARD_HEADERS, sanitizeReasoningInputContent } from "../../adapters/openai-responses";
|
|
17
|
+
import { expandPreviousResponseInput, previousResponseProviderState, rememberResponseState } from "../../responses/state";
|
|
18
|
+
import { routeModel } from "../../router";
|
|
19
|
+
import {
|
|
20
|
+
advanceComboAfterFailure,
|
|
21
|
+
comboDefaultEffort,
|
|
22
|
+
comboFailureDecision,
|
|
23
|
+
comboIdFromRawBody,
|
|
24
|
+
concreteComboRequestBody,
|
|
25
|
+
getCombo,
|
|
26
|
+
isComboTargetInCooldown,
|
|
27
|
+
NoAvailableComboTargetsError,
|
|
28
|
+
noteComboSuccess,
|
|
29
|
+
parseRetryAfterMs,
|
|
30
|
+
pickComboTarget,
|
|
31
|
+
targetKey,
|
|
32
|
+
} from "../../combos";
|
|
33
|
+
import { isInjectionDebugEnabled } from "../../lib/debug-settings";
|
|
34
|
+
import { injectionDebugLog } from "../../lib/injection-debug-log";
|
|
35
|
+
import { modelInList, namespacedToolName } from "../../types";
|
|
36
|
+
import type { AdapterEvent, OcxConfig, OcxParsedRequest, OcxProviderConfig, OcxProviderContinuationState, OcxUsage } from "../../types";
|
|
37
|
+
import {
|
|
38
|
+
forceRefreshOAuthAccessSnapshot,
|
|
39
|
+
getOAuthCredentialApiBaseUrl,
|
|
40
|
+
getOAuthCredentialProjectId,
|
|
41
|
+
getValidAccessTokenSnapshot,
|
|
42
|
+
type OAuthAccessSnapshot,
|
|
43
|
+
UnsupportedOAuthProviderError,
|
|
44
|
+
} from "../../oauth";
|
|
45
|
+
import { buildWebSearchTool, planWebSearch, runWithWebSearch, shouldResolveOpenAiWebSearchSidecar } from "../../web-search";
|
|
46
|
+
import { describeImagesInPlace, planVisionSidecar, shouldResolveOpenAiVisionSidecar, stripImagesInPlace } from "../../vision";
|
|
47
|
+
import { createAdapterEventQueue, preflightAdapterEvents } from "../../adapters/run-turn-queue";
|
|
48
|
+
import {
|
|
49
|
+
applyCodexAuthContextToProvider,
|
|
50
|
+
CodexAccountCooldownError,
|
|
51
|
+
CodexAuthContextError,
|
|
52
|
+
CodexDirectAuthenticationError,
|
|
53
|
+
CodexPoolAuthenticationError,
|
|
54
|
+
CodexThreadAffinityExpiredError,
|
|
55
|
+
headersForCodexAuthContext,
|
|
56
|
+
isCodexAuthContextUsable,
|
|
57
|
+
resolveCodexAuthContext,
|
|
58
|
+
type CodexAuthContext,
|
|
59
|
+
} from "../../codex/auth-context";
|
|
60
|
+
import {
|
|
61
|
+
formatCodexProviderForLog,
|
|
62
|
+
recordCodexUpstreamOutcome,
|
|
63
|
+
type CodexUpstreamOutcome,
|
|
64
|
+
} from "../../codex/routing";
|
|
65
|
+
import { fetchWithResetRetry, fetchWithTransientRetry, applyUpstreamRecoveryInit } from "../../lib/upstream-retry";
|
|
66
|
+
import { ForwardAdmissionCredentialError, validateForwardAdmissionCredential } from "../auth-cors";
|
|
67
|
+
import { listOpenAiForwardSidecarCandidates, resolveFirstUsableOpenAiSidecar, type ResolvedOpenAiForwardSidecar } from "../../providers/openai-sidecar";
|
|
68
|
+
import { isCanonicalOpenAiForwardProvider } from "../../providers/openai-tiers";
|
|
69
|
+
import { slugsEquivalent } from "../../providers/slug-codec";
|
|
70
|
+
import { applyOpenAiVirtualModel, resolveOpenAiCompactModel } from "../../providers/openai-virtual-models";
|
|
71
|
+
import { isUsageDebugEnabled } from "../../usage/debug";
|
|
72
|
+
import { readJsonRequestBody, DecompressedBodyTooLargeError, UnsupportedContentEncodingError } from "../request-decompress";
|
|
73
|
+
import { resolveAdapter, resolveWireProtocolOverride } from "../adapter-resolve";
|
|
74
|
+
import { hasKeyPoolFailover, rotateProviderTransportOn429 } from "../../providers/key-failover";
|
|
75
|
+
import { shouldAttemptImageTierRetry } from "../image-retry";
|
|
76
|
+
import { resolveProviderTransport } from "../../providers/xai-transport";
|
|
77
|
+
import type { WsData } from "../ws-bridge";
|
|
78
|
+
import { registerTurn, trackStreamLifetime, unregisterTurn } from "../lifecycle";
|
|
79
|
+
import { redactSecretString } from "../../lib/redact";
|
|
80
|
+
import { readBoundedResponseBody } from "../../lib/bounded-body";
|
|
81
|
+
import { supportedLadderFor } from "../effort-policy";
|
|
82
|
+
import {
|
|
83
|
+
beginRequestAttempt,
|
|
84
|
+
catalogModelSupportsServiceTier,
|
|
85
|
+
finishRequestAttempt,
|
|
86
|
+
inspectResponseLogJson,
|
|
87
|
+
noteAttemptSend,
|
|
88
|
+
readConfiguredCodexServiceTier,
|
|
89
|
+
requestLogSpeedLabel,
|
|
90
|
+
sealRequestAttemptIdentity,
|
|
91
|
+
usageFromResponsesPayload,
|
|
92
|
+
type RequestLogContext,
|
|
93
|
+
} from "../request-log";
|
|
94
|
+
import type { AttemptRecoveryKind } from "../../usage/log";
|
|
95
|
+
import {
|
|
96
|
+
consumeForInspection,
|
|
97
|
+
consumeForResponseLogMetadata,
|
|
98
|
+
markNativePassthroughSseResponse,
|
|
99
|
+
relaySseWithFailedTail,
|
|
100
|
+
relayWithAbort,
|
|
101
|
+
sanitizePassthroughHeaders,
|
|
102
|
+
} from "../relay";
|
|
103
|
+
import { hasResponsesItemIdRepair, relaySseWithResponsesItemIdRepair } from "../responses-item-id-repair";
|
|
104
|
+
import type { EffectiveSubagentRoster, SpawnAgentSurface } from "../../codex/catalog";
|
|
105
|
+
import { waitForProviderRequestSlot } from "../../providers/request-pacing";
|
|
106
|
+
import { withUpstreamHttpVersion } from "../../lib/upstream-http-version";
|
|
107
|
+
|
|
108
|
+
export { withUpstreamHttpVersion } from "../../lib/upstream-http-version";
|
|
109
|
+
|
|
110
|
+
export function disableResponsesRequestTimeout(req: Request, server: Pick<Server<WsData>, "timeout"> | undefined): boolean {
|
|
111
|
+
if (!server) return false;
|
|
112
|
+
try {
|
|
113
|
+
server.timeout(req, 0);
|
|
114
|
+
return true;
|
|
115
|
+
} catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
export function safeHostLabel(url: string): string {
|
|
123
|
+
try {
|
|
124
|
+
return new URL(url).host;
|
|
125
|
+
} catch {
|
|
126
|
+
return "upstream";
|
|
127
|
+
}
|
|
128
|
+
}
|
|
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
|
+
|
|
140
|
+
|
|
141
|
+
|
|
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
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
export async function fetchWithHeaderTimeout(
|
|
198
|
+
url: string,
|
|
199
|
+
init: Omit<RequestInit, "signal">,
|
|
200
|
+
abortSignal: AbortSignal,
|
|
201
|
+
timeoutMs: number,
|
|
202
|
+
preferIdentityEncoding = false,
|
|
203
|
+
executor: typeof globalThis.fetch = globalThis.fetch,
|
|
204
|
+
manualRedirect = false,
|
|
205
|
+
): Promise<Response> {
|
|
206
|
+
const pacing = executor as ProviderFetch;
|
|
207
|
+
await pacing.waitForPacing?.(abortSignal);
|
|
208
|
+
const fetchExecutor = pacing.unpacedFetch ?? executor;
|
|
209
|
+
const timeout = new AbortController();
|
|
210
|
+
const timer = setTimeout(() => {
|
|
211
|
+
if (!timeout.signal.aborted) timeout.abort(new DOMException("Timeout elapsed", "TimeoutError"));
|
|
212
|
+
}, timeoutMs);
|
|
213
|
+
const headers = new Headers(init.headers);
|
|
214
|
+
// Compressed SSE can be held until the decompressor has a complete block. Streaming calls
|
|
215
|
+
// default to identity for low-latency frame delivery, while an explicit caller choice wins.
|
|
216
|
+
if (preferIdentityEncoding && !headers.has("accept-encoding")) {
|
|
217
|
+
headers.set("accept-encoding", "identity");
|
|
218
|
+
}
|
|
219
|
+
try {
|
|
220
|
+
return await fetchExecutor(url, {
|
|
221
|
+
...init,
|
|
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 } : {}),
|
|
227
|
+
signal: AbortSignal.any([abortSignal, timeout.signal]),
|
|
228
|
+
});
|
|
229
|
+
} finally {
|
|
230
|
+
clearTimeout(timer);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-dispatch input admission (#1412).
|
|
3
|
+
*
|
|
4
|
+
* Refuses a turn whose estimated input cannot plausibly fit the model context window,
|
|
5
|
+
* BEFORE auth resolution, circuit admission, or any upstream I/O. #1412 reported ~127k of
|
|
6
|
+
* real context compounding to 1.3M-1.6M tokens and crashing the proxy; the provider would
|
|
7
|
+
* reject such a turn anyway, so paying for the round trip buys nothing.
|
|
8
|
+
*
|
|
9
|
+
* Deliberately narrow. This is not a context manager and not a compaction trigger: it
|
|
10
|
+
* catches the pathological case and stays out of the way otherwise. Every uncertainty
|
|
11
|
+
* resolves toward admitting.
|
|
12
|
+
*/
|
|
13
|
+
import { nativeOpenAiContextWindow, nativeOpenAiMaxInputTokens, type NativeContextLimitsInput } from "../../codex/catalog/metadata";
|
|
14
|
+
import { estimateTokens } from "../../lib/token-estimate";
|
|
15
|
+
import { isCanonicalOpenAiForwardProvider, OPENAI_CODEX_PROVIDER_ID } from "../../providers/openai-tiers";
|
|
16
|
+
import { modelRecordValue } from "../../reasoning-effort";
|
|
17
|
+
import type { OcxContentPart, OcxParsedRequest, OcxProviderConfig } from "../../types";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Multiplier applied to the ceiling before refusing.
|
|
21
|
+
*
|
|
22
|
+
* 2.5, not something tighter, because `estimateTokens` can overshoot by 1.6x on its own.
|
|
23
|
+
* `cjkRatio` samples every `stride`-th character, so a payload of fixed-width records whose
|
|
24
|
+
* length aligns with the stride samples as 100% CJK while being ~1.6% CJK, firing the
|
|
25
|
+
* 2.5-chars/token clamp instead of the 4.0 default. Measured on Bun 1.3.14: 126,046 chars,
|
|
26
|
+
* true CJK ratio 0.0161, sampled ratio 1.0, estimate inflated 1.6x. Since 4.0 / 2.5 = 1.6
|
|
27
|
+
* is that branch maximum divergence, a threshold at or under 1.6 would convert the
|
|
28
|
+
* estimator error bar into false 413s.
|
|
29
|
+
*
|
|
30
|
+
* 2.5 sits above it with room for the ~10% model-family ratio spread, and still refuses the
|
|
31
|
+
* #1412 shape (10x) four times over.
|
|
32
|
+
*/
|
|
33
|
+
export const ADMISSION_TOLERANCE = 2.5;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Token cost charged for a remote image URL. The bytes are not in this request — the
|
|
37
|
+
* provider fetches them — so the URL own length is not the cost. A small flat charge
|
|
38
|
+
* acknowledges the tiles the image will occupy without pretending to know its dimensions.
|
|
39
|
+
*/
|
|
40
|
+
const REMOTE_IMAGE_TOKENS = 850;
|
|
41
|
+
|
|
42
|
+
/** Decoded image bytes per token. Coarse tile-count proxy, not a provider formula. */
|
|
43
|
+
const IMAGE_BYTES_PER_TOKEN = 750;
|
|
44
|
+
|
|
45
|
+
export interface InputAdmissionResult {
|
|
46
|
+
admitted: boolean;
|
|
47
|
+
estimatedTokens: number;
|
|
48
|
+
/** Resolved ceiling, or null when nothing could be resolved (=> always admitted). */
|
|
49
|
+
ceiling: number | null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function positive(value: unknown): number | null {
|
|
53
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Charge a `data:` URL by its DECODED size rather than its character length: base64 inflates
|
|
58
|
+
* by 4/3, so charging the string would overcount by a third. A remote URL is charged flat.
|
|
59
|
+
*/
|
|
60
|
+
function imageTokens(imageUrl: string): number {
|
|
61
|
+
if (!imageUrl.startsWith("data:")) return REMOTE_IMAGE_TOKENS;
|
|
62
|
+
const comma = imageUrl.indexOf(",");
|
|
63
|
+
if (comma < 0) return REMOTE_IMAGE_TOKENS;
|
|
64
|
+
const payload = imageUrl.length - comma - 1;
|
|
65
|
+
if (payload <= 0) return 0;
|
|
66
|
+
const decoded = Math.floor((payload * 3) / 4);
|
|
67
|
+
return Math.max(1, Math.ceil(decoded / IMAGE_BYTES_PER_TOKEN));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function contentPartTokens(part: OcxContentPart, modelId: string): number {
|
|
71
|
+
return part.type === "image" ? imageTokens(part.imageUrl) : estimateTokens(part.text, modelId);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function contentTokens(content: string | readonly OcxContentPart[], modelId: string): number {
|
|
75
|
+
if (typeof content === "string") return estimateTokens(content, modelId);
|
|
76
|
+
let total = 0;
|
|
77
|
+
for (const part of content) total += contentPartTokens(part, modelId);
|
|
78
|
+
return total;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Estimate the input tokens of a parsed request.
|
|
83
|
+
*
|
|
84
|
+
* Walks the whole `OcxMessage` union rather than user text alone. Assistant turns carry
|
|
85
|
+
* their content as `OcxAssistantContentPart[]` — text, thinking blocks, and tool calls whose
|
|
86
|
+
* JSON arguments are frequently the largest single item in an agent conversation. A walk
|
|
87
|
+
* that counted only `{type:"text"}` would undercount exactly the turns that trigger this
|
|
88
|
+
* gate.
|
|
89
|
+
*/
|
|
90
|
+
export function estimateInputTokens(parsed: OcxParsedRequest, modelId: string): number {
|
|
91
|
+
const { context } = parsed;
|
|
92
|
+
let total = 0;
|
|
93
|
+
|
|
94
|
+
for (const prompt of context.systemPrompt ?? []) total += estimateTokens(prompt, modelId);
|
|
95
|
+
|
|
96
|
+
for (const message of context.messages) {
|
|
97
|
+
if (message.role === "assistant") {
|
|
98
|
+
for (const part of message.content) {
|
|
99
|
+
if (part.type === "text") total += estimateTokens(part.text, modelId);
|
|
100
|
+
else if (part.type === "thinking") total += estimateTokens(part.thinking, modelId);
|
|
101
|
+
else total += estimateTokens(part.name, modelId) + estimateTokens(JSON.stringify(part.arguments), modelId);
|
|
102
|
+
}
|
|
103
|
+
// Opaque provider blob replayed verbatim upstream, so it costs real input tokens.
|
|
104
|
+
if (message.kiroRedactedReasoning) total += estimateTokens(message.kiroRedactedReasoning, modelId);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
total += contentTokens(message.content, modelId);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Tool schemas ride every turn: name, description, and the JSON parameter schema all
|
|
111
|
+
// reach the upstream, and a large MCP catalog can dominate a short conversation.
|
|
112
|
+
for (const tool of context.tools ?? []) {
|
|
113
|
+
total += estimateTokens(tool.name, modelId)
|
|
114
|
+
+ estimateTokens(tool.description, modelId)
|
|
115
|
+
+ estimateTokens(JSON.stringify(tool.parameters), modelId);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return total;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Resolve the admission ceiling. Pure: no filesystem, no catalog, no registry scan.
|
|
123
|
+
*
|
|
124
|
+
* `provider` must be the ROUTED config (`route.provider`), which `routedProviderConfig`
|
|
125
|
+
* has already transport-guarded and merged. Re-deriving from `config.providers[name]` would
|
|
126
|
+
* reject a user-defined provider that merely shares a built-in name using limits that
|
|
127
|
+
* belong to a different service.
|
|
128
|
+
*/
|
|
129
|
+
export function resolveInputCeiling(
|
|
130
|
+
provider: OcxProviderConfig,
|
|
131
|
+
providerName: string,
|
|
132
|
+
modelId: string,
|
|
133
|
+
// Operator cap for the canonical native provider. Passed in rather than read from a
|
|
134
|
+
// config here so this stays pure: no filesystem, no catalog, no registry scan.
|
|
135
|
+
nativeContextCap?: NativeContextLimitsInput,
|
|
136
|
+
): number | null {
|
|
137
|
+
// `modelRecordValue`, not a bare lookup: the catalog resolves these same two maps that
|
|
138
|
+
// way, so a `gpt-oss` entry covers `gpt-oss:120b`. Reading raw here made the gate fall
|
|
139
|
+
// back to the provider-wide window and refuse turns the model can plainly hold.
|
|
140
|
+
const configured = positive(modelRecordValue(provider.modelContextWindows, modelId))
|
|
141
|
+
?? positive(provider.contextWindow);
|
|
142
|
+
|
|
143
|
+
// The canonical `openai` registry entry declares no context fields, so without this the
|
|
144
|
+
// gate would be inert on the default Codex route. All three clauses are load-bearing: a
|
|
145
|
+
// transport-mismatched custom provider named "openai" is preserved verbatim by routing
|
|
146
|
+
// and must not inherit built-in native limits, and a routed `provider/model` id is not a
|
|
147
|
+
// native slug. Static maps only — no catalog read.
|
|
148
|
+
const canonicalNativeBare = providerName === OPENAI_CODEX_PROVIDER_ID
|
|
149
|
+
&& isCanonicalOpenAiForwardProvider(provider)
|
|
150
|
+
&& !modelId.includes("/");
|
|
151
|
+
const nativeLimits = canonicalNativeBare && configured !== null
|
|
152
|
+
? {
|
|
153
|
+
...(typeof nativeContextCap === "number" ? { cap: nativeContextCap } : (nativeContextCap ?? {})),
|
|
154
|
+
modelWindows: { [modelId]: configured },
|
|
155
|
+
}
|
|
156
|
+
: nativeContextCap;
|
|
157
|
+
const native = canonicalNativeBare
|
|
158
|
+
? positive(nativeOpenAiContextWindow(modelId, nativeLimits))
|
|
159
|
+
: null;
|
|
160
|
+
const nativeMaxInput = canonicalNativeBare ? positive(nativeOpenAiMaxInputTokens(modelId, nativeLimits)) : null;
|
|
161
|
+
|
|
162
|
+
const window = canonicalNativeBare ? native : configured;
|
|
163
|
+
// modelMaxInputTokens is an input-only cap, so it can only tighten the window.
|
|
164
|
+
const configuredMaxInput = positive(modelRecordValue(provider.modelMaxInputTokens, modelId));
|
|
165
|
+
const limits = [window, configuredMaxInput, nativeMaxInput].filter((v): v is number => v !== null);
|
|
166
|
+
return limits.length === 0 ? null : Math.min(...limits);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Fail-open when no ceiling is known; refuse only past `ceiling * ADMISSION_TOLERANCE`.
|
|
171
|
+
*
|
|
172
|
+
* The caller is responsible for skipping compaction turns — see the call site in core.ts.
|
|
173
|
+
*/
|
|
174
|
+
export function checkInputAdmission(
|
|
175
|
+
parsed: OcxParsedRequest,
|
|
176
|
+
provider: OcxProviderConfig,
|
|
177
|
+
providerName: string,
|
|
178
|
+
modelId: string,
|
|
179
|
+
nativeContextCap?: NativeContextLimitsInput,
|
|
180
|
+
): InputAdmissionResult {
|
|
181
|
+
const ceiling = resolveInputCeiling(provider, providerName, modelId, nativeContextCap);
|
|
182
|
+
if (ceiling === null) return { admitted: true, estimatedTokens: 0, ceiling: null };
|
|
183
|
+
const estimatedTokens = estimateInputTokens(parsed, modelId);
|
|
184
|
+
return { admitted: estimatedTokens <= ceiling * ADMISSION_TOLERANCE, estimatedTokens, ceiling };
|
|
185
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { formatErrorResponse } from "../../bridge";
|
|
2
|
+
import { RequestPacingQueueOverloadError } from "../../providers/request-pacing";
|
|
3
|
+
|
|
4
|
+
/** Convert local request-pacing admission failures into a retryable HTTP response. */
|
|
5
|
+
export function requestPacingOverloadResponse(error: unknown): Response | undefined {
|
|
6
|
+
if (!(error instanceof RequestPacingQueueOverloadError)) return undefined;
|
|
7
|
+
return formatErrorResponse(
|
|
8
|
+
429,
|
|
9
|
+
"rate_limit_error",
|
|
10
|
+
error.message,
|
|
11
|
+
{ retryAfter: String(error.retryAfterSeconds) },
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { formatErrorResponse } from "../../bridge";
|
|
2
|
+
import {
|
|
3
|
+
resolveClientRetryAfter,
|
|
4
|
+
validateClientRetryAfterHeader,
|
|
5
|
+
} from "../../lib/retry-after";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Passthrough adapters historically relayed upstream non-2xx bodies verbatim.
|
|
9
|
+
* Codex maps an *empty* body to the literal client string "Unknown error"
|
|
10
|
+
* (UnexpectedResponseError) — issue #452. Only empty bodies need wrapping.
|
|
11
|
+
*
|
|
12
|
+
* Non-empty bodies (including ChatGPT `{detail: ...}` account-model 400s and
|
|
13
|
+
* HTML/text errors) must keep their original bytes and headers so pool-retry
|
|
14
|
+
* activation and client diagnostics stay honest.
|
|
15
|
+
*
|
|
16
|
+
* Retry-After is validated independently of the body path:
|
|
17
|
+
* - valid upstream values are preserved
|
|
18
|
+
* - missing/malformed values are replaced when resolveClientRetryAfter yields a value
|
|
19
|
+
* - malformed/expired values are removed when the resolver returns undefined
|
|
20
|
+
* (e.g. quota-exhausted 429s must not keep junk headers or get the synthetic "2")
|
|
21
|
+
*/
|
|
22
|
+
export function formatPassthroughUpstreamError(
|
|
23
|
+
status: number,
|
|
24
|
+
bodyText: string,
|
|
25
|
+
options?: {
|
|
26
|
+
statusText?: string;
|
|
27
|
+
headers?: Headers;
|
|
28
|
+
now?: number;
|
|
29
|
+
},
|
|
30
|
+
): Response {
|
|
31
|
+
const trimmed = bodyText.trim();
|
|
32
|
+
const now = options?.now ?? Date.now();
|
|
33
|
+
const upstreamRetryAfter = options?.headers?.get("retry-after")?.trim() || undefined;
|
|
34
|
+
const originalValid = validateClientRetryAfterHeader(upstreamRetryAfter, now);
|
|
35
|
+
const resolved = resolveClientRetryAfter({
|
|
36
|
+
status,
|
|
37
|
+
message: trimmed || `Provider error ${status}: (empty body)`,
|
|
38
|
+
upstreamRetryAfter,
|
|
39
|
+
now,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (trimmed) {
|
|
43
|
+
const needsSet = resolved !== undefined && upstreamRetryAfter !== resolved;
|
|
44
|
+
const needsDelete = resolved === undefined
|
|
45
|
+
&& upstreamRetryAfter !== undefined
|
|
46
|
+
&& originalValid === undefined;
|
|
47
|
+
|
|
48
|
+
if (!needsSet && !needsDelete) {
|
|
49
|
+
return new Response(bodyText, {
|
|
50
|
+
status,
|
|
51
|
+
...(options?.statusText ? { statusText: options.statusText } : {}),
|
|
52
|
+
...(options?.headers ? { headers: options.headers } : { headers: { "Content-Type": "application/json" } }),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const headers = options?.headers
|
|
57
|
+
? new Headers(options.headers)
|
|
58
|
+
: new Headers({ "Content-Type": "application/json" });
|
|
59
|
+
if (needsSet) headers.set("Retry-After", resolved!);
|
|
60
|
+
else headers.delete("Retry-After");
|
|
61
|
+
return new Response(bodyText, {
|
|
62
|
+
status,
|
|
63
|
+
...(options?.statusText ? { statusText: options.statusText } : {}),
|
|
64
|
+
headers,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const response = formatErrorResponse(
|
|
69
|
+
status,
|
|
70
|
+
"upstream_error",
|
|
71
|
+
`Provider error ${status}: (empty body)`,
|
|
72
|
+
resolved !== undefined ? { retryAfter: resolved } : undefined,
|
|
73
|
+
);
|
|
74
|
+
const headers = new Headers(response.headers);
|
|
75
|
+
headers.set("Content-Type", "application/json");
|
|
76
|
+
if (resolved !== undefined) headers.set("Retry-After", resolved);
|
|
77
|
+
return new Response(response.body, { status: response.status, headers });
|
|
78
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { comboFailureDecision } from "../../combos/failover";
|
|
2
|
+
import { readBoundedResponseBody } from "../../lib/bounded-body";
|
|
3
|
+
import { readJsonRequestBody } from "../request-decompress";
|
|
4
|
+
import { finishRequestAttempt, type RequestLogContext } from "../request-log";
|
|
5
|
+
import type { OcxConfig } from "../../types";
|
|
6
|
+
import type { RouteCandidateTrace, RouteDecisionTraceV1 } from "../../routing/trace";
|
|
7
|
+
import { handleResponses as handleResponsesCore } from "./core";
|
|
8
|
+
import { requestPacingOverloadResponse } from "./pacing-overload";
|
|
9
|
+
|
|
10
|
+
type CoreHandler = typeof handleResponsesCore;
|
|
11
|
+
type CoreOptions = Parameters<CoreHandler>[3];
|
|
12
|
+
|
|
13
|
+
export interface PolicyFallbackDeps {
|
|
14
|
+
runCore?: CoreHandler;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function candidateKey(candidate: Pick<RouteCandidateTrace, "provider" | "model">): string {
|
|
18
|
+
return `${candidate.provider}\u0000${candidate.model}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Rank the remaining candidates from the ORIGINAL policy trace. The initial
|
|
23
|
+
* decision stays immutable; fallback execution belongs in attempts[], not in a
|
|
24
|
+
* rewritten decision trace.
|
|
25
|
+
*/
|
|
26
|
+
export function rankPolicyFallbackCandidates(
|
|
27
|
+
trace: RouteDecisionTraceV1,
|
|
28
|
+
tried: ReadonlySet<string>,
|
|
29
|
+
): RouteCandidateTrace[] {
|
|
30
|
+
return trace.candidates
|
|
31
|
+
.map((candidate, index) => ({ candidate, index }))
|
|
32
|
+
.filter(({ candidate }) =>
|
|
33
|
+
candidate.eligible
|
|
34
|
+
&& candidate.exclusions.length === 0
|
|
35
|
+
&& !tried.has(candidateKey(candidate)))
|
|
36
|
+
.sort((left, right) => {
|
|
37
|
+
const scoreDelta = (right.candidate.score?.total ?? Number.NEGATIVE_INFINITY)
|
|
38
|
+
- (left.candidate.score?.total ?? Number.NEGATIVE_INFINITY);
|
|
39
|
+
return scoreDelta || left.index - right.index;
|
|
40
|
+
})
|
|
41
|
+
.map(({ candidate }) => candidate);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function requestWithCandidate(
|
|
45
|
+
req: Request,
|
|
46
|
+
rawBody: Record<string, unknown>,
|
|
47
|
+
candidate: Pick<RouteCandidateTrace, "provider" | "model">,
|
|
48
|
+
): Request {
|
|
49
|
+
const headers = new Headers(req.headers);
|
|
50
|
+
headers.delete("content-encoding");
|
|
51
|
+
headers.delete("content-length");
|
|
52
|
+
headers.set("content-type", "application/json");
|
|
53
|
+
return new Request(req.url, {
|
|
54
|
+
method: req.method,
|
|
55
|
+
headers,
|
|
56
|
+
body: JSON.stringify({ ...rawBody, model: `${candidate.provider}/${candidate.model}` }),
|
|
57
|
+
signal: req.signal,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function errorCodeFromText(text: string): string | undefined {
|
|
62
|
+
if (!text) return undefined;
|
|
63
|
+
try {
|
|
64
|
+
const payload = JSON.parse(text) as { error?: { code?: unknown; type?: unknown }; code?: unknown };
|
|
65
|
+
const candidate = payload.error?.code ?? payload.error?.type ?? payload.code;
|
|
66
|
+
return typeof candidate === "string" ? candidate : undefined;
|
|
67
|
+
} catch {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function shouldHopPolicyCandidate(response: Response, signal?: AbortSignal): Promise<boolean> {
|
|
73
|
+
if (response.status < 400 || signal?.aborted) return false;
|
|
74
|
+
try {
|
|
75
|
+
const inspected = await readBoundedResponseBody(response.clone(), { signal });
|
|
76
|
+
const text = inspected.displaySafe ? inspected.text : "";
|
|
77
|
+
return comboFailureDecision(response.status, text, { code: errorCodeFromText(text) }) === "hop";
|
|
78
|
+
} catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isPolicyDecision(trace: RouteDecisionTraceV1 | undefined): trace is RouteDecisionTraceV1 {
|
|
84
|
+
return trace?.routeKind === "policy" && !!trace.profile;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Finalize the failed physical attempt so the retry receives a fresh attempt row. */
|
|
88
|
+
function finishFailedPolicyAttempt(logCtx: RequestLogContext, status: number): void {
|
|
89
|
+
const attempt = logCtx.activeAttempt;
|
|
90
|
+
if (attempt) {
|
|
91
|
+
const startedAt = logCtx.activeAttemptStartedAt ?? Date.now();
|
|
92
|
+
finishRequestAttempt(attempt, status, Math.max(0, Date.now() - startedAt), attempt.usage ?? logCtx.usage);
|
|
93
|
+
}
|
|
94
|
+
delete logCtx.activeAttempt;
|
|
95
|
+
delete logCtx.activeAttemptStartedAt;
|
|
96
|
+
delete logCtx.usage;
|
|
97
|
+
delete logCtx.usageFromBridge;
|
|
98
|
+
delete logCtx.upstreamError;
|
|
99
|
+
delete logCtx.terminalHttpStatus;
|
|
100
|
+
delete logCtx.terminalErrorCode;
|
|
101
|
+
delete logCtx.terminalIncompleteReason;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Run a Responses request and, only for an explicitly selected policy profile,
|
|
106
|
+
* hop to the next eligible policy candidate after a retryable pre-success
|
|
107
|
+
* failure. The initial policy trace remains the canonical selection evidence;
|
|
108
|
+
* physical retries continue to accumulate in the existing request attempts.
|
|
109
|
+
*/
|
|
110
|
+
export async function handleResponsesWithPolicyFallback(
|
|
111
|
+
req: Request,
|
|
112
|
+
config: OcxConfig,
|
|
113
|
+
logCtx: RequestLogContext,
|
|
114
|
+
options: CoreOptions = {},
|
|
115
|
+
deps: PolicyFallbackDeps = {},
|
|
116
|
+
): Promise<Response> {
|
|
117
|
+
const runCore = deps.runCore ?? handleResponsesCore;
|
|
118
|
+
let requestBodyReadNotified = false;
|
|
119
|
+
const coreOptions: CoreOptions = options.onRequestBodyRead
|
|
120
|
+
? {
|
|
121
|
+
...options,
|
|
122
|
+
onRequestBodyRead: () => {
|
|
123
|
+
if (requestBodyReadNotified) return;
|
|
124
|
+
requestBodyReadNotified = true;
|
|
125
|
+
options.onRequestBodyRead?.();
|
|
126
|
+
},
|
|
127
|
+
}
|
|
128
|
+
: options;
|
|
129
|
+
let rawBody: Record<string, unknown> | null = null;
|
|
130
|
+
try {
|
|
131
|
+
const parsed = await readJsonRequestBody(req.clone());
|
|
132
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) rawBody = parsed as Record<string, unknown>;
|
|
133
|
+
} catch {
|
|
134
|
+
// Core owns the client-facing parse/decompression error.
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let response: Response;
|
|
138
|
+
try {
|
|
139
|
+
response = await runCore(req, config, logCtx, coreOptions);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
const overload = requestPacingOverloadResponse(error);
|
|
142
|
+
if (overload) return overload;
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
const initialTrace = logCtx.routeDecision;
|
|
146
|
+
const initialRequestedModel = logCtx.requestedModel;
|
|
147
|
+
if (!rawBody || !isPolicyDecision(initialTrace)) return response;
|
|
148
|
+
|
|
149
|
+
const tried = new Set<string>([
|
|
150
|
+
candidateKey({ provider: initialTrace.selected.provider, model: initialTrace.selected.model }),
|
|
151
|
+
]);
|
|
152
|
+
|
|
153
|
+
while (await shouldHopPolicyCandidate(response, req.signal)) {
|
|
154
|
+
if (req.signal.aborted) return response;
|
|
155
|
+
const next = rankPolicyFallbackCandidates(initialTrace, tried)[0];
|
|
156
|
+
if (!next) return response;
|
|
157
|
+
tried.add(candidateKey(next));
|
|
158
|
+
|
|
159
|
+
finishFailedPolicyAttempt(logCtx, response.status);
|
|
160
|
+
const retryRequest = requestWithCandidate(req, rawBody, next);
|
|
161
|
+
try {
|
|
162
|
+
try {
|
|
163
|
+
response = await runCore(retryRequest, config, logCtx, coreOptions);
|
|
164
|
+
} catch (error) {
|
|
165
|
+
const overload = requestPacingOverloadResponse(error);
|
|
166
|
+
if (overload) return overload;
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
} finally {
|
|
170
|
+
logCtx.requestedModel = initialRequestedModel;
|
|
171
|
+
logCtx.routeDecision = initialTrace;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return response;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export const handleResponses = handleResponsesWithPolicyFallback;
|