@iislee/opencodex 2.11.0 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS_INSTALL.md +109 -0
- package/README.md +117 -22
- package/bin/ocx.mjs +245 -88
- package/bin/package-main.mjs +1 -1
- package/gui/dist/assets/index-Be1sDpWw.css +1 -0
- package/gui/dist/assets/index-D4OKgUV4.js +114 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/alibaba-color.svg +1 -1
- package/gui/dist/provider-icons/antigravity-color.svg +1 -1
- package/gui/dist/provider-icons/claude-color.svg +1 -1
- package/gui/dist/provider-icons/cline-color.svg +16 -0
- package/gui/dist/provider-icons/cloudflare-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/commandcode-color.svg +1 -0
- package/gui/dist/provider-icons/copilot-color.svg +1 -1
- package/gui/dist/provider-icons/cursor-color.svg +1 -1
- package/gui/dist/provider-icons/deepseek-color.svg +1 -1
- package/gui/dist/provider-icons/firepass-color.svg +1 -1
- package/gui/dist/provider-icons/fireworks-color.svg +1 -1
- package/gui/dist/provider-icons/gemini-color.svg +1 -1
- package/gui/dist/provider-icons/github-copilot-color.svg +1 -1
- package/gui/dist/provider-icons/gitlab-duo-color.svg +1 -1
- package/gui/dist/provider-icons/grok.svg +1 -1
- package/gui/dist/provider-icons/groq-color.svg +1 -1
- package/gui/dist/provider-icons/huggingface-color.svg +1 -1
- package/gui/dist/provider-icons/kimi-color.svg +1 -1
- package/gui/dist/provider-icons/kiro-color.svg +2 -2
- package/gui/dist/provider-icons/lm-studio-color.svg +1 -1
- package/gui/dist/provider-icons/mistral-color.svg +1 -1
- package/gui/dist/provider-icons/moonshot-color.svg +1 -1
- package/gui/dist/provider-icons/nvidia-color.svg +1 -1
- package/gui/dist/provider-icons/ollama-color.svg +1 -1
- package/gui/dist/provider-icons/openai.svg +1 -1
- package/gui/dist/provider-icons/opencode.svg +2 -1
- package/gui/dist/provider-icons/openrouter-color.svg +1 -1
- package/gui/dist/provider-icons/pi.svg +2 -2
- package/gui/dist/provider-icons/qianfan-color.svg +1 -1
- package/gui/dist/provider-icons/qwen-portal-color.svg +1 -1
- package/gui/dist/provider-icons/vercel-ai-gateway-color.svg +1 -1
- package/gui/dist/provider-icons/vllm-color.svg +1 -1
- package/gui/dist/provider-icons/xiaomi-color.svg +1 -1
- package/package.json +21 -10
- package/src/adapters/anthropic-output-schema.ts +137 -0
- package/src/adapters/anthropic.ts +475 -62
- package/src/adapters/base.ts +82 -7
- package/src/adapters/client-fingerprint.ts +18 -12
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +69 -0
- package/src/adapters/command-code.ts +637 -0
- package/src/adapters/cursor/call-id.ts +44 -0
- package/src/adapters/cursor/catalog.ts +541 -0
- package/src/adapters/cursor/checkpoint-store.ts +308 -0
- package/src/adapters/cursor/cursor-errors.ts +144 -6
- package/src/adapters/cursor/discovery.ts +122 -14
- package/src/adapters/cursor/effort-map.ts +106 -4
- package/src/adapters/cursor/envelope-echo.ts +290 -0
- package/src/adapters/cursor/framing.ts +39 -0
- package/src/adapters/cursor/h2-pool.ts +123 -0
- package/src/adapters/cursor/http1-bidi.ts +361 -0
- package/src/adapters/cursor/images.ts +704 -0
- package/src/adapters/cursor/live-models.ts +180 -59
- package/src/adapters/cursor/live-transport.ts +623 -170
- package/src/adapters/cursor/message-mapper.ts +4 -1
- package/src/adapters/cursor/native-exec-common.ts +23 -2
- package/src/adapters/cursor/native-exec-desktop.ts +23 -0
- package/src/adapters/cursor/native-exec-fs.ts +10 -7
- package/src/adapters/cursor/native-exec-network.ts +1 -1
- package/src/adapters/cursor/native-exec-shell.ts +5 -3
- package/src/adapters/cursor/native-exec.ts +121 -14
- package/src/adapters/cursor/protobuf-events.ts +829 -11
- package/src/adapters/cursor/protobuf-request.ts +447 -75
- package/src/adapters/cursor/request-builder.ts +271 -35
- package/src/adapters/cursor/tool-definitions.ts +252 -12
- package/src/adapters/cursor/tool-result-normalize.ts +115 -0
- package/src/adapters/cursor/transport.ts +22 -0
- package/src/adapters/cursor/types.ts +48 -1
- package/src/adapters/cursor.ts +336 -39
- package/src/adapters/exec-tool-result-normalize.ts +99 -0
- package/src/adapters/google-antigravity-replay.ts +713 -41
- package/src/adapters/google-antigravity-wire.ts +48 -10
- package/src/adapters/google-errors.ts +44 -12
- package/src/adapters/google-http.ts +38 -10
- package/src/adapters/google-tool-schema.ts +80 -15
- package/src/adapters/google-truncation.ts +11 -0
- package/src/adapters/google.ts +742 -86
- package/src/adapters/identity.ts +39 -6
- package/src/adapters/image.ts +1 -1
- package/src/adapters/kiro-constants.ts +27 -0
- package/src/adapters/kiro-errors.ts +11 -0
- package/src/adapters/kiro-events.ts +19 -1
- package/src/adapters/kiro-thinking.ts +18 -2
- package/src/adapters/kiro-tools.ts +65 -17
- package/src/adapters/kiro.ts +270 -73
- package/src/adapters/mimo-free.ts +17 -0
- package/src/adapters/openai-chat-url.ts +11 -0
- package/src/adapters/openai-chat.ts +1377 -344
- package/src/adapters/openai-responses-url.ts +16 -0
- package/src/adapters/openai-responses.ts +1164 -64
- package/src/adapters/registry.ts +175 -0
- package/src/adapters/responses-tool-schema.ts +67 -0
- package/src/adapters/run-turn-queue.ts +36 -1
- package/src/adapters/tool-call-id.ts +119 -0
- package/src/adapters/tool-catalog-nudge.ts +105 -21
- package/src/adapters/xai-tool-schema.ts +436 -0
- package/src/adapters/xai-web-search.ts +186 -0
- package/src/bridge.ts +512 -92
- package/src/chat/inbound.ts +57 -20
- package/src/chat/outbound.ts +97 -33
- package/src/claude/agents-inject.ts +40 -10
- package/src/claude/context-windows.ts +37 -14
- package/src/claude/desktop-3p.ts +243 -9
- package/src/claude/gateway-cache.ts +41 -4
- package/src/claude/inbound.ts +72 -3
- package/src/claude/model-info.ts +38 -15
- package/src/claude/outbound.ts +88 -21
- package/src/cli/access.ts +46 -3
- package/src/cli/account-api.ts +150 -19
- package/src/cli/account-auth.ts +33 -6
- package/src/cli/account-catalog-refresh.ts +14 -0
- package/src/cli/account-extended.ts +648 -28
- package/src/cli/account-main.ts +317 -0
- package/src/cli/account.ts +97 -19
- package/src/cli/agent.ts +53 -2
- package/src/cli/alias.ts +66 -0
- package/src/cli/capabilities-command.ts +94 -0
- package/src/cli/capabilities.ts +496 -0
- package/src/cli/claude-agent-startup-sync.ts +73 -0
- package/src/cli/claude-desktop.ts +60 -15
- package/src/cli/claude.ts +129 -35
- package/src/cli/codex-log-guard-doctor.ts +103 -0
- package/src/cli/codex-shim-autorestore.ts +2 -0
- package/src/cli/codex-shim-readiness.ts +76 -0
- package/src/cli/combo.ts +8 -0
- package/src/cli/config-command.ts +74 -10
- package/src/cli/dispatch.ts +821 -0
- package/src/cli/doctor.ts +440 -56
- package/src/cli/ensure-desired-integrations.ts +152 -0
- package/src/cli/export-command.ts +46 -20
- package/src/cli/help.ts +34 -274
- package/src/cli/index.ts +417 -528
- package/src/cli/init.ts +5 -17
- package/src/cli/inspect.ts +230 -0
- package/src/cli/integrations.ts +120 -2
- package/src/cli/lab.ts +607 -0
- package/src/cli/launcher-context.ts +77 -0
- package/src/cli/minimax.ts +497 -0
- package/src/cli/models-runtime.ts +130 -2
- package/src/cli/models.ts +118 -16
- package/src/cli/observe.ts +123 -11
- package/src/cli/opencode.ts +4 -2
- package/src/cli/provider-runtime.ts +34 -3
- package/src/cli/provider.ts +25 -3
- package/src/cli/ready.ts +301 -0
- package/src/cli/registry.ts +476 -0
- package/src/cli/root.ts +86 -0
- package/src/cli/route-policy.ts +92 -0
- package/src/cli/runtime-api.ts +57 -10
- package/src/cli/star-prompt.ts +71 -15
- package/src/cli/status.ts +51 -4
- package/src/cli/storage.ts +234 -0
- package/src/cli/system-command.ts +16 -0
- package/src/cli/system-restart-client.ts +146 -0
- package/src/cli/tray-proxy.ts +153 -6
- package/src/cli/usage-report.ts +184 -0
- package/src/cli/v2.ts +137 -18
- package/src/cli/version-skew.ts +46 -0
- package/src/cli.ts +1 -1
- package/src/clients/config-export.ts +1442 -23
- package/src/clients/effective-status.ts +30 -2
- package/src/clients/probes/cline.ts +81 -0
- package/src/codex/account-label.ts +35 -1
- package/src/codex/account-lifecycle.ts +130 -13
- package/src/codex/account-namespaces.ts +49 -3
- package/src/codex/account-pause.ts +2 -1
- package/src/codex/account-priority.ts +84 -0
- package/src/codex/account-store.ts +29 -2
- package/src/codex/account-usability.ts +25 -2
- package/src/codex/admission.ts +256 -0
- package/src/codex/affinity-debug.ts +162 -0
- package/src/codex/app-server-processes.ts +570 -107
- package/src/codex/app-server-restart-service.ts +232 -0
- package/src/codex/auth-api.ts +893 -246
- package/src/codex/auth-collision.ts +5 -3
- package/src/codex/auth-context.ts +348 -32
- package/src/codex/autostart-health.ts +24 -1
- package/src/codex/catalog/account-models.ts +67 -0
- package/src/codex/catalog/aggregation.ts +86 -10
- package/src/codex/catalog/bundled.ts +331 -33
- package/src/codex/catalog/effort.ts +138 -32
- package/src/codex/catalog/filesystem-evidence.ts +302 -0
- package/src/codex/catalog/kinds.ts +2 -0
- package/src/codex/catalog/metadata.ts +555 -45
- package/src/codex/catalog/native-models.ts +75 -0
- package/src/codex/catalog/parsing.ts +269 -30
- package/src/codex/catalog/provider-fetch.ts +1626 -144
- package/src/codex/catalog/sync.ts +1576 -187
- package/src/codex/catalog-admission.ts +199 -0
- package/src/codex/catalog-refresh-status.ts +105 -0
- package/src/codex/catalog-write-serialization.ts +242 -0
- package/src/codex/catalog.ts +6 -3
- package/src/codex/codex-write-lock.ts +386 -0
- package/src/codex/convergence-types.ts +614 -0
- package/src/codex/convergence.ts +676 -0
- package/src/codex/coordinator-doctor.ts +332 -0
- package/src/codex/custom-model-catalog-migration.ts +176 -0
- package/src/codex/desired-state.ts +230 -0
- package/src/codex/desktop-app-restart.ts +355 -0
- package/src/codex/features.ts +636 -39
- package/src/codex/generation.ts +202 -0
- package/src/codex/history-job.ts +436 -0
- package/src/codex/history-lock.ts +242 -0
- package/src/codex/history-manifest.ts +112 -0
- package/src/codex/history-migration-guardian.ts +30 -24
- package/src/codex/history-provider.ts +1016 -235
- package/src/codex/history-transition.ts +105 -0
- package/src/codex/history-worker.ts +223 -0
- package/src/codex/inject-coordination.ts +373 -0
- package/src/codex/inject.ts +1114 -152
- package/src/codex/injected-marker.ts +37 -3
- package/src/codex/integration-record.ts +266 -0
- package/src/codex/internal/catalog-writer.ts +203 -0
- package/src/codex/internal/history-writer.ts +81 -0
- package/src/codex/journal.ts +66 -4
- package/src/codex/log-guard/inspect.ts +524 -0
- package/src/codex/log-guard/lock.ts +150 -0
- package/src/codex/log-guard/maintenance.ts +403 -0
- package/src/codex/log-guard/path-safety.ts +88 -0
- package/src/codex/log-guard/policy.ts +44 -0
- package/src/codex/log-guard/processes.ts +205 -0
- package/src/codex/log-guard/protection.ts +489 -0
- package/src/codex/log-guard/sqlite-errors.ts +9 -0
- package/src/codex/main-account-cache.ts +24 -0
- package/src/codex/main-account.ts +29 -1
- package/src/codex/management-convergence.ts +167 -0
- package/src/codex/model-cache.ts +56 -10
- package/src/codex/model-entitlements.ts +360 -0
- package/src/codex/native-main-admission.ts +47 -0
- package/src/codex/native-main-auth-temp.ts +187 -0
- package/src/codex/native-main-claim.ts +178 -0
- package/src/codex/native-main-lock-file.ts +162 -0
- package/src/codex/native-main-owner.ts +329 -0
- package/src/codex/native-profile-api.ts +247 -0
- package/src/codex/native-profile-manager.ts +1531 -0
- package/src/codex/native-profile-processes.ts +121 -0
- package/src/codex/native-profile-recovery.ts +99 -0
- package/src/codex/native-profile-stage-store.ts +387 -0
- package/src/codex/native-profile-startup.ts +622 -0
- package/src/codex/native-profile-store.ts +855 -0
- package/src/codex/native-profile-types.ts +120 -0
- package/src/codex/native-residue.ts +675 -0
- package/src/codex/paths.ts +80 -1
- package/src/codex/plan-from-token.ts +140 -0
- package/src/codex/plan.ts +40 -0
- package/src/codex/plugins-doctor.ts +1 -1
- package/src/codex/pool-rotation.ts +74 -4
- package/src/codex/project-config-warnings.ts +20 -6
- package/src/codex/prompt-journal.ts +352 -0
- package/src/codex/prompt-layers.ts +1313 -0
- package/src/codex/prompt-lock.ts +143 -0
- package/src/codex/prompt-text-probe.ts +238 -0
- package/src/codex/quota-rejection.ts +298 -0
- package/src/codex/quota.ts +264 -21
- package/src/codex/refresh.ts +11 -2
- package/src/codex/reset-credit-recovery.ts +1044 -0
- package/src/codex/routing.ts +514 -94
- package/src/codex/runtime.ts +159 -38
- package/src/codex/shim.ts +1065 -31
- package/src/codex/subagent-model-fallback.ts +437 -43
- package/src/codex/sync.ts +191 -2
- package/src/codex/transition-state.ts +720 -0
- package/src/codex/upstream-host-health.ts +368 -0
- package/src/codex/user-identity.ts +557 -0
- package/src/codex/warmup.ts +187 -81
- package/src/codex/write-coordination.ts +114 -0
- package/src/combos/failover.ts +47 -0
- package/src/combos/index.ts +4 -0
- package/src/combos/request.ts +32 -0
- package/src/combos/types.ts +91 -9
- package/src/compatibility/index.ts +26 -0
- package/src/compatibility/manifest.ts +253 -0
- package/src/compatibility/openai-responses.ts +121 -0
- package/src/config/atomic-write.ts +219 -0
- package/src/config/paths.ts +40 -0
- package/src/config/process-state.ts +309 -0
- package/src/config/provider-name.ts +24 -0
- package/src/config/provider-validation.ts +177 -0
- package/src/config/rebase-provenance.ts +68 -0
- package/src/config.ts +1713 -709
- package/src/generated/compatibility-version.json +3324 -0
- package/src/generated/{jawcode-model-metadata.ts → model-metadata.ts} +19 -17
- package/src/grok/inject.ts +16 -5
- package/src/grok/inspect.ts +45 -0
- package/src/grok/sync.ts +2 -2
- package/src/images/loop.ts +157 -33
- package/src/images/plan.ts +24 -13
- package/src/integrations/config-io.ts +269 -0
- package/src/integrations/journal.ts +315 -0
- package/src/integrations/merge.ts +135 -0
- package/src/integrations/mutation-flight.ts +71 -0
- package/src/integrations/native/ownership-preflight.ts +202 -0
- package/src/integrations/omp-yaml-source.ts +358 -0
- package/src/integrations/owned-refresh.ts +74 -0
- package/src/integrations/ownership-policy.ts +160 -0
- package/src/integrations/ownership.ts +155 -0
- package/src/integrations/registry.ts +166 -0
- package/src/integrations/serialize.ts +314 -0
- package/src/integrations/state.ts +433 -0
- package/src/integrations/store.ts +103 -0
- package/src/integrations/writer-lock.ts +98 -0
- package/src/integrations/writer.ts +715 -0
- package/src/lab/artifacts/sanitize.ts +586 -0
- package/src/lab/artifacts/secure-fs.ts +475 -0
- package/src/lab/artifacts/store.ts +310 -0
- package/src/lab/automation/budgets.ts +78 -0
- package/src/lab/automation/config-persistence.ts +256 -0
- package/src/lab/automation/constants.ts +39 -0
- package/src/lab/automation/cooldown.ts +103 -0
- package/src/lab/automation/dispatch.ts +211 -0
- package/src/lab/automation/index.ts +13 -0
- package/src/lab/automation/orchestrator.ts +499 -0
- package/src/lab/automation/persistence.ts +512 -0
- package/src/lab/automation/planner.ts +371 -0
- package/src/lab/automation/policy.ts +136 -0
- package/src/lab/automation/queue.ts +191 -0
- package/src/lab/automation/recovery.ts +24 -0
- package/src/lab/automation/route-context.ts +21 -0
- package/src/lab/automation/run-key.ts +44 -0
- package/src/lab/automation/runs-query.ts +34 -0
- package/src/lab/automation/types.ts +160 -0
- package/src/lab/conformance/assertion.ts +325 -0
- package/src/lab/conformance/digest.ts +22 -0
- package/src/lab/conformance/executor.ts +741 -0
- package/src/lab/conformance/fixture-provider.ts +27 -0
- package/src/lab/conformance/fixtures/live-v1-cases.json +175 -0
- package/src/lab/conformance/fixtures/protocol-v1-cases.json +461 -0
- package/src/lab/conformance/harness-budget.ts +47 -0
- package/src/lab/conformance/index.ts +5 -0
- package/src/lab/conformance/jcs.ts +64 -0
- package/src/lab/conformance/json-pointer.ts +39 -0
- package/src/lab/conformance/manifest.ts +180 -0
- package/src/lab/conformance/mcp-stub.ts +179 -0
- package/src/lab/conformance/negative-controls.ts +164 -0
- package/src/lab/conformance/observation.ts +355 -0
- package/src/lab/conformance/runner.ts +68 -0
- package/src/lab/conformance/sse-normalize.ts +59 -0
- package/src/lab/conformance/suite-manifest.ts +78 -0
- package/src/lab/conformance/types.ts +214 -0
- package/src/lab/constants.ts +126 -0
- package/src/lab/digest.ts +64 -0
- package/src/lab/events/errors.ts +9 -0
- package/src/lab/events/limits.ts +117 -0
- package/src/lab/events/types.ts +229 -0
- package/src/lab/events/validate.ts +781 -0
- package/src/lab/fabric/constants.ts +40 -0
- package/src/lab/fabric/executor.ts +492 -0
- package/src/lab/fabric/index.ts +80 -0
- package/src/lab/fabric/manifest.ts +222 -0
- package/src/lab/fabric/observe.ts +489 -0
- package/src/lab/fabric/patch.ts +79 -0
- package/src/lab/fabric/producer-child.ts +139 -0
- package/src/lab/fabric/producer-isolate.ts +276 -0
- package/src/lab/fabric/producer-protocol.ts +61 -0
- package/src/lab/fabric/scratch.ts +439 -0
- package/src/lab/fabric/subject.ts +106 -0
- package/src/lab/fabric/types.ts +134 -0
- package/src/lab/fabric/verifier.ts +98 -0
- package/src/lab/index.ts +54 -0
- package/src/lab/ledger/artifact-refs.ts +127 -0
- package/src/lab/ledger/invalidation.ts +136 -0
- package/src/lab/ledger/purge.ts +310 -0
- package/src/lab/ledger/store.ts +532 -0
- package/src/lab/live/credential-lease.ts +53 -0
- package/src/lab/live/destination.ts +155 -0
- package/src/lab/live/executor.ts +336 -0
- package/src/lab/live/inert-tools.ts +56 -0
- package/src/lab/live/manifest.ts +85 -0
- package/src/lab/live/mcp-loopback.ts +57 -0
- package/src/lab/live/runner.ts +19 -0
- package/src/lab/live/sandbox.ts +61 -0
- package/src/lab/live/suite-manifest.ts +41 -0
- package/src/lab/live/transport.ts +118 -0
- package/src/lab/live/types.ts +197 -0
- package/src/lab/observe/from-conformance.ts +301 -0
- package/src/lab/observe/from-live.ts +117 -0
- package/src/lab/paths.ts +153 -0
- package/src/lab/projection/rebuild.ts +495 -0
- package/src/lab/projection/schema.ts +135 -0
- package/src/lab/projection/verdicts.ts +474 -0
- package/src/lab/projection/verification.ts +412 -0
- package/src/lab/public/bundle.ts +217 -0
- package/src/lab/public/community-authority.ts +175 -0
- package/src/lab/public/community-files.ts +29 -0
- package/src/lab/public/community.ts +479 -0
- package/src/lab/public/file-safety.ts +155 -0
- package/src/lab/public/ids.ts +26 -0
- package/src/lab/public/index.ts +16 -0
- package/src/lab/public/mutation-lock.ts +424 -0
- package/src/lab/public/operator.ts +353 -0
- package/src/lab/public/origin-purge.ts +79 -0
- package/src/lab/public/origin.ts +203 -0
- package/src/lab/public/privacy.ts +143 -0
- package/src/lab/public/private-file.ts +261 -0
- package/src/lab/public/project.ts +124 -0
- package/src/lab/public/purge-test-fault.ts +21 -0
- package/src/lab/public/purge.ts +223 -0
- package/src/lab/public/registry.ts +44 -0
- package/src/lab/public/revocation.ts +252 -0
- package/src/lab/public/signature.ts +243 -0
- package/src/lab/public/storage.ts +105 -0
- package/src/lab/public/strict-json.ts +206 -0
- package/src/lab/public/time.ts +26 -0
- package/src/lab/public/types.ts +172 -0
- package/src/lab/public/validate.ts +391 -0
- package/src/lab/query/catalog.ts +101 -0
- package/src/lab/query/connection.ts +107 -0
- package/src/lab/query/constants.ts +4 -0
- package/src/lab/query/cursor.ts +132 -0
- package/src/lab/query/dto-map.ts +277 -0
- package/src/lab/query/errors.ts +22 -0
- package/src/lab/query/freshness.ts +53 -0
- package/src/lab/query/index.ts +45 -0
- package/src/lab/query/latest-observation.ts +59 -0
- package/src/lab/query/passive-production.ts +159 -0
- package/src/lab/query/queries.ts +444 -0
- package/src/lab/query/types.ts +266 -0
- package/src/lab/subject/behavior-fingerprint.ts +77 -0
- package/src/lab/subject/installation-salt.ts +112 -0
- package/src/lab/subject/protocol-subject.ts +80 -0
- package/src/lab/subject/route-subject.ts +74 -0
- package/src/lib/admin-secrets.ts +24 -0
- package/src/lib/app-owned-memory-stores.ts +22 -0
- package/src/lib/bounded-body.ts +167 -11
- package/src/lib/bun-runtime.ts +125 -12
- package/src/lib/bun-stream-caps.ts +13 -9
- package/src/lib/codex-restart-contract.ts +120 -0
- package/src/lib/config-ownership.ts +26 -2
- package/src/lib/destination-policy.ts +65 -1
- package/src/lib/errors.ts +80 -5
- package/src/lib/fabric-task-execution-authority.ts +7 -0
- package/src/lib/fabric-task-host.ts +29 -0
- package/src/lib/lab-activation.ts +223 -0
- package/src/lib/lab-live-execution-authority.ts +13 -0
- package/src/lib/lab-live-host.ts +30 -0
- package/src/lib/lab-live-pinned-sender.ts +56 -0
- package/src/lib/lab-live-route-production.ts +130 -0
- package/src/lib/lab-passive-linker-registration.ts +26 -0
- package/src/lib/local-management-attestation.ts +51 -0
- package/src/lib/local-management-capability.ts +100 -0
- package/src/lib/local-provider-reload-contract.ts +100 -0
- package/src/lib/optional-shutdown-hooks.ts +57 -0
- package/src/lib/package-tree-integrity.ts +101 -0
- package/src/lib/pinned-http.ts +145 -26
- package/src/lib/process-control.ts +6 -2
- package/src/lib/provider-outbound.ts +49 -9
- package/src/lib/redact.ts +419 -3
- package/src/lib/self-launch-argv.ts +15 -0
- package/src/lib/server-resource-ownership.ts +71 -0
- package/src/lib/service-secrets.ts +15 -0
- package/src/lib/shadow-call.ts +35 -4
- package/src/lib/sse-decoder.ts +41 -0
- package/src/lib/state-store-registrations.ts +10 -2
- package/src/lib/system-restart-contract.ts +73 -0
- package/src/lib/token-estimate.ts +19 -2
- package/src/lib/tool-argument-integers.ts +253 -0
- package/src/lib/translator-budget.ts +44 -0
- package/src/lib/upstream-http-version.ts +57 -0
- package/src/lib/upstream-reachability.ts +95 -0
- package/src/lib/upstream-retry.ts +156 -3
- package/src/lib/windows-atomic-replace.ts +155 -0
- package/src/lib/windows-elevation.ts +70 -2
- package/src/lib/windows-secret-acl.ts +409 -69
- package/src/lib/windows-service-wrappers.ts +72 -0
- package/src/lib/windows-text.ts +106 -0
- package/src/lib/windows-user-principal.ts +341 -0
- package/src/lib/winsw.ts +33 -5
- package/src/oauth/account-import/google-antigravity-adapter.ts +74 -0
- package/src/oauth/account-import/index.ts +15 -0
- package/src/oauth/account-import/parser.ts +83 -0
- package/src/oauth/account-import/registry.ts +18 -0
- package/src/oauth/account-import/service.ts +75 -0
- package/src/oauth/account-import/types.ts +91 -0
- package/src/oauth/anthropic.ts +12 -1
- package/src/oauth/callback-server.ts +30 -4
- package/src/oauth/chatgpt.ts +12 -1
- package/src/oauth/cline.ts +203 -0
- package/src/oauth/command-code.ts +239 -0
- package/src/oauth/cursor.ts +46 -5
- package/src/oauth/generic-account-failover.ts +231 -0
- package/src/oauth/google-antigravity.ts +35 -3
- package/src/oauth/health.ts +20 -12
- package/src/oauth/index.ts +462 -71
- package/src/oauth/key-providers.ts +25 -0
- package/src/oauth/kimi.ts +25 -3
- package/src/oauth/kiro.ts +95 -6
- package/src/oauth/local-token-detect.ts +13 -2
- package/src/oauth/log.ts +3 -1
- package/src/oauth/login-cli.ts +88 -28
- package/src/oauth/nous.ts +798 -0
- package/src/oauth/open-browser-choice.ts +26 -0
- package/src/oauth/store.ts +133 -26
- package/src/oauth/token-guardian.ts +9 -3
- package/src/oauth/types.ts +15 -0
- package/src/pi/models.ts +2 -2
- package/src/providers/alibaba-region-migration.ts +1 -1
- package/src/providers/antigravity-models.ts +521 -31
- package/src/providers/auto-compact-budget.ts +65 -0
- package/src/providers/base-url-choices.ts +10 -0
- package/src/providers/codex-capacity.ts +292 -0
- package/src/providers/command-code-efforts.ts +176 -0
- package/src/providers/context-cap.ts +26 -8
- package/src/providers/cursor-pool.ts +72 -0
- package/src/providers/default-aliases.ts +65 -0
- package/src/providers/derive.ts +281 -6
- package/src/providers/fastwire.ts +507 -0
- package/src/providers/free-directory.ts +10 -7
- package/src/providers/google-vertex-location.ts +14 -0
- package/src/providers/key-failover.ts +71 -3
- package/src/providers/label.ts +35 -2
- package/src/providers/model-discovery-limits.ts +16 -0
- package/src/providers/model-discovery.ts +115 -22
- package/src/providers/model-presets.ts +119 -0
- package/src/providers/model-rename-migration.ts +255 -0
- package/src/providers/model-rename-startup.ts +28 -0
- package/src/providers/new-model-policy.ts +146 -0
- package/src/providers/openai-sidecar.ts +72 -4
- package/src/providers/openai-tier-startup.ts +31 -2
- package/src/providers/openai-tiers.ts +119 -4
- package/src/providers/openai-virtual-models.ts +1 -0
- package/src/providers/opencode-zen-rate-limit.ts +102 -0
- package/src/providers/provider-id-rewrite.ts +30 -0
- package/src/providers/quota.ts +1379 -40
- package/src/providers/registry.ts +1545 -112
- package/src/providers/request-pacing.ts +310 -0
- package/src/providers/service-tier.ts +277 -0
- package/src/providers/slug-codec.ts +94 -6
- package/src/providers/static-model-discovery.ts +86 -0
- package/src/providers/xai-responses-opt-in.ts +15 -0
- package/src/providers/xai-transport.ts +32 -4
- package/src/reasoning-effort.ts +68 -3
- package/src/responses/apply-patch-envelope.ts +63 -0
- package/src/responses/code-mode-helper-compat.ts +50 -0
- package/src/responses/compaction.ts +26 -1
- package/src/responses/custom-tool-compat.ts +384 -0
- package/src/responses/hosted-tool-policy.ts +9 -0
- package/src/responses/namespace-tool-compat.ts +435 -0
- package/src/responses/parser.ts +225 -38
- package/src/responses/provider-continuation.ts +98 -0
- package/src/responses/provider-opaque-metadata.ts +73 -0
- package/src/responses/reasoning-envelope.ts +9 -1
- package/src/responses/reasoning-replay-cache.ts +504 -0
- package/src/responses/schema.ts +12 -2
- package/src/responses/spill-store.ts +75 -10
- package/src/responses/state.ts +659 -31
- package/src/responses/thought-signature-replay.ts +364 -0
- package/src/responses/tool-search-compat.ts +301 -0
- package/src/responses/truncated-stop-reason.ts +60 -0
- package/src/responses/turn-termination.ts +107 -0
- package/src/router.ts +405 -31
- package/src/routing/analytics.ts +379 -0
- package/src/routing/capability.ts +244 -0
- package/src/routing/compatibility/assemble.ts +73 -0
- package/src/routing/compatibility/behavior.ts +278 -0
- package/src/routing/compatibility/catalog.ts +99 -0
- package/src/routing/compatibility/endpoint.ts +52 -0
- package/src/routing/compatibility/lab-evidence-provider.ts +130 -0
- package/src/routing/compatibility/policy.ts +181 -0
- package/src/routing/compatibility/provider-slot.ts +56 -0
- package/src/routing/compatibility/reader.ts +110 -0
- package/src/routing/compatibility/subject.ts +191 -0
- package/src/routing/compatibility/types.ts +64 -0
- package/src/routing/compatibility/version.ts +104 -0
- package/src/routing/cost.ts +77 -0
- package/src/routing/evaluator.ts +495 -0
- package/src/routing/health.ts +412 -0
- package/src/routing/history/cursor.ts +43 -0
- package/src/routing/history/indexer.ts +605 -0
- package/src/routing/history/schema.ts +72 -0
- package/src/routing/profile-namespace.ts +15 -0
- package/src/routing/profile.ts +547 -0
- package/src/routing/quota.ts +155 -0
- package/src/routing/request-evidence.ts +45 -0
- package/src/routing/trace.ts +776 -0
- package/src/server/adapter-resolve.ts +2 -29
- package/src/server/auth-cors.ts +289 -48
- package/src/server/background-lifecycle.ts +182 -0
- package/src/server/chat-completions.ts +154 -72
- package/src/server/chat-native-sse.ts +331 -0
- package/src/server/chat-native.ts +445 -0
- package/src/server/claude-messages.ts +160 -44
- package/src/server/direct-local-http.ts +347 -0
- package/src/server/effort-policy.ts +18 -0
- package/src/server/github-copilot-responses-repair.ts +338 -0
- package/src/server/gui-static.ts +39 -10
- package/src/server/images.ts +94 -12
- package/src/server/index.ts +1021 -190
- package/src/server/lifecycle.ts +336 -14
- package/src/server/live.ts +136 -17
- package/src/server/local-management-read-client.ts +90 -0
- package/src/server/local-provider-reload-client.ts +137 -0
- package/src/server/management/agent-settings-routes.ts +433 -116
- package/src/server/management/api-key-usage.ts +31 -5
- package/src/server/management/body.ts +6 -0
- package/src/server/management/codex-prompt-routes.ts +570 -0
- package/src/server/management/combo-routes.ts +64 -25
- package/src/server/management/config-routes.ts +511 -51
- package/src/server/management/context.ts +89 -2
- package/src/server/management/integration-routes.ts +498 -0
- package/src/server/management/lab-automation-routes.ts +206 -0
- package/src/server/management/lab-routes.ts +563 -0
- package/src/server/management/logs-usage-routes.ts +127 -52
- package/src/server/management/model-routes.ts +461 -133
- package/src/server/management/model-rows.ts +167 -0
- package/src/server/management/native-integration-routes.ts +770 -0
- package/src/server/management/oauth-account-routes.ts +90 -8
- package/src/server/management/provider-capability-config.ts +48 -0
- package/src/server/management/provider-routes.ts +836 -159
- package/src/server/management/request-history-routes.ts +191 -0
- package/src/server/management/route-registry.ts +332 -0
- package/src/server/management/routing-analytics-routes.ts +74 -0
- package/src/server/management/routing-profile-routes.ts +380 -0
- package/src/server/management/shared.ts +27 -11
- package/src/server/management/sidebar-routes.ts +47 -31
- package/src/server/management/storage-log-guard-routes.ts +186 -0
- package/src/server/management/sync-response.ts +69 -0
- package/src/server/management/system-restart.ts +289 -33
- package/src/server/management/system-routes.ts +77 -0
- package/src/server/management/usage-summary-cache.ts +9 -1
- package/src/server/management/vision-sidecar-options.ts +167 -0
- package/src/server/management/web-search-sidecar-options.ts +120 -0
- package/src/server/management-api.ts +126 -23
- package/src/server/management-auth.ts +220 -5
- package/src/server/passive-route-linker.ts +66 -0
- package/src/server/port-reclaim.ts +1 -1
- package/src/server/ports.ts +41 -1
- package/src/server/proxy-liveness.ts +161 -10
- package/src/server/readiness.ts +99 -0
- package/src/server/relay-eager.ts +221 -54
- package/src/server/relay.ts +479 -87
- package/src/server/request-decompress.ts +113 -6
- package/src/server/request-log-conversation.ts +51 -0
- package/src/server/request-log.ts +298 -31
- package/src/server/responses/agent-task-recovery-cache.ts +143 -0
- package/src/server/responses/agent-task-recovery.ts +465 -0
- package/src/server/responses/codex-auth-error.ts +55 -0
- package/src/server/responses/collaboration.ts +239 -36
- package/src/server/responses/combo-stream-preflight.ts +178 -0
- package/src/server/responses/compact.ts +444 -72
- package/src/server/responses/core.ts +3579 -436
- package/src/server/responses/empty-completion-guard.ts +333 -0
- package/src/server/responses/encrypted-payload.ts +62 -39
- package/src/server/responses/fetch-helpers.ts +89 -99
- package/src/server/responses/input-admission.ts +187 -0
- package/src/server/responses/pacing-overload.ts +13 -0
- package/src/server/responses/passthrough-error.ts +33 -9
- package/src/server/responses/policy-fallback.ts +178 -0
- package/src/server/responses/responses-field-backfill.ts +343 -0
- package/src/server/responses/terminal-guard.ts +26 -5
- package/src/server/responses/upstream-error.ts +5 -0
- package/src/server/responses/ws-upstream.ts +381 -0
- package/src/server/responses-custom-tool-repair.ts +363 -0
- package/src/server/responses-item-id-repair.ts +54 -6
- package/src/server/responses-json-events.ts +90 -0
- package/src/server/responses-model-rewrite.ts +29 -0
- package/src/server/responses-reasoning-summary-rewrite.ts +178 -0
- package/src/server/responses-snapshot-repair.ts +621 -0
- package/src/server/responses-terminal-repair.ts +363 -0
- package/src/server/responses-tool-search-repair.ts +267 -0
- package/src/server/responses-undeclared-tool-guard.ts +376 -0
- package/src/server/responses.ts +18 -2
- package/src/server/search.ts +78 -13
- package/src/server/sse-frame-buffer.ts +319 -0
- package/src/server/sse-payload-rewrite.ts +110 -22
- package/src/server/startup-action-control.ts +8 -1
- package/src/server/startup-health-cache.ts +19 -1
- package/src/server/system-env.ts +80 -9
- package/src/server/ws-bridge.ts +53 -40
- package/src/service-manager-probe.ts +892 -0
- package/src/service.ts +1153 -94
- package/src/sidecar/auth.ts +92 -0
- package/src/sidecar/candidates.ts +83 -0
- package/src/storage/cleanup.ts +2 -2
- package/src/storage/policy-job.ts +14 -4
- package/src/storage/policy.ts +88 -23
- package/src/storage/scanner.ts +1 -1
- package/src/storage/worker-lifecycle.ts +14 -14
- package/src/tray/windows-tray.ps1 +83 -9
- package/src/tray/windows.ts +43 -16
- package/src/types/accounts.ts +37 -0
- package/src/types/config.ts +911 -0
- package/src/types/provider.ts +614 -0
- package/src/types/request.ts +397 -0
- package/src/types/tools.ts +236 -0
- package/src/types/wire.ts +80 -0
- package/src/types.ts +107 -1237
- package/src/update/index.ts +37 -23
- package/src/update/job.ts +445 -68
- package/src/update/notify.ts +12 -6
- package/src/update/npm-cache-preflight.d.mts +47 -0
- package/src/update/npm-cache-preflight.mjs +201 -0
- package/src/update/transactional-install.d.mts +22 -0
- package/src/update/transactional-install.mjs +266 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/expected-prices.ts +287 -16
- package/src/usage/log.ts +666 -50
- package/src/usage/summary.ts +388 -17
- package/src/usage/user-cost-overlay-reconciler.ts +313 -0
- package/src/usage/user-cost-overlays.ts +314 -0
- package/src/vision/anthropic-describe.ts +10 -6
- package/src/vision/backends.ts +97 -0
- package/src/vision/describe.ts +27 -16
- package/src/vision/eligibility.ts +250 -0
- package/src/vision/index.ts +238 -24
- package/src/vision/reasoning.ts +55 -0
- package/src/vision/routed-describe.ts +175 -0
- package/src/vision/timeout-bounds.ts +9 -0
- package/src/web-search/anthropic-executor.ts +13 -7
- package/src/web-search/backends.ts +108 -0
- package/src/web-search/exa-executor.ts +119 -0
- package/src/web-search/executor.ts +21 -6
- package/src/web-search/gemini-executor.ts +141 -0
- package/src/web-search/index.ts +150 -15
- package/src/web-search/loop.ts +284 -54
- package/src/web-search/parse.ts +125 -30
- package/src/web-search/sources.ts +60 -0
- package/src/web-search/xai-executor.ts +219 -0
- package/gui/dist/assets/index-DTpMHS4F.js +0 -67
- package/gui/dist/assets/index-ZNVDE3C7.css +0 -1
- package/gui/dist/provider-icons/antigravity.svg +0 -1
- package/gui/dist/provider-icons/claude.svg +0 -1
- package/gui/dist/provider-icons/copilot.svg +0 -1
- package/gui/dist/provider-icons/cursor.svg +0 -2
- package/gui/dist/provider-icons/gemini.svg +0 -1
- package/gui/dist/provider-icons/grok-color.svg +0 -1
- package/gui/dist/provider-icons/kiro.svg +0 -14
- package/src/cli/internal-dispatch.ts +0 -20
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import { namespacedToolName, normalizeDeclaredToolName } from "../types";
|
|
2
|
+
import { sseDataPayload, type SseBlockRewrite } from "./sse-payload-rewrite";
|
|
3
|
+
|
|
4
|
+
/** Item types the client executes through a request-declared wire name. */
|
|
5
|
+
const CLIENT_EXECUTED_CALL_TYPES = new Set(["function_call", "custom_tool_call"]);
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Hosted declarations whose response items the PROVIDER executes, keyed by the request
|
|
9
|
+
* declaration type. These need no client answer, so their names are deliberately absent from
|
|
10
|
+
* the request catalog and must not be read as an undeclared client tool.
|
|
11
|
+
*
|
|
12
|
+
* xAI surfaces hosted `x_search` as `custom_tool_call`. Probed 2026-08-23 against the OAuth CLI
|
|
13
|
+
* destination: its hosted calls use an `xs_call-` call-id prefix. Observed call names were
|
|
14
|
+
* `x_keyword_search`, `x_semantic_search`, and `x_user_search` — three literals for one tool,
|
|
15
|
+
* which is why authorization keys on the declaration, item type, and call-id prefix, never on
|
|
16
|
+
* the name.
|
|
17
|
+
*/
|
|
18
|
+
export type ProviderExecutedCallType = Readonly<{
|
|
19
|
+
itemType: string;
|
|
20
|
+
callIdPrefix: string;
|
|
21
|
+
}>;
|
|
22
|
+
|
|
23
|
+
type ProviderExecutedCallTypes = ReadonlySet<ProviderExecutedCallType>;
|
|
24
|
+
|
|
25
|
+
export const PROVIDER_EXECUTED_DECLARATION_CALL_TYPES = new Map<string, ProviderExecutedCallType>([
|
|
26
|
+
["x_search", { itemType: "custom_tool_call", callIdPrefix: "xs_call-" }],
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
/** Nameless declaration kinds whose response items still require client execution. */
|
|
30
|
+
const NAMELESS_CLIENT_DECLARATION_CALL_TYPES = new Map([
|
|
31
|
+
["local_shell", "local_shell_call"],
|
|
32
|
+
["tool_search", "tool_search_call"],
|
|
33
|
+
["computer_use_preview", "computer_call"],
|
|
34
|
+
["computer_use", "computer_call"],
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
const NAMELESS_CLIENT_CALL_DISPLAY_NAMES = new Map([
|
|
38
|
+
["local_shell_call", "local_shell"],
|
|
39
|
+
["tool_search_call", "tool_search"],
|
|
40
|
+
["computer_call", "computer_use"],
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
const EMPTY_DECLARED_NAMELESS_CLIENT_CALL_TYPES: ReadonlySet<string> = new Set();
|
|
44
|
+
const EMPTY_PROVIDER_EXECUTED_CALL_TYPES: ReadonlySet<ProviderExecutedCallType> = new Set();
|
|
45
|
+
|
|
46
|
+
/** Supported hosted/private declarations that carry no client-executable wire name. */
|
|
47
|
+
const NAMELESS_TOOL_SPEC_TYPES = new Set([
|
|
48
|
+
"web_search",
|
|
49
|
+
"web_search_preview",
|
|
50
|
+
"file_search",
|
|
51
|
+
"computer_use_preview",
|
|
52
|
+
"computer_use",
|
|
53
|
+
"code_interpreter",
|
|
54
|
+
"image_generation",
|
|
55
|
+
"image_gen",
|
|
56
|
+
"mcp",
|
|
57
|
+
"tool_search",
|
|
58
|
+
"local_shell",
|
|
59
|
+
"x_search",
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
/** An upstream-supplied name reaches the error message; keep it bounded. */
|
|
63
|
+
const MAX_REPORTED_NAME_CHARS = 100;
|
|
64
|
+
|
|
65
|
+
export const UNDECLARED_TOOL_CALL_ERROR_CODE = "undeclared_tool_call";
|
|
66
|
+
|
|
67
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
68
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function addWireToolName(names: Set<string>, tool: unknown, namespace?: string): void {
|
|
72
|
+
if (!isPlainObject(tool)) return;
|
|
73
|
+
const nestedFunction = tool.type === "function" && isPlainObject(tool.function)
|
|
74
|
+
? tool.function
|
|
75
|
+
: undefined;
|
|
76
|
+
const name = typeof tool.name === "string" && tool.name.length > 0
|
|
77
|
+
? tool.name
|
|
78
|
+
: typeof nestedFunction?.name === "string" && nestedFunction.name.length > 0
|
|
79
|
+
? nestedFunction.name
|
|
80
|
+
: undefined;
|
|
81
|
+
if (!name) return;
|
|
82
|
+
names.add(name);
|
|
83
|
+
// Codex routes MCP calls by an explicit `namespace` field, so the same tool is reachable
|
|
84
|
+
// as a bare inner name or as the flattened form; accept both rather than guess which
|
|
85
|
+
// coordinate system this provider echoes back.
|
|
86
|
+
if (namespace) names.add(namespacedToolName(namespace, name));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Catalog view owned by the current Responses turn.
|
|
91
|
+
*
|
|
92
|
+
* `previous_response_id` expansion prepends stored input items, including historical
|
|
93
|
+
* `additional_tools` declarations. Those items remain conversation history but cannot grant
|
|
94
|
+
* execution authority to this turn. Top-level `tools` always belongs to the current request;
|
|
95
|
+
* only input catalogs at or after the replay boundary are current.
|
|
96
|
+
*/
|
|
97
|
+
export function currentTurnWireToolCatalogBody(
|
|
98
|
+
body: unknown,
|
|
99
|
+
replayPrefixLength: number | undefined,
|
|
100
|
+
): unknown {
|
|
101
|
+
if (!isPlainObject(body) || !Array.isArray(body.input)) return body;
|
|
102
|
+
if (typeof replayPrefixLength !== "number" || !Number.isFinite(replayPrefixLength)) return body;
|
|
103
|
+
const start = Math.min(body.input.length, Math.max(0, Math.trunc(replayPrefixLength)));
|
|
104
|
+
if (start === 0) return body;
|
|
105
|
+
return { ...body, input: body.input.slice(start) };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function addWireToolSpecs(names: Set<string>, specs: unknown): void {
|
|
109
|
+
if (!Array.isArray(specs)) return;
|
|
110
|
+
for (const spec of specs) {
|
|
111
|
+
if (!isPlainObject(spec)) continue;
|
|
112
|
+
if (spec.type === "namespace" && Array.isArray(spec.tools)) {
|
|
113
|
+
const namespace = typeof spec.name === "string" ? spec.name : undefined;
|
|
114
|
+
for (const inner of spec.tools) addWireToolName(names, inner, namespace);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
addWireToolName(names, spec);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Tool names the OUTBOUND Responses body actually declared.
|
|
123
|
+
*
|
|
124
|
+
* This reads the body that goes upstream rather than the parsed internal tool list: the
|
|
125
|
+
* passthrough forwards wire shapes (namespaced MCP groups, `additional_tools` items carried
|
|
126
|
+
* inside `input`, routed custom-tool rewrites) that the internal list flattens or renames, and
|
|
127
|
+
* only the wire names can be compared against what the provider echoes back.
|
|
128
|
+
*/
|
|
129
|
+
export function collectDeclaredWireToolNames(body: unknown): Set<string> {
|
|
130
|
+
const names = new Set<string>();
|
|
131
|
+
if (!isPlainObject(body)) return names;
|
|
132
|
+
addWireToolSpecs(names, body.tools);
|
|
133
|
+
if (Array.isArray(body.input)) {
|
|
134
|
+
for (const item of body.input) {
|
|
135
|
+
if (
|
|
136
|
+
isPlainObject(item)
|
|
137
|
+
&& (item.type === "additional_tools" || item.type === "tool_search_output")
|
|
138
|
+
) addWireToolSpecs(names, item.tools);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return names;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function addNamelessClientCallTypes(callTypes: Set<string>, specs: unknown): void {
|
|
145
|
+
if (!Array.isArray(specs)) return;
|
|
146
|
+
for (const spec of specs) {
|
|
147
|
+
if (!isPlainObject(spec) || typeof spec.type !== "string") continue;
|
|
148
|
+
const callType = NAMELESS_CLIENT_DECLARATION_CALL_TYPES.get(spec.type);
|
|
149
|
+
if (callType) callTypes.add(callType);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function addProviderExecutedCallTypes(
|
|
154
|
+
callTypes: Set<ProviderExecutedCallType>,
|
|
155
|
+
specs: unknown,
|
|
156
|
+
): void {
|
|
157
|
+
if (!Array.isArray(specs)) return;
|
|
158
|
+
for (const spec of specs) {
|
|
159
|
+
if (!isPlainObject(spec) || typeof spec.type !== "string") continue;
|
|
160
|
+
const callType = PROVIDER_EXECUTED_DECLARATION_CALL_TYPES.get(spec.type);
|
|
161
|
+
if (callType) callTypes.add(callType);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Item types this turn's hosted declarations authorize the PROVIDER to emit unnamed.
|
|
167
|
+
*
|
|
168
|
+
* Caller must gate this on the destination actually being that provider; a declaration alone
|
|
169
|
+
* is not authority, or any upstream could claim a hosted shape it never serves.
|
|
170
|
+
*/
|
|
171
|
+
export function collectProviderExecutedCallTypes(body: unknown): Set<ProviderExecutedCallType> {
|
|
172
|
+
const callTypes = new Set<ProviderExecutedCallType>();
|
|
173
|
+
if (!isPlainObject(body)) return callTypes;
|
|
174
|
+
addProviderExecutedCallTypes(callTypes, body.tools);
|
|
175
|
+
if (Array.isArray(body.input)) {
|
|
176
|
+
for (const item of body.input) {
|
|
177
|
+
if (
|
|
178
|
+
isPlainObject(item)
|
|
179
|
+
&& (item.type === "additional_tools" || item.type === "tool_search_output")
|
|
180
|
+
) addProviderExecutedCallTypes(callTypes, item.tools);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return callTypes;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function isAuthorizedProviderExecutedCall(
|
|
187
|
+
item: Record<string, unknown>,
|
|
188
|
+
callTypes: ProviderExecutedCallTypes,
|
|
189
|
+
): boolean {
|
|
190
|
+
if (typeof item.call_id !== "string") return false;
|
|
191
|
+
for (const callType of callTypes) {
|
|
192
|
+
if (
|
|
193
|
+
item.type === callType.itemType
|
|
194
|
+
&& item.call_id.startsWith(callType.callIdPrefix)
|
|
195
|
+
) return true;
|
|
196
|
+
}
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Nameless client-call item types authorized by supported request tool declarations. */
|
|
201
|
+
export function collectDeclaredNamelessClientCallTypes(body: unknown): Set<string> {
|
|
202
|
+
const callTypes = new Set<string>();
|
|
203
|
+
if (!isPlainObject(body)) return callTypes;
|
|
204
|
+
addNamelessClientCallTypes(callTypes, body.tools);
|
|
205
|
+
if (Array.isArray(body.input)) {
|
|
206
|
+
for (const item of body.input) {
|
|
207
|
+
if (
|
|
208
|
+
isPlainObject(item)
|
|
209
|
+
&& (item.type === "additional_tools" || item.type === "tool_search_output")
|
|
210
|
+
) {
|
|
211
|
+
addNamelessClientCallTypes(callTypes, item.tools);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return callTypes;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function isReadableWireToolSpec(spec: unknown): boolean {
|
|
219
|
+
if (!isPlainObject(spec) || typeof spec.type !== "string" || spec.type.length === 0) return false;
|
|
220
|
+
if (spec.type === "function") {
|
|
221
|
+
return (typeof spec.name === "string" && spec.name.length > 0)
|
|
222
|
+
|| (isPlainObject(spec.function)
|
|
223
|
+
&& typeof spec.function.name === "string"
|
|
224
|
+
&& spec.function.name.length > 0);
|
|
225
|
+
}
|
|
226
|
+
if (spec.type === "custom") return typeof spec.name === "string" && spec.name.length > 0;
|
|
227
|
+
if (spec.type === "namespace") {
|
|
228
|
+
return typeof spec.name === "string"
|
|
229
|
+
&& spec.name.length > 0
|
|
230
|
+
&& Array.isArray(spec.tools)
|
|
231
|
+
&& (spec.tools.length === 0 || spec.tools.some(inner =>
|
|
232
|
+
isPlainObject(inner)
|
|
233
|
+
&& (inner.type === "function" || inner.type === "custom")
|
|
234
|
+
&& typeof inner.name === "string"
|
|
235
|
+
&& inner.name.length > 0
|
|
236
|
+
));
|
|
237
|
+
}
|
|
238
|
+
if (NAMELESS_TOOL_SPEC_TYPES.has(spec.type)) return true;
|
|
239
|
+
return typeof spec.name === "string" && spec.name.length > 0;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function isReadableWireToolCatalog(value: unknown): boolean {
|
|
243
|
+
return Array.isArray(value)
|
|
244
|
+
&& (value.length === 0 || value.some(isReadableWireToolSpec));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** Whether a request contains a supported catalog, including an explicit empty deny-all array. */
|
|
248
|
+
export function hasExplicitWireToolCatalog(body: unknown): boolean {
|
|
249
|
+
if (!isPlainObject(body)) return false;
|
|
250
|
+
if (isReadableWireToolCatalog(body.tools)) return true;
|
|
251
|
+
if (!Array.isArray(body.input)) return false;
|
|
252
|
+
return body.input.some(item =>
|
|
253
|
+
isPlainObject(item)
|
|
254
|
+
&& item.type === "additional_tools"
|
|
255
|
+
&& isReadableWireToolCatalog(item.tools)
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function undeclaredNameInItem(
|
|
260
|
+
item: unknown,
|
|
261
|
+
declared: ReadonlySet<string>,
|
|
262
|
+
declaredNamelessClientCallTypes: ReadonlySet<string>,
|
|
263
|
+
providerExecutedCallTypes: ProviderExecutedCallTypes = EMPTY_PROVIDER_EXECUTED_CALL_TYPES,
|
|
264
|
+
): string | undefined {
|
|
265
|
+
if (!isPlainObject(item)) return undefined;
|
|
266
|
+
if (typeof item.type !== "string") return undefined;
|
|
267
|
+
// The provider executes this exact measured shape itself, so there is no client name to
|
|
268
|
+
// authorize. The caller supplies these signatures only for the matching destination and
|
|
269
|
+
// declarations; the item must additionally carry the hosted call-id prefix.
|
|
270
|
+
if (isAuthorizedProviderExecutedCall(item, providerExecutedCallTypes)) return undefined;
|
|
271
|
+
const namelessDisplayName = NAMELESS_CLIENT_CALL_DISPLAY_NAMES.get(item.type);
|
|
272
|
+
if (namelessDisplayName !== undefined) {
|
|
273
|
+
// Only Codex's explicit `execution: "client"` form delegates tool search to the client.
|
|
274
|
+
if (item.type === "tool_search_call" && item.execution !== "client") return undefined;
|
|
275
|
+
return declaredNamelessClientCallTypes.has(item.type) ? undefined : namelessDisplayName;
|
|
276
|
+
}
|
|
277
|
+
if (!CLIENT_EXECUTED_CALL_TYPES.has(item.type)) return undefined;
|
|
278
|
+
const name = item.name;
|
|
279
|
+
if (typeof name !== "string" || name.length === 0) return undefined;
|
|
280
|
+
if (typeof item.namespace === "string") {
|
|
281
|
+
// Namespaced calls are matched by their full wire name only — never legacy-normalize
|
|
282
|
+
// them, or an undeclared namespaced `exec_command` could slip through as bare `exec`.
|
|
283
|
+
if (declared.has(namespacedToolName(item.namespace, name))) return undefined;
|
|
284
|
+
return name;
|
|
285
|
+
}
|
|
286
|
+
const effectiveName = normalizeDeclaredToolName(name, declared);
|
|
287
|
+
if (declared.has(effectiveName)) return undefined;
|
|
288
|
+
return name;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/** First undeclared client tool named by a Responses SSE payload, or undefined. */
|
|
292
|
+
export function undeclaredToolCallName(
|
|
293
|
+
payload: unknown,
|
|
294
|
+
declared: ReadonlySet<string>,
|
|
295
|
+
declaredNamelessClientCallTypes: ReadonlySet<string> = EMPTY_DECLARED_NAMELESS_CLIENT_CALL_TYPES,
|
|
296
|
+
providerExecutedCallTypes: ProviderExecutedCallTypes = EMPTY_PROVIDER_EXECUTED_CALL_TYPES,
|
|
297
|
+
): string | undefined {
|
|
298
|
+
if (!isPlainObject(payload)) return undefined;
|
|
299
|
+
if (payload.type === "response.output_item.added" || payload.type === "response.output_item.done") {
|
|
300
|
+
return undeclaredNameInItem(payload.item, declared, declaredNamelessClientCallTypes, providerExecutedCallTypes);
|
|
301
|
+
}
|
|
302
|
+
// Sparse gateways skip incremental items and only ever ship the terminal snapshot.
|
|
303
|
+
if (payload.type === "response.completed" || payload.type === "response.incomplete") {
|
|
304
|
+
return undeclaredToolCallNameInResponse(payload.response, declared, declaredNamelessClientCallTypes, providerExecutedCallTypes);
|
|
305
|
+
}
|
|
306
|
+
return undefined;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** First undeclared client tool in a Responses object's `output` array, or undefined. */
|
|
310
|
+
export function undeclaredToolCallNameInResponse(
|
|
311
|
+
response: unknown,
|
|
312
|
+
declared: ReadonlySet<string>,
|
|
313
|
+
declaredNamelessClientCallTypes: ReadonlySet<string> = EMPTY_DECLARED_NAMELESS_CLIENT_CALL_TYPES,
|
|
314
|
+
providerExecutedCallTypes: ProviderExecutedCallTypes = EMPTY_PROVIDER_EXECUTED_CALL_TYPES,
|
|
315
|
+
): string | undefined {
|
|
316
|
+
if (!isPlainObject(response) || !Array.isArray(response.output)) return undefined;
|
|
317
|
+
for (const item of response.output) {
|
|
318
|
+
const name = undeclaredNameInItem(item, declared, declaredNamelessClientCallTypes, providerExecutedCallTypes);
|
|
319
|
+
if (name !== undefined) return name;
|
|
320
|
+
}
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export function undeclaredToolCallMessage(name: string): string {
|
|
325
|
+
const reported = name.slice(0, MAX_REPORTED_NAME_CHARS);
|
|
326
|
+
return `routed provider emitted undeclared client tool "${reported}"; only request-declared tools may be called`;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function failedBlocks(name: string, newline: string): readonly string[] {
|
|
330
|
+
const failure = {
|
|
331
|
+
type: "upstream_error",
|
|
332
|
+
code: UNDECLARED_TOOL_CALL_ERROR_CODE,
|
|
333
|
+
message: undeclaredToolCallMessage(name),
|
|
334
|
+
};
|
|
335
|
+
const payload = JSON.stringify({
|
|
336
|
+
type: "response.failed",
|
|
337
|
+
response: { status: "failed", error: failure, last_error: failure },
|
|
338
|
+
});
|
|
339
|
+
return [`event: response.failed${newline}data: ${payload}`, "data: [DONE]"];
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Fail closed when a routed provider calls a tool the request never declared (#1700).
|
|
344
|
+
*
|
|
345
|
+
* The bridged paths already refuse such a call (`declaredToolNames` in src/bridge.ts), but the
|
|
346
|
+
* native Responses passthrough relayed it verbatim: Codex received a `function_call` for a tool
|
|
347
|
+
* it has no top-level handler for — `apply_patch`, which under code mode exists only as a nested
|
|
348
|
+
* `tools.apply_patch(...)` helper inside `exec` — and the turn surfaced as a bare `aborted` with
|
|
349
|
+
* no output and no explanation. Replacing the offending event with an explicit `response.failed`
|
|
350
|
+
* turns that silent dead end into a compatibility error naming the tool.
|
|
351
|
+
*
|
|
352
|
+
* Everything after the trip is dropped so a later `response.completed` cannot contradict the
|
|
353
|
+
* terminal already sent. Non-JSON and non-item blocks pass through untouched.
|
|
354
|
+
*/
|
|
355
|
+
export function createUndeclaredToolCallGuardBlockRewrite(
|
|
356
|
+
declared: ReadonlySet<string>,
|
|
357
|
+
declaredNamelessClientCallTypes: ReadonlySet<string> = EMPTY_DECLARED_NAMELESS_CLIENT_CALL_TYPES,
|
|
358
|
+
providerExecutedCallTypes: ProviderExecutedCallTypes = EMPTY_PROVIDER_EXECUTED_CALL_TYPES,
|
|
359
|
+
): SseBlockRewrite {
|
|
360
|
+
let tripped = false;
|
|
361
|
+
return (block: string) => {
|
|
362
|
+
if (tripped) return [];
|
|
363
|
+
const payload = sseDataPayload(block);
|
|
364
|
+
if (payload === null || payload === "[DONE]") return [block];
|
|
365
|
+
let parsed: unknown;
|
|
366
|
+
try {
|
|
367
|
+
parsed = JSON.parse(payload);
|
|
368
|
+
} catch {
|
|
369
|
+
return [block];
|
|
370
|
+
}
|
|
371
|
+
const name = undeclaredToolCallName(parsed, declared, declaredNamelessClientCallTypes, providerExecutedCallTypes);
|
|
372
|
+
if (name === undefined) return [block];
|
|
373
|
+
tripped = true;
|
|
374
|
+
return failedBlocks(name, block.includes("\r\n") ? "\r\n" : "\n");
|
|
375
|
+
};
|
|
376
|
+
}
|
package/src/server/responses.ts
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
// AUTO-SPLIT facade: original responses.ts body moved into ./responses/* modules.
|
|
2
2
|
// Public surface preserved exactly; importers keep using "src/server/responses".
|
|
3
|
+
import { handleResponsesCompact as handleResponsesCompactImpl } from "./responses/compact";
|
|
4
|
+
import { requestPacingOverloadResponse } from "./responses/pacing-overload";
|
|
5
|
+
|
|
3
6
|
export { buildToolBridgeMaps, isV1CollabSurface, collabSurface, multiAgentGuidanceText, V2_GUIDANCE_CHAR_BUDGET, injectDeveloperMessage } from "./responses/collaboration";
|
|
4
7
|
export type { MultiAgentGuidanceOptions, MultiAgentGuidanceDeps } from "./responses/collaboration";
|
|
5
8
|
export { hasUnreadableEncryptedAgentTask, sanitizeEncryptedContentInPlace } from "./responses/encrypted-payload";
|
|
6
|
-
export { COMPACT_RESPONSE_MAX_BYTES, bufferCompactResponse
|
|
9
|
+
export { COMPACT_RESPONSE_MAX_BYTES, bufferCompactResponse } from "./responses/compact";
|
|
7
10
|
export { disableResponsesRequestTimeout, safeHostLabel, fetchWithHeaderTimeout } from "./responses/fetch-helpers";
|
|
8
|
-
export { sidecarOutcomeRecorder, isShadowSourceModel, codexLogAccountId, usesCodexForwardPoolAuth, codexForwardTerminalOutcomeRecorder, decodeRequestErrorResponse, buildComboChildHeaders,
|
|
11
|
+
export { sidecarOutcomeRecorder, isShadowSourceModel, codexLogAccountId, usesCodexForwardPoolAuth, codexForwardTerminalOutcomeRecorder, decodeRequestErrorResponse, buildComboChildHeaders, linkAbortSignal } from "./responses/core";
|
|
12
|
+
export { handleResponses, handleResponsesWithPolicyFallback, rankPolicyFallbackCandidates } from "./responses/policy-fallback";
|
|
9
13
|
export { adapterNeedsForcedContinuation } from "./responses/core";
|
|
14
|
+
|
|
15
|
+
export async function handleResponsesCompact(
|
|
16
|
+
...args: Parameters<typeof handleResponsesCompactImpl>
|
|
17
|
+
): Promise<Response> {
|
|
18
|
+
try {
|
|
19
|
+
return await handleResponsesCompactImpl(...args);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
const overload = requestPacingOverloadResponse(error);
|
|
22
|
+
if (overload) return overload;
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
}
|
package/src/server/search.ts
CHANGED
|
@@ -11,20 +11,31 @@
|
|
|
11
11
|
import { formatErrorResponse } from "../bridge";
|
|
12
12
|
import {
|
|
13
13
|
CodexAccountCooldownError,
|
|
14
|
+
codexMainProfileDrainingResponse,
|
|
14
15
|
cooldownErrorResponse,
|
|
15
16
|
CodexAuthContextError,
|
|
17
|
+
CodexMainProfileDrainingError,
|
|
16
18
|
CodexPoolAuthenticationError,
|
|
17
19
|
CodexThreadAffinityExpiredError,
|
|
18
20
|
} from "../codex/auth-context";
|
|
21
|
+
import { codexAccountNamespaceForModel } from "../codex/account-namespace-match";
|
|
19
22
|
import { formatCodexProviderForLog } from "../codex/routing";
|
|
20
23
|
import { signalWithTimeout } from "../lib/abort";
|
|
24
|
+
import { readBoundedResponseBytes } from "../lib/bounded-body";
|
|
21
25
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
22
26
|
import type { OcxConfig } from "../types";
|
|
23
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
listOpenAiForwardSidecarCandidates,
|
|
29
|
+
resolveFirstUsableOpenAiSidecar,
|
|
30
|
+
type ExactOpenAiSidecarAccount,
|
|
31
|
+
} from "../providers/openai-sidecar";
|
|
32
|
+
import { routeModel } from "../router";
|
|
24
33
|
import { readJsonRequestBody } from "./request-decompress";
|
|
25
34
|
import { ForwardAdmissionCredentialError, validateForwardAdmissionCredential } from "./auth-cors";
|
|
26
35
|
import type { RequestLogContext } from "./request-log";
|
|
27
36
|
import { codexLogAccountId, decodeRequestErrorResponse } from "./responses";
|
|
37
|
+
import type { AdmissionLease } from "../lib/admission";
|
|
38
|
+
import { codexAccountSelectionForTurn } from "./lifecycle";
|
|
28
39
|
|
|
29
40
|
/**
|
|
30
41
|
* Default TOTAL deadline for one search relay. alpha/search is non-streaming JSON — response
|
|
@@ -34,12 +45,13 @@ import { codexLogAccountId, decodeRequestErrorResponse } from "./responses";
|
|
|
34
45
|
* long-running search).
|
|
35
46
|
*/
|
|
36
47
|
const SEARCH_UPSTREAM_TIMEOUT_MS = 200_000;
|
|
37
|
-
const SEARCH_RESPONSE_MAX_BYTES = 16 * 1024 * 1024;
|
|
48
|
+
export const SEARCH_RESPONSE_MAX_BYTES = 16 * 1024 * 1024;
|
|
38
49
|
|
|
39
50
|
export async function handleSearch(
|
|
40
51
|
req: Request,
|
|
41
52
|
config: OcxConfig,
|
|
42
53
|
logCtx: RequestLogContext,
|
|
54
|
+
turnAdmissionLease?: AdmissionLease,
|
|
43
55
|
): Promise<Response> {
|
|
44
56
|
try { validateForwardAdmissionCredential(req.headers, config); }
|
|
45
57
|
catch (err) {
|
|
@@ -55,6 +67,32 @@ export async function handleSearch(
|
|
|
55
67
|
const model = (body as { model?: unknown } | null)?.model;
|
|
56
68
|
if (typeof model === "string" && model) logCtx.model = model;
|
|
57
69
|
|
|
70
|
+
let exactAccount: ExactOpenAiSidecarAccount | undefined;
|
|
71
|
+
let relayBody = body;
|
|
72
|
+
const accountNamespace = typeof model === "string"
|
|
73
|
+
? codexAccountNamespaceForModel(config.codexAccountNamespaces, model)
|
|
74
|
+
: undefined;
|
|
75
|
+
if (accountNamespace && typeof model === "string") {
|
|
76
|
+
try {
|
|
77
|
+
const route = routeModel(config, model);
|
|
78
|
+
if (!route.codexAccountId || route.codexAccountNamespace !== accountNamespace) {
|
|
79
|
+
return formatErrorResponse(400, "invalid_request_error", "Invalid Codex account-qualified search model");
|
|
80
|
+
}
|
|
81
|
+
exactAccount = { accountId: route.codexAccountId, modelId: route.modelId };
|
|
82
|
+
logCtx.provider = `${route.providerName}-${accountNamespace}`;
|
|
83
|
+
logCtx.routeDecision = route.routeDecision;
|
|
84
|
+
// The ChatGPT search endpoint only understands the native model slug. The
|
|
85
|
+
// account namespace is proxy routing syntax and must not cross the wire.
|
|
86
|
+
relayBody = { ...(body as Record<string, unknown>), model: route.modelId };
|
|
87
|
+
} catch (err) {
|
|
88
|
+
return formatErrorResponse(
|
|
89
|
+
400,
|
|
90
|
+
"invalid_request_error",
|
|
91
|
+
err instanceof Error ? err.message : "Invalid Codex account-qualified search model",
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
58
96
|
const candidates = listOpenAiForwardSidecarCandidates(config);
|
|
59
97
|
if (candidates.length === 0) {
|
|
60
98
|
return formatErrorResponse(
|
|
@@ -67,7 +105,10 @@ export async function handleSearch(
|
|
|
67
105
|
|
|
68
106
|
let upstream: Awaited<ReturnType<typeof resolveFirstUsableOpenAiSidecar>>;
|
|
69
107
|
try {
|
|
70
|
-
upstream = await resolveFirstUsableOpenAiSidecar(candidates, req.headers, config
|
|
108
|
+
upstream = await resolveFirstUsableOpenAiSidecar(candidates, req.headers, config, {
|
|
109
|
+
exactAccount,
|
|
110
|
+
beginCodexAccountSelection: codexAccountSelectionForTurn(turnAdmissionLease),
|
|
111
|
+
});
|
|
71
112
|
if (!upstream) {
|
|
72
113
|
return formatErrorResponse(
|
|
73
114
|
401,
|
|
@@ -75,16 +116,21 @@ export async function handleSearch(
|
|
|
75
116
|
"web search relay needs ChatGPT auth (Authorization header)",
|
|
76
117
|
);
|
|
77
118
|
}
|
|
78
|
-
logCtx.provider =
|
|
119
|
+
logCtx.provider = accountNamespace
|
|
120
|
+
? `${upstream.providerName}-${accountNamespace}`
|
|
121
|
+
: formatCodexProviderForLog(upstream.providerName, codexLogAccountId(upstream.authContext), config);
|
|
79
122
|
} catch (err) {
|
|
80
123
|
if (err instanceof CodexAccountCooldownError) {
|
|
81
|
-
return cooldownErrorResponse(err);
|
|
124
|
+
return cooldownErrorResponse(err, Date.now(), accountNamespace);
|
|
82
125
|
}
|
|
126
|
+
if (err instanceof CodexMainProfileDrainingError) return codexMainProfileDrainingResponse();
|
|
83
127
|
if (err instanceof CodexThreadAffinityExpiredError) {
|
|
84
128
|
return formatErrorResponse(409, "invalid_request_error", "Codex thread account affinity expired; start a new session");
|
|
85
129
|
}
|
|
86
130
|
if (err instanceof CodexAuthContextError) {
|
|
87
|
-
const safeAccountLabel =
|
|
131
|
+
const safeAccountLabel = accountNamespace
|
|
132
|
+
? `openai-${accountNamespace}`
|
|
133
|
+
: formatCodexProviderForLog("openai", err.accountId, config);
|
|
88
134
|
console.error(`[search] Pool account ${safeAccountLabel} token failed; reauthentication required`);
|
|
89
135
|
return formatErrorResponse(401, "authentication_error", "Selected Codex account needs reauthentication");
|
|
90
136
|
}
|
|
@@ -99,27 +145,40 @@ export async function handleSearch(
|
|
|
99
145
|
const timeoutMs = config.search?.timeoutMs ?? SEARCH_UPSTREAM_TIMEOUT_MS;
|
|
100
146
|
const linkedSignal = signalWithTimeout(timeoutMs, req.signal);
|
|
101
147
|
const sidecarExit = sidecarEnter("search");
|
|
148
|
+
let upstreamResponse: Response | undefined;
|
|
102
149
|
try {
|
|
103
|
-
|
|
150
|
+
upstreamResponse = await fetch(url, {
|
|
104
151
|
method: "POST",
|
|
105
152
|
headers,
|
|
106
|
-
body: JSON.stringify(
|
|
153
|
+
body: JSON.stringify(relayBody),
|
|
154
|
+
signal: linkedSignal.signal,
|
|
155
|
+
// Credential-bearing: do not follow a cross-origin 3xx. Bun strips `Authorization`
|
|
156
|
+
// across origins but forwards nonstandard headers such as `chatgpt-account-id`,
|
|
157
|
+
// `session_id`, and `x-codex-turn-metadata` to the redirect target.
|
|
158
|
+
redirect: "manual",
|
|
159
|
+
});
|
|
160
|
+
const observed = await readBoundedResponseBytes(upstreamResponse, {
|
|
161
|
+
maxBytes: SEARCH_RESPONSE_MAX_BYTES,
|
|
107
162
|
signal: linkedSignal.signal,
|
|
108
163
|
});
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return formatErrorResponse(
|
|
164
|
+
if (observed.oversized) {
|
|
165
|
+
upstream.recordOutcome?.(upstreamResponse.status);
|
|
166
|
+
return formatErrorResponse(
|
|
167
|
+
502,
|
|
168
|
+
"upstream_error",
|
|
169
|
+
`search response too large (exceeded ${SEARCH_RESPONSE_MAX_BYTES} bytes)`,
|
|
170
|
+
);
|
|
112
171
|
}
|
|
113
172
|
upstream.recordOutcome?.(upstreamResponse.status);
|
|
114
173
|
const relayHeaders: Record<string, string> = {};
|
|
115
174
|
const contentType = upstreamResponse.headers.get("content-type");
|
|
116
175
|
if (contentType) relayHeaders["content-type"] = contentType;
|
|
117
|
-
return new Response(
|
|
176
|
+
return new Response(observed.bytes, { status: upstreamResponse.status, headers: relayHeaders });
|
|
118
177
|
} catch (err) {
|
|
119
178
|
if (req.signal.aborted) {
|
|
120
179
|
return formatErrorResponse(499, "client_closed_request", "search request canceled by client");
|
|
121
180
|
}
|
|
122
|
-
if (err instanceof Error && err.name === "TimeoutError") {
|
|
181
|
+
if (linkedSignal.signal.aborted || (err instanceof Error && err.name === "TimeoutError")) {
|
|
123
182
|
upstream.recordOutcome?.("timeout");
|
|
124
183
|
return formatErrorResponse(504, "upstream_error", "search upstream timed out");
|
|
125
184
|
}
|
|
@@ -132,5 +191,11 @@ export async function handleSearch(
|
|
|
132
191
|
} finally {
|
|
133
192
|
sidecarExit();
|
|
134
193
|
linkedSignal.cleanup();
|
|
194
|
+
// A response that aborted before the reader attached still owns its upstream socket.
|
|
195
|
+
// Consumed/cancelled bodies are already closed; locked bodies remain owned by the reader.
|
|
196
|
+
const pendingBody = upstreamResponse?.body;
|
|
197
|
+
if (pendingBody && !pendingBody.locked) {
|
|
198
|
+
try { void pendingBody.cancel().catch(() => undefined); } catch { /* already closed */ }
|
|
199
|
+
}
|
|
135
200
|
}
|
|
136
201
|
}
|