@bitkyc08/opencodex 2.86.0 → 2.88.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/gui/dist/assets/App-CHC89EXQ.js +58 -0
- package/gui/dist/assets/App-wT3mXqFz.css +1 -0
- package/gui/dist/assets/{Tray-DyR9yBee.js → Tray-B5bC7AWL.js} +1 -1
- package/gui/dist/assets/index-B5bsvxor.js +94 -0
- package/gui/dist/assets/index-DPeB9HpV.css +1 -0
- package/gui/dist/assets/quota-summary-D8y2wTsB.js +1 -0
- package/gui/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/adapters/anthropic/beta-allowlist.ts +9 -8
- package/src/adapters/anthropic/beta-body-pairs.ts +93 -0
- package/src/adapters/anthropic/passthrough.ts +7 -23
- package/src/adapters/anthropic-progress.ts +84 -0
- package/src/adapters/anthropic-rejection-memo.ts +71 -0
- package/src/adapters/anthropic-replay.ts +135 -0
- package/src/adapters/anthropic-tool-catalog.ts +11 -0
- package/src/adapters/anthropic.ts +151 -33
- package/src/adapters/base.ts +2 -0
- package/src/adapters/claude-cli/adapter.ts +111 -23
- package/src/adapters/claude-cli/profiles.ts +2 -1
- package/src/adapters/claude-cli/stable-replay.ts +108 -0
- package/src/adapters/claude-cli/usage-admission.ts +230 -0
- package/src/adapters/coding-agent/protocol.ts +1 -1
- package/src/adapters/coding-agent/turn.ts +18 -2
- package/src/adapters/dsh-account.ts +97 -0
- package/src/adapters/google-progress-history.ts +53 -0
- package/src/adapters/google.ts +52 -9
- package/src/adapters/openai-chat/messages.ts +4 -3
- package/src/adapters/openai-chat/passthrough.ts +8 -2
- package/src/adapters/openai-chat/reasoning-replay.ts +52 -0
- package/src/adapters/openai-responses/compaction-search-history.ts +14 -7
- package/src/adapters/openai-responses/passthrough.ts +57 -125
- package/src/adapters/openai-responses/request-strips.ts +25 -3
- package/src/adapters/openai-responses/transport.ts +81 -0
- package/src/adapters/qoder/adapter.ts +4 -2
- package/src/adapters/registry.ts +5 -0
- package/src/adapters/zed.ts +26 -1
- package/src/advisor/activity.ts +55 -0
- package/src/advisor/budget.ts +62 -0
- package/src/advisor/consult.ts +4 -1
- package/src/advisor/context.ts +16 -4
- package/src/advisor/evidence-tool.ts +21 -0
- package/src/advisor/evidence.ts +117 -0
- package/src/advisor/runtime.ts +79 -31
- package/src/advisor/settings.ts +11 -2
- package/src/bridge/errors.ts +19 -1
- package/src/bridge/internal.ts +7 -1
- package/src/bridge/response-json.ts +18 -3
- package/src/bridge/sse.ts +59 -8
- package/src/bridge/terminal-refusal.ts +59 -0
- package/src/claude/desktop-3p-library.ts +32 -7
- package/src/claude/desktop-3p.ts +55 -13
- package/src/claude/desktop-first-party.ts +1 -1
- package/src/claude/desktop-picker-platform.ts +4 -0
- package/src/claude/desktop-picker.ts +15 -8
- package/src/claude/desktop-system-proxy.ts +50 -4
- package/src/claude/inbound-content-options.ts +77 -0
- package/src/claude/inbound.ts +33 -0
- package/src/claude/intercept/picker-ca-startup.ts +2 -1
- package/src/claude/intercept/picker-runtime.ts +6 -5
- package/src/claude/intercept/picker-trust-windows.ts +338 -0
- package/src/claude/intercept/picker-trust.ts +19 -0
- package/src/claude/intercept/port-policy.ts +30 -0
- package/src/claude/intercept/runtime.ts +97 -94
- package/src/claude/outbound.ts +46 -13
- package/src/cli/account-api.ts +1 -0
- package/src/cli/account-policy-dto.ts +6 -0
- package/src/cli/account-policy.ts +34 -5
- package/src/cli/account-preservation.ts +44 -0
- package/src/cli/account.ts +8 -2
- package/src/cli/advisor.ts +17 -3
- package/src/cli/capabilities-accounts.ts +20 -1
- package/src/cli/capabilities-agents-routing.ts +5 -2
- package/src/cli/capabilities-base.ts +38 -10
- package/src/cli/capabilities-observe-system.ts +63 -3
- package/src/cli/capabilities-provider-models.ts +11 -0
- package/src/cli/codex-cli-update.ts +151 -41
- package/src/cli/codex-provider.ts +44 -0
- package/src/cli/combo-input.ts +10 -1
- package/src/cli/combo-result.ts +1 -1
- package/src/cli/combo.ts +2 -1
- package/src/cli/cross-home-owner.ts +33 -16
- package/src/cli/dispatch.ts +25 -4
- package/src/cli/doctor.ts +6 -1
- package/src/cli/ensure-desktop-cold-start.ts +60 -7
- package/src/cli/help.ts +3 -2
- package/src/cli/index.ts +1 -1
- package/src/cli/integration-plan-dto.ts +1 -0
- package/src/cli/log-history.ts +172 -0
- package/src/cli/loopback-family.ts +31 -0
- package/src/cli/models-runtime-subcommands.ts +1 -0
- package/src/cli/models-runtime.ts +72 -8
- package/src/cli/observe-stream.ts +2 -0
- package/src/cli/observe.ts +16 -4
- package/src/cli/provider.ts +27 -5
- package/src/cli/registry.ts +28 -8
- package/src/cli/runtime-api.ts +5 -3
- package/src/cli/system-command.ts +40 -8
- package/src/cli/uninstall-client-state.ts +32 -0
- package/src/cli/usage-compare.ts +309 -0
- package/src/cli/usage-model-search.ts +4 -4
- package/src/cli/usage-report.ts +2 -2
- package/src/cli/v2.ts +1 -1
- package/src/client/machine-listener.ts +1 -3
- package/src/client/runtime.ts +1 -0
- package/src/clients/client-path.ts +51 -0
- package/src/clients/config-export/contracts.ts +2 -1
- package/src/clients/config-export.ts +18 -44
- package/src/clients/gentle-shell-path.ts +87 -0
- package/src/codex/account-auto-switch.ts +2 -0
- package/src/codex/account-identity.ts +29 -0
- package/src/codex/account-label.ts +1 -1
- package/src/codex/account-lifecycle.ts +21 -5
- package/src/codex/account-preservation.ts +28 -0
- package/src/codex/account-use-remaining.ts +23 -0
- package/src/codex/app-server-processes.ts +97 -7
- package/src/codex/app-server-restart-service.ts +55 -4
- package/src/codex/auth-api/account-list.ts +4 -0
- package/src/codex/auth-api/account-pause-group.ts +6 -50
- package/src/codex/auth-api/account-preservation.ts +57 -0
- package/src/codex/auth-api/routes.ts +8 -0
- package/src/codex/auth-api/use-remaining-route.ts +36 -0
- package/src/codex/auth-api.ts +0 -1
- package/src/codex/auth-context.ts +2 -2
- package/src/codex/catalog/auto-review.ts +20 -3
- package/src/codex/catalog/build-entries.ts +9 -1
- package/src/codex/catalog/combo-member.ts +14 -5
- package/src/codex/catalog/configured-tiers.ts +1 -1
- package/src/codex/catalog/gather-capture.ts +2 -0
- package/src/codex/catalog/metadata.ts +11 -9
- package/src/codex/catalog/model-hints.ts +21 -16
- package/src/codex/catalog/model-visibility.ts +3 -1
- package/src/codex/catalog/parsing.ts +30 -86
- package/src/codex/catalog/provider-models.ts +36 -34
- package/src/codex/catalog/routed-gather.ts +14 -13
- package/src/codex/cli-install-provenance.ts +105 -17
- package/src/codex/cli-update-plan.ts +545 -0
- package/src/codex/config-write-lock.ts +23 -2
- package/src/codex/desktop-app/picker-freshness.ts +96 -0
- package/src/codex/desktop-app-restart.ts +21 -0
- package/src/codex/desktop-compatibility/installed-build.ts +24 -6
- package/src/codex/desktop-compatibility/routing-preflight.ts +1 -1
- package/src/codex/desktop-compatibility/runtime.ts +12 -3
- package/src/codex/desktop-compatibility/windows-key-protection.ts +115 -9
- package/src/codex/features.ts +85 -45
- package/src/codex/inject/history-failure.ts +27 -0
- package/src/codex/inject/restore.ts +24 -2
- package/src/codex/inject/routing-classify.ts +4 -3
- package/src/codex/inject.ts +18 -27
- package/src/codex/main-account-hard-lock.ts +30 -1
- package/src/codex/native-profile-startup.ts +1 -1
- package/src/codex/ocx-compaction-history.ts +12 -10
- package/src/codex/paths.ts +86 -1
- package/src/codex/provider-routing.ts +174 -0
- package/src/codex/refresh.ts +2 -2
- package/src/codex/routing/health-store.ts +1 -1
- package/src/codex/routing/selection.ts +4 -3
- package/src/codex/routing/thread-affinity.ts +1 -1
- package/src/codex/signed-in-identity.ts +43 -0
- package/src/codex/subagent-model-fallback.ts +1 -1
- package/src/codex/sync.ts +6 -1
- package/src/codex/user-identity.ts +16 -5
- package/src/codex/websocket-activity.ts +161 -0
- package/src/codex/websocket-registry.ts +25 -1
- package/src/codex/windows-local-appdata.ts +84 -0
- package/src/combos/failover.ts +6 -1
- package/src/combos/index.ts +1 -0
- package/src/combos/resolve.ts +46 -10
- package/src/combos/types.ts +15 -0
- package/src/config/diagnostics.ts +33 -6
- package/src/config/live-reconcile.ts +38 -2
- package/src/config/load-degrade.ts +17 -0
- package/src/config/opencode-wire-upgrade.ts +54 -0
- package/src/config/opencode-zen-upgrade.ts +53 -0
- package/src/config/owner-registry.ts +22 -17
- package/src/config/provider-validation.ts +45 -2
- package/src/config/schema/config-schema.ts +22 -0
- package/src/config/schema/leaf-validators.ts +38 -9
- package/src/config/schema/main-account-hard-lock-fallback.ts +26 -0
- package/src/config/schema/native-reasoning-retention.ts +26 -0
- package/src/config.ts +2 -0
- package/src/generated/compatibility-version.json +657 -297
- package/src/grok/sync.ts +1 -1
- package/src/images/loop.ts +116 -27
- package/src/integrations/catalog-refresh.ts +1 -1
- package/src/integrations/mutation-plan.ts +1 -0
- package/src/integrations/registry.ts +8 -0
- package/src/lib/codex-restart-contract.ts +15 -0
- package/src/lib/desktop-upstream-tunnel.ts +18 -53
- package/src/lib/empty-tool-catalog.ts +62 -0
- package/src/lib/errors.ts +19 -3
- package/src/lib/gcp-adc.ts +96 -9
- package/src/lib/gcp-credential-input.ts +12 -0
- package/src/lib/lab-live-route-production.ts +5 -0
- package/src/lib/opaque-proxy-tunnel.ts +217 -0
- package/src/lib/redact.ts +2 -2
- package/src/lib/request-failure-model.ts +2 -0
- package/src/oauth/account-quota-rank.ts +69 -2
- package/src/oauth/anthropic-account-refusal.ts +20 -2
- package/src/oauth/anthropic-oauth-definitions.ts +3 -1
- package/src/oauth/anthropic-routing.ts +1 -21
- package/src/oauth/anthropic.ts +38 -7
- package/src/oauth/callback-server.ts +27 -1
- package/src/oauth/chatgpt-device.ts +1 -1
- package/src/oauth/chatgpt-shared.ts +83 -0
- package/src/oauth/chatgpt.ts +8 -72
- package/src/oauth/dsh.ts +203 -0
- package/src/oauth/generic-account-failover.ts +40 -11
- package/src/oauth/generic-session-affinity.ts +125 -0
- package/src/oauth/index.ts +184 -109
- package/src/oauth/local-token-detect.ts +21 -1
- package/src/oauth/login-cli-errors.ts +44 -0
- package/src/oauth/login-cli.ts +69 -7
- package/src/oauth/login-flow-state.ts +371 -23
- package/src/oauth/meta-muse-errors.ts +41 -0
- package/src/oauth/meta-muse-keychain.ts +52 -0
- package/src/oauth/meta-muse.ts +51 -84
- package/src/oauth/model-discovery-auth.ts +3 -0
- package/src/oauth/pool-settings-capability.ts +4 -2
- package/src/oauth/refresh-flight-retirement.ts +48 -0
- package/src/oauth/session-affinity-key.ts +23 -0
- package/src/oauth/store-anthropic-instance.ts +9 -2
- package/src/oauth/store.ts +12 -5
- package/src/protocols/encoders/adapter-events.ts +6 -5
- package/src/protocols/encoders/messages.ts +9 -6
- package/src/protocols/provider-summary.ts +2 -1
- package/src/providers/api-key-cooldowns.ts +49 -0
- package/src/providers/api-key-resolve.ts +11 -6
- package/src/providers/api-key-response-ownership.ts +57 -0
- package/src/providers/api-key-selection.ts +31 -6
- package/src/providers/api-keys.ts +214 -3
- package/src/providers/claude-cli-usage.ts +96 -0
- package/src/providers/dsh-account-destination.ts +31 -0
- package/src/providers/dsh-account-models.ts +41 -0
- package/src/providers/gcp-credential-cleanup.ts +59 -0
- package/src/providers/key-failover.ts +54 -50
- package/src/providers/key-store.ts +7 -2
- package/src/providers/model-rename-fields.ts +3 -0
- package/src/providers/model-rename-migration.ts +2 -2
- package/src/providers/openai-tiers-destination.ts +11 -2
- package/src/providers/openai-tiers.ts +5 -12
- package/src/providers/opencode-go-transport.ts +3 -1
- package/src/providers/opencode-zen-rate-limit.ts +7 -2
- package/src/providers/quota/account-cache.ts +6 -5
- package/src/providers/quota/account-row.ts +34 -0
- package/src/providers/quota/antigravity.ts +28 -7
- package/src/providers/quota/dsh-account.ts +70 -0
- package/src/providers/quota/vendor-probes-oauth.ts +1 -93
- package/src/providers/quota-types.ts +2 -0
- package/src/providers/quota.ts +14 -20
- package/src/providers/registry/entries-core.ts +37 -8
- package/src/providers/registry/types.ts +1 -1
- package/src/providers/request-pacing.ts +77 -19
- package/src/providers/routed-config.ts +339 -0
- package/src/providers/service-tier.ts +2 -1
- package/src/quota/window-mapping.ts +5 -2
- package/src/responses/anthropic-progress.ts +34 -0
- package/src/responses/assistant-replay.ts +35 -0
- package/src/responses/compaction-history-framing.ts +65 -0
- package/src/responses/compaction.ts +6 -1
- package/src/responses/incomplete-reason.ts +31 -0
- package/src/responses/parser.ts +50 -5
- package/src/responses/reasoning-envelope.ts +4 -0
- package/src/responses/reasoning-replay-cache.ts +74 -6
- package/src/responses/reasoning-retention.ts +173 -0
- package/src/responses/retained-compaction.ts +46 -0
- package/src/responses/schema.ts +23 -0
- package/src/router.ts +8 -321
- package/src/routing/analytics.ts +7 -15
- package/src/routing/health.ts +37 -22
- package/src/routing/history/indexer.ts +6 -5
- package/src/routing/history/ingest.ts +6 -2
- package/src/routing/profile.ts +1 -1
- package/src/server/admission-model-scope.ts +17 -0
- package/src/server/auth-cors.ts +11 -0
- package/src/server/chat-completions.ts +7 -1
- package/src/server/chat-native-reasoning.ts +123 -0
- package/src/server/chat-native-sse.ts +110 -7
- package/src/server/chat-native.ts +76 -17
- package/src/server/claude-messages.ts +56 -414
- package/src/server/effort-policy.ts +1 -1
- package/src/server/images.ts +15 -2
- package/src/server/index/live-sideband.ts +3 -2
- package/src/server/index/model-alias-id.ts +36 -0
- package/src/server/index/optional-listeners.ts +2 -0
- package/src/server/index/serve-options.ts +20 -6
- package/src/server/index/startup-warnings.ts +2 -0
- package/src/server/index/websocket-handler.ts +18 -4
- package/src/server/index.ts +8 -8
- package/src/server/inference/advisor-diagnostics.ts +31 -0
- package/src/server/lifecycle.ts +13 -1
- package/src/server/management/advisor-routes.ts +15 -4
- package/src/server/management/claude-desktop-picker-routes.ts +1 -1
- package/src/server/management/combo-routes.ts +176 -50
- package/src/server/management/companion-routes.ts +1 -1
- package/src/server/management/config-routes.ts +75 -4
- package/src/server/management/cursor-integration-routes.ts +1 -1
- package/src/server/management/model-routes.ts +11 -6
- package/src/server/management/model-rows.ts +14 -0
- package/src/server/management/native-integration-routes.ts +2 -7
- package/src/server/management/native-reasoning-retention-routes.ts +41 -0
- package/src/server/management/oauth-account-routes.ts +87 -14
- package/src/server/management/provider-gcp-credential-routes.ts +29 -0
- package/src/server/management/provider-key-pacing-routes.ts +31 -0
- package/src/server/management/provider-overwrite-carry.ts +7 -0
- package/src/server/management/provider-routes.ts +25 -30
- package/src/server/management/route-registry.ts +10 -1
- package/src/server/management-api.ts +3 -1
- package/src/server/messages-native-tool-guard.ts +185 -0
- package/src/server/messages-native.ts +117 -24
- package/src/server/messages-shared.ts +431 -0
- package/src/server/relay.ts +1 -1
- package/src/server/request-log-terminal-status.ts +1 -1
- package/src/server/request-log.ts +6 -1
- package/src/server/responses/account-change-state.ts +8 -2
- package/src/server/responses/adapter-continuation.ts +47 -19
- package/src/server/responses/adapter-delivery.ts +72 -12
- package/src/server/responses/adapter-dispatch.ts +46 -3
- package/src/server/responses/advisor-retention.ts +117 -0
- package/src/server/responses/advisor-slot.ts +73 -41
- package/src/server/responses/anthropic-thinking-recovery.ts +153 -0
- package/src/server/responses/codex-ws-wire.ts +15 -8
- package/src/server/responses/combo-stream-preflight.ts +3 -2
- package/src/server/responses/compact.ts +303 -125
- package/src/server/responses/compaction-recovery.ts +20 -10
- package/src/server/responses/compaction-retention.ts +61 -0
- package/src/server/responses/context-overflow.ts +11 -6
- package/src/server/responses/core-auth.ts +6 -0
- package/src/server/responses/core-codex-account.ts +11 -1
- package/src/server/responses/core-combo-failure.ts +2 -0
- package/src/server/responses/core-combo.ts +121 -36
- package/src/server/responses/core-errors.ts +3 -3
- package/src/server/responses/core-lifetime.ts +8 -4
- package/src/server/responses/core-opaque-recovery.ts +35 -0
- package/src/server/responses/core-options.ts +7 -0
- package/src/server/responses/core-pipeline.ts +141 -0
- package/src/server/responses/core-replay.ts +23 -3
- package/src/server/responses/core.ts +2 -115
- package/src/server/responses/fetch-helpers.ts +73 -19
- package/src/server/responses/main-hard-lock-routing.ts +109 -0
- package/src/server/responses/native-response-control.ts +4 -2
- package/src/server/responses/passthrough-delivery.ts +3 -1
- package/src/server/responses/passthrough-dispatch.ts +15 -13
- package/src/server/responses/passthrough-execution.ts +3 -2
- package/src/server/responses/request-prepare.ts +77 -12
- package/src/server/responses/request-sidecar-auth.ts +2 -2
- package/src/server/responses/request-transport.ts +104 -27
- package/src/server/responses/response-effects.ts +2 -0
- package/src/server/responses/response-tool-ownership.ts +21 -0
- package/src/server/responses/run-turn-execution.ts +96 -30
- package/src/server/responses/sidecar-execution.ts +63 -9
- package/src/server/responses/sidecar-send-budget.ts +2 -2
- package/src/server/responses/terminal-guard.ts +2 -16
- package/src/server/responses-undeclared-tool-guard.ts +1 -1
- package/src/server/ws-bridge.ts +2 -0
- package/src/service/auth-preflight.ts +71 -0
- package/src/service/cli.ts +4 -2
- package/src/service/definition.ts +97 -0
- package/src/service/guards.ts +1 -61
- package/src/service/health-sentinel-linux.ts +112 -0
- package/src/service/health-sentinel-main.ts +76 -57
- package/src/service/health.ts +5 -89
- package/src/service/launchd.ts +27 -7
- package/src/service/logging.ts +72 -9
- package/src/service/repair.ts +2 -1
- package/src/service/state.ts +7 -8
- package/src/service/systemd.ts +1 -1
- package/src/service/windows-guarded-manager.ts +2 -1
- package/src/service/windows-ops.ts +1 -1
- package/src/service/windows-scheduler.ts +2 -7
- package/src/service/windows-taskxml.ts +2 -2
- package/src/service/windows-wscript.ts +14 -0
- package/src/service.ts +4 -2
- package/src/sidecar/auth.ts +2 -0
- package/src/types/config.ts +64 -3
- package/src/types/opencode-go.ts +61 -0
- package/src/types/opencode-zen.ts +35 -0
- package/src/types/provider.ts +32 -6
- package/src/types/request.ts +31 -2
- package/src/types/wire.ts +31 -37
- package/src/types.ts +2 -0
- package/src/update/npm-invocation.mjs +12 -2
- package/src/usage/cost.ts +48 -12
- package/src/usage/expected-prices.ts +3 -0
- package/src/usage/ledger-retention.ts +2 -1
- package/src/usage/ledger-scanner.ts +6 -5
- package/src/usage/log.ts +17 -8
- package/src/usage/summary.ts +30 -11
- package/src/usage/telemetry-contract.ts +1 -0
- package/src/usage/user-cost-overlays.ts +14 -19
- package/src/usage/user-cost-validation.ts +38 -0
- package/src/vision/eligibility.ts +13 -0
- package/src/web-search/anthropic-history.ts +59 -0
- package/src/web-search/loop.ts +236 -73
- package/src/web-search/progress-stream.ts +15 -2
- package/src/web-search/run-turn-loop.ts +9 -1
- package/gui/dist/assets/App-BjlttVLy.js +0 -58
- package/gui/dist/assets/App-CSJvmjNs.css +0 -1
- package/gui/dist/assets/index-BB6uK6tU.css +0 -1
- package/gui/dist/assets/index-BMssP4k3.js +0 -94
- package/gui/dist/assets/quota-summary-D8M1bc_R.js +0 -1
|
@@ -27,10 +27,10 @@ import {
|
|
|
27
27
|
anthropicRoutingFor,
|
|
28
28
|
AnthropicAccountCooldownError,
|
|
29
29
|
formatAnthropicProviderForLog,
|
|
30
|
-
anthropicSessionKeyFromParts,
|
|
31
30
|
} from "../../oauth/anthropic-routing";
|
|
32
31
|
import {
|
|
33
32
|
OAuthAccountPausedError,
|
|
33
|
+
OAuthTokenRefreshBusyError,
|
|
34
34
|
getValidAccessSnapshotForAccount,
|
|
35
35
|
forceRefreshOAuthAccessSnapshot,
|
|
36
36
|
getValidAccessTokenSnapshot,
|
|
@@ -49,6 +49,9 @@ import {
|
|
|
49
49
|
refusalAwareInitialKiroAccount,
|
|
50
50
|
noteGenericPoolSelection,
|
|
51
51
|
} from "../../oauth/generic-account-failover";
|
|
52
|
+
import { admitGenericSessionAccount, bindGenericSessionAccount, genericSessionAccount, genericSessionAccountEligible, genericSessionAffinityEnabled, preferredGenericSessionAccount } from "../../oauth/generic-session-affinity";
|
|
53
|
+
import { oauthSessionKeyFromParts } from "../../oauth/session-affinity-key";
|
|
54
|
+
import { resolveContextPrincipal } from "../auth-cors";
|
|
52
55
|
import { tryKiroAlternateAfterTerminalRefresh } from "../../oauth/kiro-terminal-failover";
|
|
53
56
|
import { classifyModelFamilyForQuota } from "../../oauth/account-quota-rank";
|
|
54
57
|
import { expandInferenceOAuthSendBudget } from "../inference/context";
|
|
@@ -78,6 +81,7 @@ import { bindRouteReasoningReplayScope } from "./core-replay";
|
|
|
78
81
|
import { sessionIdHeaderFromRequest, normalizeLogConversationId } from "../request-log-conversation";
|
|
79
82
|
import { redactSecretString } from "../../lib/redact";
|
|
80
83
|
import { selectProactiveApiKeyTransport } from "../../providers/key-failover";
|
|
84
|
+
import { distributedKeyPhysicalFetch } from "../../providers/api-key-response-ownership";
|
|
81
85
|
import { isCanonicalOpenAiForwardProvider } from "../../providers/openai-tiers";
|
|
82
86
|
import { providerConsumesCallerAuthorization } from "../../providers/caller-authorization";
|
|
83
87
|
import { releaseCodexAuthContextProbeLease, stripCodexRuntimeProviderFields } from "../../codex/auth-context";
|
|
@@ -120,6 +124,7 @@ export async function prepareResponsesTransport(
|
|
|
120
124
|
) {
|
|
121
125
|
const { config, logCtx, options, req } = requestContext;
|
|
122
126
|
const { route, parsed, inboundWire, translatorBudget } = requestState;
|
|
127
|
+
const genericAffinityMode = genericSessionAffinityEnabled(config, route.providerName);
|
|
123
128
|
const anthropicInstance = route.provider.authMode === "oauth"
|
|
124
129
|
? configuredAnthropicInstance(config, route.providerName) : undefined;
|
|
125
130
|
// Refuse custom/orphan B OAuth before any generic resolver can observe its auth row.
|
|
@@ -176,6 +181,7 @@ export async function prepareResponsesTransport(
|
|
|
176
181
|
|| route.providerName === "orcarouter-oauth"
|
|
177
182
|
// runTurn transport: the replay runs on the first-event preflight in run-turn-execution.
|
|
178
183
|
|| route.providerName === "devin"
|
|
184
|
+
|| route.providerName === "dsh-account"
|
|
179
185
|
) && route.provider.authMode === "oauth";
|
|
180
186
|
let sentOAuthSnapshot: OAuthAccessSnapshot | undefined;
|
|
181
187
|
// One inference-401 replay belongs to this request, even when Auto changes exchange wire.
|
|
@@ -217,6 +223,8 @@ export async function prepareResponsesTransport(
|
|
|
217
223
|
for (let attempt = 0; attempt < maxSelectionAttempts; attempt++) {
|
|
218
224
|
requireAnthropicAdmission();
|
|
219
225
|
if (candidate.provider !== route.providerName) return null;
|
|
226
|
+
if (genericAffinityMode && route.provider.googleMode === "cloud-code-assist" && !candidate.projectId)
|
|
227
|
+
throw new OAuthLoginRequiredError(route.providerName);
|
|
220
228
|
if (anthropicInstance) anthropicRouteDecision = currentAnthropicRouteDecision();
|
|
221
229
|
if (!oauthSelection) return null;
|
|
222
230
|
const proactiveEnabled = anthropicInstance !== undefined
|
|
@@ -234,7 +242,9 @@ export async function prepareResponsesTransport(
|
|
|
234
242
|
if (candidate.provider !== route.providerName) return null;
|
|
235
243
|
if (anthropicInstance) anthropicRouteDecision = currentAnthropicRouteDecision();
|
|
236
244
|
if (anthropicRouteDecision && !routeCandidates(anthropicRouting!.getEligibleAnthropicAccounts(Date.now(), route.modelId), anthropicRouteDecision).includes(candidate.accountId)) return null;
|
|
237
|
-
const committed =
|
|
245
|
+
const committed = genericAffinityMode
|
|
246
|
+
? admitGenericSessionAccount(config, route.providerName, oauthSelection, candidate, route.modelId, genericAffinityMode)
|
|
247
|
+
: await commitOAuthAccountSelection(route.providerName, candidate.accountId, {
|
|
238
248
|
expectedSelection: oauthSelection,
|
|
239
249
|
expectedCredentialGeneration: candidate.generation,
|
|
240
250
|
requireUsableAccount: true,
|
|
@@ -248,14 +258,18 @@ export async function prepareResponsesTransport(
|
|
|
248
258
|
)) return null;
|
|
249
259
|
oauthSelection = committed;
|
|
250
260
|
servingOAuthSnapshot = candidate;
|
|
261
|
+
bindGenericSessionAccount(config, route.providerName, genericSessionKey, candidate.accountId, route.modelId);
|
|
251
262
|
if (anthropicInstance) replayOAuthCredentialSnapshot = { accountId: candidate.accountId, generation: candidate.generation };
|
|
252
263
|
forgetGenericFailoverRoster(route.providerName);
|
|
253
264
|
return candidate;
|
|
254
265
|
}
|
|
255
266
|
// A newer manual choice wins over this request's old proposal, including A→B→A.
|
|
256
267
|
// Resolve that choice, not the rejected candidate, before trying admission again.
|
|
268
|
+
const previousSelection = oauthSelection;
|
|
257
269
|
oauthSelection = captureOAuthAccountSelection(route.providerName);
|
|
258
270
|
if (!oauthSelection) return null;
|
|
271
|
+
const selectionChanged = oauthSelection.accountId !== previousSelection.accountId
|
|
272
|
+
|| oauthSelection.revision !== previousSelection.revision;
|
|
259
273
|
// A revision also changes on per-account policy edits. Re-evaluate the selector
|
|
260
274
|
// after credential waits even without a model route, rather than reusing stale active.
|
|
261
275
|
const revisedAnthropic = anthropicInstance !== undefined
|
|
@@ -263,9 +277,15 @@ export async function prepareResponsesTransport(
|
|
|
263
277
|
const revisedAnthropicId = revisedAnthropic?.accountId;
|
|
264
278
|
if (anthropicInstance !== undefined && !revisedAnthropicId) return null;
|
|
265
279
|
if (revisedAnthropic) anthropicReason = revisedAnthropic.reason;
|
|
280
|
+
const genericAccountId = genericAffinityMode && !selectionChanged
|
|
281
|
+
? (genericSessionAccountEligible(config, route.providerName, candidate.accountId, route.modelId, Date.now(), true)
|
|
282
|
+
? candidate.accountId : (preferredGenericSessionAccount(config, route.providerName, genericSessionKey, route.modelId)
|
|
283
|
+
?? oauthSelection.accountId))
|
|
284
|
+
: oauthSelection.accountId;
|
|
285
|
+
if (!genericAccountId && !anthropicInstance) return null;
|
|
266
286
|
candidate = anthropicInstance !== undefined
|
|
267
287
|
? await anthropicRouting!.getAnthropicPoolAccessSnapshot(revisedAnthropicId ?? oauthSelection.accountId)
|
|
268
|
-
: await getValidAccessSnapshotForAccount(route.providerName,
|
|
288
|
+
: await getValidAccessSnapshotForAccount(route.providerName, genericAccountId!, { requireUsableAccount: true });
|
|
269
289
|
if (route.provider.googleMode === "cloud-code-assist" && !candidate.projectId) return null;
|
|
270
290
|
}
|
|
271
291
|
return null;
|
|
@@ -275,7 +295,10 @@ export async function prepareResponsesTransport(
|
|
|
275
295
|
// Keyed on the account, not the selection revision: a selection that moved away and back
|
|
276
296
|
// (A -> B -> A) before the 401 landed still serves the rejected credential, and skipping
|
|
277
297
|
// the refresh would replay it and spend the one recovery attempt.
|
|
278
|
-
const candidate = current?.accountId === sent.accountId
|
|
298
|
+
const candidate = (current?.accountId === sent.accountId
|
|
299
|
+
|| (genericAffinityMode && current?.revision === oauthSelection?.revision
|
|
300
|
+
&& current?.accountId === oauthSelection?.accountId && servingOAuthSnapshot?.accountId === sent.accountId))
|
|
301
|
+
? await forceRefreshOAuthAccessSnapshot(sent) : sent;
|
|
279
302
|
const admitted = await commitResolvedOAuthSelection(candidate);
|
|
280
303
|
if (!admitted) throw new Error("OAuth selection changed during credential recovery");
|
|
281
304
|
if (kiroLoadEnabled && options.accountLoad?.lease?.accountId !== admitted.accountId) {
|
|
@@ -519,6 +542,8 @@ export async function prepareResponsesTransport(
|
|
|
519
542
|
return selected?.accountId === binding.selection.accountId && selected?.revision === binding.selection.revision
|
|
520
543
|
&& !!row && !row.paused && !row.needsReauth && row.credential.expires > Date.now()
|
|
521
544
|
&& (anthropicInstance === undefined || !anthropicRouting!.getAnthropicAccountHealthSnapshot(binding.snapshot.accountId) && !anthropicRatePolicy!.anthropicRatePauseUntil(binding.snapshot.accountId) && !anthropicQuota!.anthropicFamilyRejected(binding.snapshot.accountId, route.modelId))
|
|
545
|
+
&& (!genericAffinityMode
|
|
546
|
+
|| genericSessionAccountEligible(config, route.providerName, binding.snapshot.accountId, route.modelId, Date.now(), true))
|
|
522
547
|
&& credentialGeneration(row.credential) === binding.snapshot.generation;
|
|
523
548
|
};
|
|
524
549
|
/** Bind the negotiated wire adapter and its built requests to the serving credential's authority. */
|
|
@@ -592,12 +617,23 @@ export async function prepareResponsesTransport(
|
|
|
592
617
|
const accountId = await anthropicRouting!.resolveAnthropicDispatchAccountId(config, anthropicSessionKey, anthropicRouteDecision, route.modelId);
|
|
593
618
|
candidate = await anthropicRouting!.getAnthropicPoolAccessSnapshot(accountId);
|
|
594
619
|
}
|
|
620
|
+
if (genericAffinityMode
|
|
621
|
+
&& (!candidate || !genericSessionAccountEligible(config, route.providerName, candidate.accountId, route.modelId, Date.now(), true))) {
|
|
622
|
+
const accountId = preferredGenericSessionAccount(config, route.providerName, genericSessionKey, route.modelId)
|
|
623
|
+
?? captureOAuthAccountSelection(route.providerName)?.accountId;
|
|
624
|
+
candidate = accountId ? await getValidAccessSnapshotForAccount(route.providerName, accountId, { requireUsableAccount: true }) : undefined;
|
|
625
|
+
}
|
|
595
626
|
if (!candidate || !await applyFailoverSnapshot(candidate, requestParsed, true)) {
|
|
596
627
|
if (anthropicInstance !== undefined) await anthropicRouting!.resolveAnthropicDispatchAccountId(config, anthropicSessionKey, anthropicRouteDecision, route.modelId);
|
|
597
628
|
throw new Error("OAuth account selection changed before dispatch");
|
|
598
629
|
}
|
|
599
630
|
} else {
|
|
600
|
-
|
|
631
|
+
let current = resolveCurrentProviderApiKeyTransport(config, route.providerName, route.provider);
|
|
632
|
+
if (!current && (route.provider._apiKeyAttempt?.distributed || (route.provider.requestPacing?.enabled
|
|
633
|
+
&& (route.provider.requestPacing.keys || route.provider.requestPacing.keySelection === "round-robin")))) {
|
|
634
|
+
const fresh = resolveCurrentProviderApiKeyTransport(config, route.providerName, { ...route.provider, _apiKeyAttempt: undefined });
|
|
635
|
+
if (fresh) current = selectProactiveApiKeyTransport(config, route.providerName, fresh) ?? fresh;
|
|
636
|
+
}
|
|
601
637
|
if (!current) throw new Error("API key selection is unavailable before dispatch");
|
|
602
638
|
route.provider = current;
|
|
603
639
|
await resolveCopilotSelection(requestParsed, true);
|
|
@@ -625,7 +661,10 @@ export async function prepareResponsesTransport(
|
|
|
625
661
|
? (options.sendBudget as import("../../lib/request-execution-budget").RequestExecutionBudget).beginSpendProducer?.() : undefined;
|
|
626
662
|
try {
|
|
627
663
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
628
|
-
|
|
664
|
+
incoming.abortSignal?.throwIfAborted();
|
|
665
|
+
const selectionRefreshed = !selectionIsCurrent(adapterBindings.get(selectedAdapter));
|
|
666
|
+
if (attempt === 0 && selectionRefreshed) releaseProviderRequestSlot(incoming.pacingSlot);
|
|
667
|
+
if (selectionRefreshed) selectedAdapter = await refreshRunTurnAdapter(requestParsed);
|
|
629
668
|
const binding = adapterBindings.get(selectedAdapter);
|
|
630
669
|
const run = rawRunTurns.get(selectedAdapter);
|
|
631
670
|
if (!run) throw new Error("Selected provider no longer supports this turn transport");
|
|
@@ -635,24 +674,39 @@ export async function prepareResponsesTransport(
|
|
|
635
674
|
// Both main and image-loop callers already acquired the initial pacing slot.
|
|
636
675
|
// Subsequent physical messages retain this adapter/credential and are paced normally.
|
|
637
676
|
try {
|
|
638
|
-
|
|
639
|
-
|
|
677
|
+
// A pre-acquired lease belongs to the original selection, never its replacement.
|
|
678
|
+
attemptSlot = attempt === 0 && !selectionRefreshed && incoming.pacingSlot
|
|
679
|
+
? incoming.pacingSlot
|
|
640
680
|
: await waitForProviderRequestSlot(route.providerName, route.provider, route.modelId, incoming.abortSignal);
|
|
681
|
+
incoming.abortSignal?.throwIfAborted();
|
|
682
|
+
// Every admission can queue, including a replacement's. Never enter an
|
|
683
|
+
// adapter on a lease whose credential changed while it waited.
|
|
684
|
+
if (!selectionIsCurrent(binding)) {
|
|
685
|
+
refused = true;
|
|
686
|
+
throw new Error("Account selection changed before turn admission");
|
|
687
|
+
}
|
|
688
|
+
const beforePhysicalSend = (): void => {
|
|
689
|
+
incoming.abortSignal?.throwIfAborted();
|
|
690
|
+
if (sent) {
|
|
691
|
+
if (binding?.kind === "api-key" && binding.provider._apiKeyAttempt?.distributed
|
|
692
|
+
&& !selectionIsCurrent(binding)) throw new Error("API key became unavailable during the turn");
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
if (!selectionIsCurrent(binding)) {
|
|
696
|
+
refused = true;
|
|
697
|
+
throw new Error("Account selection changed before the first turn dispatch");
|
|
698
|
+
}
|
|
699
|
+
incoming.beforePhysicalSend?.();
|
|
700
|
+
commitKeyAttemptSend();
|
|
701
|
+
sent = true;
|
|
702
|
+
};
|
|
641
703
|
const fetch = providerFetch(route.provider, options.codexWsRuntimeIdentity, {
|
|
642
704
|
providerName: route.providerName, modelId: route.modelId, pacingSlotAcquired: true,
|
|
643
705
|
pacingSlot: attemptSlot,
|
|
644
706
|
turnScopedPacing: true,
|
|
645
|
-
beforeDispatch:
|
|
646
|
-
if (sent) return;
|
|
647
|
-
if (!selectionIsCurrent(binding)) {
|
|
648
|
-
refused = true;
|
|
649
|
-
throw new Error("Account selection changed before the first turn dispatch");
|
|
650
|
-
}
|
|
651
|
-
commitKeyAttemptSend();
|
|
652
|
-
sent = true;
|
|
653
|
-
},
|
|
707
|
+
beforeDispatch: beforePhysicalSend,
|
|
654
708
|
});
|
|
655
|
-
await run(requestParsed, { ...incoming, providerFetch: fetch }, event => { if (!refused) emit(event); });
|
|
709
|
+
await run(requestParsed, { ...incoming, pacingSlot: attemptSlot, providerFetch: fetch, beforePhysicalSend }, event => { if (!refused) emit(event); });
|
|
656
710
|
} catch (error) {
|
|
657
711
|
if (!refused) throw error;
|
|
658
712
|
} finally {
|
|
@@ -661,7 +715,7 @@ export async function prepareResponsesTransport(
|
|
|
661
715
|
if (!refused) return;
|
|
662
716
|
// The adapter may map the guard's exception to an error event. Neither that
|
|
663
717
|
// event nor a refused send may escape before retrying the newly selected account.
|
|
664
|
-
selectedAdapter = await refreshRunTurnAdapter(requestParsed);
|
|
718
|
+
if (attempt < 2) selectedAdapter = await refreshRunTurnAdapter(requestParsed);
|
|
665
719
|
}
|
|
666
720
|
throw new Error("Account selection changed repeatedly before turn dispatch");
|
|
667
721
|
} finally { producer?.close(); }
|
|
@@ -669,10 +723,16 @@ export async function prepareResponsesTransport(
|
|
|
669
723
|
/** Fence the physical send, with bounded credential/session rebuilds and safe negotiated refusals. */
|
|
670
724
|
const oauthDispatch = (wireRequest: AdapterRequest, requestParsed = parsed, owner: "adapter" | "passthrough" = "adapter"): ProviderFetchOptions["dispatchOverride"] => {
|
|
671
725
|
if (route.provider.authMode === "forward") return undefined;
|
|
672
|
-
return /** Dispatch with the current binding and session, rebuilding at most three times before returning a safe refusal. */ async (input, init, execute) => {
|
|
726
|
+
return /** Dispatch with the current binding and session, rebuilding at most three times before returning a safe refusal. */ async (input, init, execute, reacquirePacing) => {
|
|
673
727
|
let destination = input;
|
|
674
728
|
let dispatchInit = init;
|
|
729
|
+
let pacingChanged = false;
|
|
675
730
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
731
|
+
if (pacingChanged) {
|
|
732
|
+
if (!reacquirePacing) throw new Error("Refreshed dispatch requires pacing readmission");
|
|
733
|
+
await reacquirePacing(route.provider, route.modelId);
|
|
734
|
+
pacingChanged = false;
|
|
735
|
+
}
|
|
676
736
|
if (selectionIsCurrent(requestBindings.get(wireRequest)) && copilotSessionExpiresAt > Date.now() + 1000) {
|
|
677
737
|
const fetchImpl = (route.provider as OcxProviderConfig & { fetch?: typeof globalThis.fetch }).fetch ?? execute;
|
|
678
738
|
const binding = requestBindings.get(wireRequest);
|
|
@@ -713,7 +773,7 @@ export async function prepareResponsesTransport(
|
|
|
713
773
|
}
|
|
714
774
|
commitKeyAttemptSend();
|
|
715
775
|
response = await sendWithConnectionPolicy(
|
|
716
|
-
anthropicBillingPhysicalFetch(fetchImpl, route.providerName, route.provider),
|
|
776
|
+
distributedKeyPhysicalFetch(anthropicBillingPhysicalFetch(fetchImpl, route.providerName, route.provider), route.providerName, route.provider, target),
|
|
717
777
|
destination,
|
|
718
778
|
{ ...dispatchInit, redirect: "manual" },
|
|
719
779
|
{ providerName: route.providerName, provider: route.provider },
|
|
@@ -775,13 +835,15 @@ export async function prepareResponsesTransport(
|
|
|
775
835
|
sameTargetToken = transportToken;
|
|
776
836
|
destination = rebuilt.url;
|
|
777
837
|
dispatchInit = { ...dispatchInit, method: rebuilt.method, headers, body: rebuilt.body };
|
|
778
|
-
|
|
838
|
+
pacingChanged = route.provider.requestPacing?.enabled === true
|
|
839
|
+
&& (!!route.provider.requestPacing.keys || route.provider.requestPacing.keySelection === "round-robin");
|
|
840
|
+
// A refreshed key must reacquire admission before the next synchronous send guard.
|
|
779
841
|
}
|
|
780
842
|
throw new Error("OAuth account selection changed repeatedly before dispatch");
|
|
781
843
|
};
|
|
782
844
|
};
|
|
783
|
-
const
|
|
784
|
-
?
|
|
845
|
+
const oauthSessionKey = route.provider.authMode === "oauth"
|
|
846
|
+
? oauthSessionKeyFromParts({
|
|
785
847
|
sessionIdHeader: sessionIdHeaderFromRequest(req.headers),
|
|
786
848
|
threadIdHeader: req.headers.get("thread-id"),
|
|
787
849
|
promptCacheKey: typeof parsed.options.promptCacheKey === "string" ? parsed.options.promptCacheKey : null,
|
|
@@ -789,6 +851,9 @@ export async function prepareResponsesTransport(
|
|
|
789
851
|
promptCacheKeyIsSharedCohort: options.promptCacheKeyIsSharedCohort === true,
|
|
790
852
|
})
|
|
791
853
|
: null;
|
|
854
|
+
const anthropicSessionKey = anthropicInstance ? oauthSessionKey : null;
|
|
855
|
+
const genericSessionKey = genericAffinityMode && oauthSessionKey
|
|
856
|
+
? JSON.stringify([resolveContextPrincipal(req, config, options.admission) ?? "loopback", oauthSessionKey]) : null;
|
|
792
857
|
if (route.provider.authMode === "oauth") {
|
|
793
858
|
try {
|
|
794
859
|
if (anthropicInstance !== undefined && anthropicRouting!.isAnthropicAccountPoolEnabled(config)) {
|
|
@@ -821,10 +886,17 @@ export async function prepareResponsesTransport(
|
|
|
821
886
|
// without quota evidence keeps the resolution it has today.
|
|
822
887
|
const refusalAwareId = route.providerName === "kiro" && oauthSelection?.accountId
|
|
823
888
|
? refusalAwareInitialKiroAccount(config, oauthSelection.accountId, Date.now(), route.modelId) : null;
|
|
824
|
-
const
|
|
889
|
+
const affinityAccountId = genericSessionAccount(config, route.providerName, genericSessionKey, route.modelId);
|
|
890
|
+
const proposedAccountId = affinityAccountId
|
|
891
|
+
?? preferredGenericSessionAccount(config, route.providerName, genericSessionKey, route.modelId)
|
|
892
|
+
?? refusalAwareId ?? (isGenericFailoverProvider(route.providerName, route.provider)
|
|
825
893
|
? preferredInitialAccount(config, route.providerName, Date.now(), route.modelId)
|
|
826
894
|
: null);
|
|
827
|
-
|
|
895
|
+
// An unchanged active choice must retain the ordinary resolver's terminal-refresh
|
|
896
|
+
// recovery (not the speculative-preference fallback that resolves the same dead grant).
|
|
897
|
+
const preferredAccountId = genericAffinityMode && proposedAccountId === oauthSelection?.accountId
|
|
898
|
+
? null : proposedAccountId;
|
|
899
|
+
let safetyAlternateId: string | null = !affinityAccountId && preferredAccountId === refusalAwareId ? refusalAwareId : null;
|
|
828
900
|
// Resolved account-scoped, NOT through failoverAccountSnapshot: that helper marks a
|
|
829
901
|
// rotation site, and rotation sites must apply their credential through
|
|
830
902
|
// applyFailoverSnapshot's pairing rules. This is initial resolution — the code below
|
|
@@ -926,7 +998,8 @@ export async function prepareResponsesTransport(
|
|
|
926
998
|
// Advance the pool cursor only now that this account is actually admitted. The
|
|
927
999
|
// helper returns immediately unless the kernel is on AND the strategy is
|
|
928
1000
|
// round-robin, so quota and fill-first pools reach it without being touched.
|
|
929
|
-
|
|
1001
|
+
if (!affinityAccountId || affinityAccountId !== resolved.accountId)
|
|
1002
|
+
noteGenericPoolSelection(config, route.providerName, resolved.accountId, route.modelId);
|
|
930
1003
|
}
|
|
931
1004
|
// Anthropic is excluded from isGenericFailoverProvider -- its own pool owns affinity and
|
|
932
1005
|
// a fail-closed local-cli credential rule -- so without this stamp its identity is
|
|
@@ -964,6 +1037,10 @@ export async function prepareResponsesTransport(
|
|
|
964
1037
|
`${redactSecretString(err.message)}. Remove or reconfigure provider '${safeProviderName}' in the OpenCodex configuration.`,
|
|
965
1038
|
);
|
|
966
1039
|
}
|
|
1040
|
+
if (err instanceof OAuthTokenRefreshBusyError) {
|
|
1041
|
+
return options.abortSignal?.aborted || req.signal.aborted ? clientCancelledResponse()
|
|
1042
|
+
: formatErrorResponse(503, "server_error", err.message, { retryAfter: "1" });
|
|
1043
|
+
}
|
|
967
1044
|
if (err instanceof OAuthAccountPausedError) {
|
|
968
1045
|
return formatErrorResponse(403, "permission_error", publicOAuthAuthenticationErrorMessage(err));
|
|
969
1046
|
}
|
|
@@ -89,6 +89,8 @@ export function createResponsesEffects(
|
|
|
89
89
|
if (routedCompaction) {
|
|
90
90
|
delete parsed.context.tools;
|
|
91
91
|
delete parsed._webSearch;
|
|
92
|
+
delete parsed._anthropicServerTools;
|
|
93
|
+
delete parsed._anthropicServerReplay;
|
|
92
94
|
delete parsed.options.toolChoice;
|
|
93
95
|
delete parsed.options.parallelToolCalls;
|
|
94
96
|
// The compaction turn is a plain prose summary; a surviving structured-output format
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ProviderExecutedCallType } from "../responses-undeclared-tool-guard";
|
|
2
|
+
|
|
3
|
+
// Route-authorized execution ownership follows only the response selected for delivery.
|
|
4
|
+
// It never becomes a wire header or mutable state shared by competing route attempts.
|
|
5
|
+
const providerCalls = new WeakMap<Response, ReadonlySet<ProviderExecutedCallType>>();
|
|
6
|
+
|
|
7
|
+
export function attachResponseToolOwnership(response: Response, types: ReadonlySet<ProviderExecutedCallType>): Response {
|
|
8
|
+
if (types.size > 0) providerCalls.set(response, new Set(types));
|
|
9
|
+
return response;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function responseToolOwnership(response: Response): ReadonlySet<ProviderExecutedCallType> | undefined {
|
|
13
|
+
return providerCalls.get(response);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Carry ownership only when rebuilding the same selected response body. */
|
|
17
|
+
export function carryResponseToolOwnership(source: Response, target: Response): Response {
|
|
18
|
+
const types = providerCalls.get(source);
|
|
19
|
+
if (types) providerCalls.set(target, types);
|
|
20
|
+
return target;
|
|
21
|
+
}
|