@bitkyc08/opencodex 2.84.0 → 2.87.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/README.md +0 -4
- package/bin/ocx.mjs +61 -3
- package/gui/dist/assets/App-ZfYbLHkB.js +58 -0
- package/gui/dist/assets/App-wT3mXqFz.css +1 -0
- package/gui/dist/assets/{Tray-C9TGtwad.js → Tray-DCd-A1az.js} +1 -1
- package/gui/dist/assets/index-CfYDMj34.js +94 -0
- package/gui/dist/assets/index-DPeB9HpV.css +1 -0
- package/gui/dist/assets/quota-summary-ChvmKGOk.js +1 -0
- package/gui/dist/index.html +2 -2
- package/package.json +1 -2
- package/src/adapters/anthropic/beta-allowlist.ts +91 -11
- package/src/adapters/anthropic/beta-body-pairs.ts +93 -0
- package/src/adapters/anthropic/client-identity.ts +1 -1
- package/src/adapters/anthropic/passthrough.ts +16 -3
- package/src/adapters/anthropic-progress.ts +84 -0
- package/src/adapters/anthropic.ts +108 -21
- package/src/adapters/azure.ts +19 -1
- 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/client-fingerprint.ts +24 -0
- package/src/adapters/coding-agent/protocol.ts +1 -1
- package/src/adapters/coding-agent/turn.ts +40 -11
- package/src/adapters/cursor/arg-codec.ts +17 -5
- package/src/adapters/cursor/catalog.ts +8 -0
- package/src/adapters/cursor/effort-map.ts +3 -0
- package/src/adapters/cursor/freeform-args.ts +75 -0
- package/src/adapters/cursor/protobuf-events.ts +36 -23
- package/src/adapters/dsh-account.ts +97 -0
- package/src/adapters/google-antigravity-wire.ts +22 -1
- package/src/adapters/google.ts +37 -10
- 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-chat/response-events.ts +59 -1
- package/src/adapters/openai-chat.ts +8 -5
- 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 +44 -3
- 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 +223 -0
- package/src/advisor/context.ts +238 -0
- package/src/advisor/disclosure.ts +20 -0
- package/src/advisor/evidence-tool.ts +21 -0
- package/src/advisor/evidence.ts +117 -0
- package/src/advisor/runtime.ts +353 -0
- package/src/advisor/settings.ts +144 -0
- package/src/advisor/state.ts +369 -0
- package/src/advisor/synthetic-tool.ts +33 -0
- package/src/bridge/errors.ts +24 -1
- package/src/bridge/internal.ts +3 -1
- package/src/bridge/response-json.ts +18 -3
- package/src/bridge/sse.ts +58 -8
- package/src/bridge/terminal-refusal.ts +59 -0
- package/src/chat/inbound.ts +30 -6
- package/src/chat/outbound.ts +5 -0
- package/src/claude/desktop-3p-library.ts +72 -7
- package/src/claude/desktop-3p.ts +75 -19
- package/src/claude/desktop-first-party.ts +1 -1
- package/src/claude/desktop-picker-platform.ts +4 -0
- package/src/claude/desktop-picker-profile.ts +11 -4
- package/src/claude/desktop-picker.ts +15 -8
- package/src/claude/desktop-profile.ts +10 -1
- package/src/claude/desktop-remote-store-io.ts +5 -3
- package/src/claude/desktop-system-proxy.ts +50 -4
- package/src/claude/inbound-content-options.ts +11 -0
- package/src/claude/inbound.ts +154 -50
- package/src/claude/intercept/local-ca.ts +8 -1
- 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/model-default-settings.ts +154 -0
- package/src/claude/model-info.ts +7 -7
- package/src/claude/outbound.ts +51 -19
- 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 +165 -0
- package/src/cli/auxiliary-listener-preflight.ts +37 -0
- package/src/cli/capabilities-accounts.ts +20 -1
- package/src/cli/capabilities-agents-routing.ts +23 -2
- package/src/cli/capabilities-base.ts +39 -11
- package/src/cli/capabilities-observe-system.ts +63 -3
- package/src/cli/capabilities-provider-models.ts +11 -0
- package/src/cli/chatgpt-command.ts +35 -14
- package/src/cli/claude.ts +46 -6
- 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 +17 -14
- package/src/cli/dispatch.ts +30 -5
- package/src/cli/doctor.ts +15 -1
- package/src/cli/ensure-desktop-cold-start.ts +382 -0
- package/src/cli/export-command.ts +1 -1
- package/src/cli/help.ts +4 -2
- package/src/cli/index.ts +14 -5
- package/src/cli/integration-plan-dto.ts +3 -0
- package/src/cli/log-history.ts +172 -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 +41 -9
- package/src/cli/restart-scope.ts +3 -1
- 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 +3 -1
- package/src/clients/config-export/model-metadata.ts +3 -2
- package/src/clients/config-export/qoder.ts +93 -0
- package/src/clients/config-export.ts +35 -48
- 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/pool-mode-gate.ts +5 -2
- 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 +81 -7
- package/src/codex/autostart-health.ts +4 -0
- package/src/codex/catalog/auto-review.ts +20 -3
- package/src/codex/catalog/build-entries.ts +19 -2
- package/src/codex/catalog/combo-member.ts +14 -5
- package/src/codex/catalog/configured-tiers.ts +50 -0
- package/src/codex/catalog/effort.ts +4 -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 +42 -19
- package/src/codex/catalog/model-visibility.ts +3 -1
- package/src/codex/catalog/native-ultrafast.ts +106 -0
- package/src/codex/catalog/parsing.ts +35 -86
- package/src/codex/catalog/provider-models.ts +40 -34
- package/src/codex/catalog/retained-sync.ts +2 -0
- package/src/codex/catalog/routed-gather.ts +33 -16
- package/src/codex/catalog/vendor-context.ts +82 -0
- 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 +63 -4
- package/src/codex/convergence.ts +2 -0
- package/src/codex/desktop-app/picker-freshness.ts +96 -0
- package/src/codex/desktop-app/types.ts +2 -0
- package/src/codex/desktop-app/windows.ts +29 -16
- package/src/codex/desktop-app-restart.ts +25 -2
- package/src/codex/desktop-compatibility/certificate-service.ts +99 -0
- package/src/codex/desktop-compatibility/certificate-store.ts +193 -0
- package/src/codex/desktop-compatibility/connection-store.ts +87 -0
- package/src/codex/desktop-compatibility/installed-build.ts +73 -0
- package/src/codex/desktop-compatibility/json-body.ts +29 -0
- package/src/codex/desktop-compatibility/native-identity.ts +62 -0
- package/src/codex/desktop-compatibility/relay-listener.ts +93 -0
- package/src/codex/desktop-compatibility/routing-binding.ts +10 -0
- package/src/codex/desktop-compatibility/routing-preflight.ts +69 -0
- package/src/codex/desktop-compatibility/runtime-ownership.ts +28 -0
- package/src/codex/desktop-compatibility/runtime.ts +182 -0
- package/src/codex/desktop-compatibility/service.ts +30 -0
- package/src/codex/desktop-compatibility/startup-settings.ts +50 -0
- package/src/codex/desktop-compatibility/usage-activation.ts +86 -0
- package/src/codex/desktop-compatibility/usage-controlled-fetch.ts +59 -0
- package/src/codex/desktop-compatibility/usage-controller.ts +107 -0
- package/src/codex/desktop-compatibility/usage-policy.ts +59 -0
- package/src/codex/desktop-compatibility/usage-refresh.ts +33 -0
- package/src/codex/desktop-compatibility/usage-sse-controller.ts +86 -0
- package/src/codex/desktop-compatibility/windows-activation-source.ts +44 -0
- package/src/codex/desktop-compatibility/windows-certificate-trust.ts +81 -0
- package/src/codex/desktop-compatibility/windows-key-protection.ts +165 -0
- package/src/codex/desktop-compatibility/windows-package-command.ts +86 -0
- package/src/codex/desktop-compatibility/windows-package-launch.ts +28 -0
- package/src/codex/features.ts +85 -45
- package/src/codex/history-provider.ts +1 -1
- package/src/codex/inject/config-write-section.ts +4 -1
- package/src/codex/inject/history-failure.ts +27 -0
- package/src/codex/inject/remove.ts +18 -6
- 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/journal.ts +16 -1
- package/src/codex/main-account-hard-lock.ts +30 -1
- package/src/codex/main-account.ts +99 -15
- package/src/codex/native-main-refresh-mode.ts +217 -0
- 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 +2 -2
- package/src/codex/routing/pool-recovery.ts +79 -0
- package/src/codex/routing/selection.ts +4 -3
- package/src/codex/routing/thread-affinity.ts +1 -1
- package/src/codex/shim-diagnostics.ts +6 -0
- package/src/codex/shim-overlay.ts +7 -2
- 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/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 +35 -7
- package/src/config/live-reconcile.ts +51 -2
- package/src/config/load-degrade.ts +23 -1
- package/src/config/opencode-wire-upgrade.ts +54 -0
- package/src/config/opencode-zen-upgrade.ts +52 -0
- package/src/config/owner-registry.ts +22 -17
- package/src/config/paths.ts +10 -3
- package/src/config/provider-validation.ts +45 -2
- package/src/config/schema/config-schema.ts +39 -0
- package/src/config/schema/desktop-compatibility.ts +9 -0
- package/src/config/schema/leaf-validators.ts +39 -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 +962 -350
- package/src/generated/model-metadata.ts +1 -1
- package/src/grok/sync.ts +1 -1
- package/src/images/loop.ts +46 -8
- package/src/integrations/catalog-refresh.ts +1 -1
- package/src/integrations/config-io.ts +20 -2
- package/src/integrations/journal.ts +15 -1
- package/src/integrations/mutation-plan.ts +2 -0
- package/src/integrations/registry.ts +15 -0
- package/src/integrations/store.ts +3 -0
- package/src/integrations/writer.ts +10 -1
- package/src/lib/advisor-activation.ts +16 -0
- package/src/lib/background-work.ts +65 -0
- package/src/lib/bounded-file-read.ts +58 -0
- package/src/lib/bun-path-runtime.d.mts +10 -1
- package/src/lib/bun-path-runtime.mjs +62 -3
- package/src/lib/codex-restart-contract.ts +15 -0
- package/src/lib/desktop-proxy-route.ts +30 -0
- package/src/lib/desktop-upstream-tunnel.ts +72 -0
- package/src/lib/empty-tool-catalog.ts +62 -0
- package/src/lib/errors.ts +26 -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/local-internal-call-capability.ts +55 -0
- package/src/lib/opaque-proxy-tunnel.ts +217 -0
- package/src/lib/package-tree-integrity.ts +2 -2
- package/src/lib/redact.ts +2 -2
- package/src/lib/socks5-fetch.ts +48 -71
- package/src/lib/socks5-handshake.ts +112 -0
- package/src/lib/translator-budget.ts +7 -1
- 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 +62 -12
- package/src/oauth/generic-session-affinity.ts +125 -0
- package/src/oauth/index.ts +188 -111
- package/src/oauth/kiro-device-login.ts +2 -1
- package/src/oauth/kiro.ts +7 -1
- 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/codecs/chat-ir.ts +467 -0
- package/src/protocols/codecs/chat.ts +10 -1
- package/src/protocols/codecs/messages-ir.ts +500 -0
- package/src/protocols/encoders/adapter-events.ts +5 -4
- package/src/protocols/encoders/messages.ts +9 -6
- package/src/protocols/features.ts +10 -2
- package/src/protocols/path.ts +11 -1
- package/src/protocols/plan-snapshot.ts +39 -16
- package/src/protocols/plan.ts +9 -1
- package/src/protocols/provider-summary.ts +2 -1
- package/src/protocols/settings.ts +8 -0
- package/src/providers/antigravity-account-roster.ts +102 -0
- package/src/providers/antigravity-models.ts +85 -7
- 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 +5 -0
- package/src/providers/model-rename-migration.ts +7 -5
- 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/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 +44 -14
- package/src/providers/registry/entries-extended.ts +19 -0
- 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 +78 -22
- package/src/responses/reasoning-envelope.ts +4 -0
- package/src/responses/reasoning-replay-cache.ts +24 -2
- 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/responses/state.ts +32 -29
- package/src/router.ts +8 -321
- package/src/routing/health.ts +37 -22
- package/src/routing/history/build-file.ts +92 -0
- package/src/routing/history/indexer.ts +254 -221
- package/src/routing/history/ingest.ts +242 -0
- package/src/routing/history/rebuild-job.ts +111 -0
- package/src/routing/history/rebuild-protocol.ts +15 -0
- package/src/routing/history/rebuild-worker.ts +34 -0
- package/src/routing/profile.ts +1 -1
- package/src/server/admission-model-scope.ts +21 -1
- package/src/server/antigravity-direct-eligibility.ts +208 -0
- package/src/server/auth-cors.ts +15 -0
- package/src/server/chat-completions.ts +82 -10
- 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 +164 -433
- package/src/server/effort-policy.ts +1 -1
- package/src/server/images.ts +15 -2
- package/src/server/index/desktop-compatibility-startup.ts +56 -0
- 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 +11 -3
- package/src/server/index/startup-warnings.ts +11 -0
- package/src/server/index/websocket-handler.ts +9 -0
- package/src/server/index.ts +14 -11
- package/src/server/inference/advisor-diagnostics.ts +31 -0
- package/src/server/inference/client-encoder-delivery.ts +6 -5
- package/src/server/login-shell-path.ts +146 -0
- package/src/server/management/advisor-routes.ts +202 -0
- package/src/server/management/agent-settings-routes.ts +22 -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 +4 -0
- package/src/server/management/config-routes.ts +77 -6
- package/src/server/management/context.ts +4 -0
- package/src/server/management/cursor-integration-routes.ts +1 -1
- package/src/server/management/desktop-compatibility-routes.ts +46 -0
- package/src/server/management/desktop-compatibility-runtime-routes.ts +46 -0
- package/src/server/management/desktop-compatibility-settings-routes.ts +27 -0
- package/src/server/management/model-routes.ts +13 -8
- 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/protocol-settings-patch.ts +1 -0
- 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 +21 -1
- package/src/server/management/sibling-guard.ts +1 -0
- package/src/server/management-api.ts +9 -1
- package/src/server/messages-antigravity-direct.ts +195 -0
- package/src/server/messages-native-tool-guard.ts +185 -0
- package/src/server/messages-native.ts +106 -22
- 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 +13 -1
- package/src/server/responses/account-change-state.ts +8 -2
- package/src/server/responses/adapter-continuation.ts +48 -19
- package/src/server/responses/adapter-delivery.ts +43 -8
- package/src/server/responses/adapter-dispatch.ts +48 -4
- package/src/server/responses/advisor-plan-slot.ts +27 -0
- package/src/server/responses/advisor-retention.ts +117 -0
- package/src/server/responses/advisor-slot.ts +368 -0
- package/src/server/responses/code-mode-collab-surface.ts +116 -8
- package/src/server/responses/codex-ws-wire.ts +15 -8
- package/src/server/responses/compact.ts +303 -125
- package/src/server/responses/compaction-recovery.ts +18 -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 +12 -1
- package/src/server/responses/core-combo.ts +141 -36
- package/src/server/responses/core-errors.ts +3 -3
- package/src/server/responses/core-lifetime.ts +7 -2
- package/src/server/responses/core-normalize.ts +11 -0
- package/src/server/responses/core-opaque-recovery.ts +35 -0
- package/src/server/responses/core-options.ts +51 -0
- package/src/server/responses/core-pipeline.ts +141 -0
- package/src/server/responses/core-replay.ts +25 -6
- package/src/server/responses/core.ts +3 -116
- 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 +19 -11
- package/src/server/responses/passthrough-dispatch.ts +29 -16
- package/src/server/responses/request-prepare.ts +144 -17
- package/src/server/responses/request-sidecar-auth.ts +2 -2
- package/src/server/responses/request-transport.ts +120 -27
- package/src/server/responses/response-effects.ts +1 -0
- package/src/server/responses/run-turn-execution.ts +166 -38
- package/src/server/responses/sidecar-execution.ts +98 -5
- package/src/server/responses/terminal-guard.ts +4 -17
- package/src/server/responses-undeclared-tool-guard.ts +30 -9
- package/src/server/startup-action-control.ts +16 -2
- package/src/server/startup-health-cache.ts +1 -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/desktop-startup.ts +14 -0
- package/src/service/guards.ts +1 -61
- package/src/service/health-sentinel-linux.ts +112 -0
- package/src/service/health-sentinel-main.ts +99 -61
- package/src/service/health-sentinel-probe.ts +24 -7
- package/src/service/health.ts +5 -89
- package/src/service/launchd.ts +27 -7
- package/src/service/logging.ts +135 -0
- 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/tray/windows-tray.ps1 +43 -24
- package/src/types/config.ts +124 -6
- package/src/types/opencode-go.ts +61 -0
- package/src/types/opencode-zen.ts +29 -0
- package/src/types/provider.ts +39 -6
- package/src/types/request.ts +38 -2
- package/src/types/tools.ts +2 -0
- package/src/types/wire.ts +29 -37
- package/src/types.ts +1 -0
- package/src/update/async-check.ts +1 -1
- package/src/update/badge.ts +2 -2
- package/src/update/index.ts +88 -15
- package/src/update/job-supervised-restart.ts +107 -0
- package/src/update/job.ts +32 -32
- package/src/update/notify.ts +1 -1
- package/src/update/npm-invocation.mjs +12 -2
- package/src/update/refresh-scheduler.ts +2 -2
- package/src/update/supervised-recovery.d.mts +27 -0
- package/src/update/supervised-recovery.mjs +157 -0
- package/src/usage/cache-diagnostic.ts +2 -0
- package/src/usage/cost.ts +48 -12
- package/src/usage/expected-prices.ts +15 -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 +22 -9
- 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/gemini-executor.ts +2 -2
- package/src/web-search/loop.ts +55 -5
- package/src/web-search/progress-stream.ts +4 -1
- package/src/web-search/run-turn-loop.ts +9 -1
- package/assets/sponsors/packycode.png +0 -0
- package/gui/dist/assets/App-CSJvmjNs.css +0 -1
- package/gui/dist/assets/App-CZtqiGcw.js +0 -56
- package/gui/dist/assets/index-BB6uK6tU.css +0 -1
- package/gui/dist/assets/index-CTm4l-HQ.js +0 -94
- package/gui/dist/assets/quota-summary-BbEeRfPY.js +0 -1
|
@@ -61,7 +61,9 @@ import {
|
|
|
61
61
|
type UpstreamSendRecovery,
|
|
62
62
|
UPSTREAM_RESET_REPLAY_REFUSED_CODE,
|
|
63
63
|
} from "../lib/upstream-retry";
|
|
64
|
+
import { distributedKeyPhysicalFetch, distributedKeyResponseOwner, recordDistributedResponseFailure } from "../providers/api-key-response-ownership";
|
|
64
65
|
import { providerApiKeySelectionIsCurrent, resolveCurrentProviderApiKeyTransport } from "../providers/api-key-selection";
|
|
66
|
+
import { RequestPacingQueueOverloadError } from "../providers/request-pacing";
|
|
65
67
|
import {
|
|
66
68
|
hasKeyPoolFailover,
|
|
67
69
|
rateLimitRetryDelayMs,
|
|
@@ -82,6 +84,7 @@ import { preservesPhysicalComboProvider, resolveComboId } from "../combos";
|
|
|
82
84
|
import { captureRouteStaticPolicy, routedProviderConfig, routeModel, type RouteResult } from "../router";
|
|
83
85
|
import { POLICY_NAMESPACE, resolvePolicyProfileId } from "../routing/profile";
|
|
84
86
|
import type { AnthropicClientIdentity } from "../adapters/anthropic/client-identity";
|
|
87
|
+
import { logDroppedAnthropicBetas } from "../adapters/anthropic/beta-allowlist";
|
|
85
88
|
import type { OcxConfig, OcxProviderConfig, OcxUsage } from "../types";
|
|
86
89
|
import { resolveWireProtocolOverride } from "./adapter-resolve";
|
|
87
90
|
import {
|
|
@@ -90,12 +93,14 @@ import {
|
|
|
90
93
|
resolvePassthroughBodyGuard,
|
|
91
94
|
sanitizePassthroughToolCallIds,
|
|
92
95
|
tapAnthropicSseForLog,
|
|
93
|
-
} from "./
|
|
96
|
+
} from "./messages-shared";
|
|
94
97
|
import { beginInferenceAttempt } from "./inference/attempt";
|
|
95
98
|
import { createFinalRequestLog, type FinalRequestLogMeta } from "./inference/final-log";
|
|
96
99
|
import { registerTurn, unregisterTurn } from "./lifecycle";
|
|
97
100
|
import { nativeMessagesDeclineReason, type NativeMessagesSelector } from "./messages-native-eligibility";
|
|
98
101
|
import { messagesSecondaryInstanceUnavailable } from "./messages-native-selector";
|
|
102
|
+
import { guardNativeMessagesEmptyToolCatalog, nativeMessagesClientToolName, nativeMessagesInlineToolNames } from "./messages-native-tool-guard";
|
|
103
|
+
import { UNDECLARED_TOOL_CALL_ERROR_CODE, undeclaredToolCallMessage } from "./responses-undeclared-tool-guard";
|
|
99
104
|
import {
|
|
100
105
|
nativeOAuthBindingIsCurrent,
|
|
101
106
|
NativeOAuthSelectionChangedError,
|
|
@@ -314,6 +319,8 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
314
319
|
const { req, config, logCtx, logIds, route, body, requestedModel, translatorBudget } = options;
|
|
315
320
|
const nativeInstance = configuredAnthropicInstance(config, route.providerName);
|
|
316
321
|
const requestedStream = body.stream === true;
|
|
322
|
+
const clientDeclaredEmptyToolCatalog = Array.isArray(body.tools) && body.tools.length === 0;
|
|
323
|
+
const declaredInlineTools = clientDeclaredEmptyToolCatalog ? nativeMessagesInlineToolNames(body) : undefined;
|
|
317
324
|
logCtx.inboundProtocol = "messages";
|
|
318
325
|
logCtx.model = route.modelId;
|
|
319
326
|
logCtx.provider = route.providerName;
|
|
@@ -435,8 +442,16 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
435
442
|
}
|
|
436
443
|
} else {
|
|
437
444
|
// Same pre-dispatch key preference every direct send path applies (see chat-native.ts).
|
|
438
|
-
|
|
439
|
-
|
|
445
|
+
try {
|
|
446
|
+
const proactiveKeyProvider = selectProactiveApiKeyTransport(config, route.providerName, route.provider);
|
|
447
|
+
if (proactiveKeyProvider) route.provider = proactiveKeyProvider;
|
|
448
|
+
} catch (error) {
|
|
449
|
+
cleanupAbort(); upstream.abort();
|
|
450
|
+
if (!(error instanceof RequestPacingQueueOverloadError)) throw error;
|
|
451
|
+
const refusal = fail(429, error.message, "rate_limit_error");
|
|
452
|
+
refusal.headers.set("Retry-After", String(error.retryAfterSeconds));
|
|
453
|
+
return refusal;
|
|
454
|
+
}
|
|
440
455
|
}
|
|
441
456
|
let activeProvider: OcxProviderConfig = oauthBinding ? oauthProvider(oauthBinding) : route.provider;
|
|
442
457
|
stampApiKeyAccountLabel(logCtx, route.providerName, activeProvider);
|
|
@@ -469,7 +484,10 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
469
484
|
clientIdentity: options.clientIdentity,
|
|
470
485
|
});
|
|
471
486
|
if (built.strippedOpaqueState && rejectUnrepresentable) throw new NativeOpaqueStateRefusal();
|
|
472
|
-
if (built.droppedBetas)
|
|
487
|
+
if (built.droppedBetas) {
|
|
488
|
+
addProtocolEntryReason(logCtx, "anthropic-beta-dropped");
|
|
489
|
+
logDroppedAnthropicBetas({ droppedNames: built.droppedBetaNames, droppedUnrecognized: built.droppedUnrecognizedBetas });
|
|
490
|
+
}
|
|
473
491
|
if (built.strippedOpaqueState) addProtocolEntryReason(logCtx, "opaque-state-stripped");
|
|
474
492
|
return built;
|
|
475
493
|
};
|
|
@@ -517,6 +535,15 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
517
535
|
&& nativeMessagesDeclineReason({ ...route, provider: routed }, body, config, selector) === undefined;
|
|
518
536
|
};
|
|
519
537
|
|
|
538
|
+
// Keep the actual failed wire identity if a later recovery is refused before sending.
|
|
539
|
+
// A 429 remains eligible for explicit same-key retries until that ladder is finished.
|
|
540
|
+
let pendingDistributedFailure: (() => void) | undefined;
|
|
541
|
+
let distributedResponseOwnsKey = true;
|
|
542
|
+
const settleDistributedFailure = () => {
|
|
543
|
+
const record = pendingDistributedFailure;
|
|
544
|
+
pendingDistributedFailure = undefined;
|
|
545
|
+
record?.();
|
|
546
|
+
};
|
|
520
547
|
const send = async (recovery?: "rate-limit-429" | "oauth-401" | "oauth-account-403" | "key-429" | "key-401"): Promise<Response> => {
|
|
521
548
|
const remaining = remainingTransientSends();
|
|
522
549
|
if (requestTransientPolicy && remaining <= 0) {
|
|
@@ -534,7 +561,7 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
534
561
|
providerFetch(activeProvider, undefined, {
|
|
535
562
|
providerName: route.providerName,
|
|
536
563
|
modelId: route.modelId,
|
|
537
|
-
dispatchOverride: async (_input, init, execute) => {
|
|
564
|
+
dispatchOverride: async (_input, init, execute, reacquirePacing) => {
|
|
538
565
|
if (oauthBinding) {
|
|
539
566
|
if (!nativeOAuthRouteIsCurrent(oauthBinding)) throw new NativeOAuthSelectionChangedError();
|
|
540
567
|
// The OAuth twin of the key check below: re-resolve through the same selection
|
|
@@ -551,12 +578,25 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
551
578
|
rebuildFor(oauthProvider(oauthBinding));
|
|
552
579
|
logCtx.provider = formatAnthropicProviderForLog(route.providerName, oauthBinding.snapshot.accountId, config);
|
|
553
580
|
}
|
|
554
|
-
} else
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
581
|
+
} else {
|
|
582
|
+
for (let attempt = 0; !providerApiKeySelectionIsCurrent(config, route.providerName, activeProvider); attempt++) {
|
|
583
|
+
if (attempt >= 3) throw new Error("Provider key selection changed repeatedly before native Messages dispatch");
|
|
584
|
+
let current = resolveCurrentProviderApiKeyTransport(config, route.providerName, activeProvider);
|
|
585
|
+
if (!current && activeProvider.requestPacing?.enabled
|
|
586
|
+
&& (activeProvider.requestPacing.keys || activeProvider.requestPacing.keySelection === "round-robin")) {
|
|
587
|
+
const fresh = resolveCurrentProviderApiKeyTransport(config, route.providerName, { ...activeProvider, _apiKeyAttempt: undefined });
|
|
588
|
+
if (fresh) current = selectProactiveApiKeyTransport(config, route.providerName, fresh) ?? fresh;
|
|
589
|
+
}
|
|
590
|
+
if (!current || nativeMessagesDeclineReason({ ...route, provider: current }, body, config, selector) !== undefined) {
|
|
591
|
+
throw new Error("Provider key selection is no longer available for native Messages");
|
|
592
|
+
}
|
|
593
|
+
rebuildFor(current);
|
|
594
|
+
if (current.requestPacing?.enabled
|
|
595
|
+
&& (current.requestPacing.keys || current.requestPacing.keySelection === "round-robin")) {
|
|
596
|
+
if (!reacquirePacing) throw new Error("Refreshed native Messages dispatch requires pacing readmission");
|
|
597
|
+
await reacquirePacing(current, route.modelId);
|
|
598
|
+
}
|
|
558
599
|
}
|
|
559
|
-
rebuildFor(current);
|
|
560
600
|
}
|
|
561
601
|
// The retry closure may hold a pre-reselection request: send the current one whole.
|
|
562
602
|
const wire = activeRequest;
|
|
@@ -575,6 +615,7 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
575
615
|
}
|
|
576
616
|
const releaseFamily = snapshot && oauthBinding ? anthropicModelQuotaFor(oauthBinding.instance).claimAnthropicFamilyRevalidation(snapshot.accountId, route.modelId) : () => {};
|
|
577
617
|
if (!releaseFamily) throw new AnthropicAccountCooldownError(1);
|
|
618
|
+
const selection = activeProvider._apiKeyAttempt;
|
|
578
619
|
let dispatched: Response;
|
|
579
620
|
const spendReport = createPhysicalSendReporter(physicalBudget, () => ({
|
|
580
621
|
poolId: logCtx.spendPoolId ?? route.providerName, identityId: logCtx.accountLogLabel,
|
|
@@ -595,7 +636,9 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
595
636
|
if (snapshot && !sendOwner) throw new NativeOAuthSelectionChangedError();
|
|
596
637
|
physicalSendsUsed++;
|
|
597
638
|
dispatched = await sendWithConnectionPolicy(
|
|
598
|
-
|
|
639
|
+
distributedKeyPhysicalFetch(
|
|
640
|
+
anthropicBillingPhysicalFetch((activeProvider as OcxProviderTransport).fetch ?? execute, route.providerName, activeProvider),
|
|
641
|
+
route.providerName, activeProvider, wire.url, activeProvider.apiKeyTransport === "bearer" ? "authorization" : "x-api-key"),
|
|
599
642
|
wire.url,
|
|
600
643
|
applyUpstreamRecoveryInit({ ...init, method: "POST", headers, body: wire.body }, transportRecovery),
|
|
601
644
|
{ providerName: route.providerName, provider: activeProvider },
|
|
@@ -619,6 +662,14 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
619
662
|
}
|
|
620
663
|
} catch { /* Passive observation must not fail the response. */ }
|
|
621
664
|
}
|
|
665
|
+
const ownsDistributedKey = !selection?.distributed
|
|
666
|
+
|| distributedKeyResponseOwner(dispatched, config, route.providerName) !== null;
|
|
667
|
+
distributedResponseOwnsKey = ownsDistributedKey;
|
|
668
|
+
const failureStatus = dispatched.status;
|
|
669
|
+
pendingDistributedFailure = selection?.distributed && ownsDistributedKey && (failureStatus === 401 || failureStatus === 429)
|
|
670
|
+
&& !isNonReplayableResponse(dispatched)
|
|
671
|
+
? () => { recordDistributedResponseFailure(dispatched, config, route.providerName, req.signal); }
|
|
672
|
+
: undefined;
|
|
622
673
|
if (!dispatched.ok) await recordKeyAttemptFailure(logCtx, dispatched, init.signal ?? upstream.signal);
|
|
623
674
|
return dispatched;
|
|
624
675
|
},
|
|
@@ -643,25 +694,28 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
643
694
|
let response: Response;
|
|
644
695
|
try {
|
|
645
696
|
response = await send();
|
|
646
|
-
|
|
697
|
+
let retryPolicy: ReturnType<typeof rateLimitRetryPolicyFor> | undefined;
|
|
647
698
|
let retries = 0;
|
|
648
699
|
let billingRecoveryActive = false;
|
|
649
700
|
const keySendAvailable = () => transientSendAvailable()
|
|
650
701
|
&& (!billingRecoveryActive || Math.max(physicalSendsUsed, physicalBudget.used) < physicalBudget.policy.maxTotalModelSends);
|
|
651
|
-
|
|
702
|
+
const recoveryPasses = activeProvider._apiKeyAttempt?.distributed ? activeProvider.apiKeyPool?.length ?? 1 : 1;
|
|
703
|
+
for (let pass = 0; ; pass++) {
|
|
652
704
|
const priorResponse = response;
|
|
653
705
|
// A credential-scoped 401 on a static key pool says nothing about the sibling keys.
|
|
654
|
-
while (response.status === 401 && hasKeyPoolFailover(activeProvider) && keySendAvailable()) {
|
|
706
|
+
while (response.status === 401 && distributedResponseOwnsKey && hasKeyPoolFailover(activeProvider) && keySendAvailable()) {
|
|
655
707
|
const rotated = rotateProviderTransportOn401(config, route.providerName, activeProvider, {
|
|
656
708
|
now: Date.now(),
|
|
657
709
|
attemptedKey: activeProvider.apiKey,
|
|
710
|
+
attemptedSelection: activeProvider._apiKeyAttempt,
|
|
658
711
|
});
|
|
712
|
+
pendingDistributedFailure = undefined; // Rotation already records this physical failure.
|
|
659
713
|
if (!rotated) break;
|
|
660
714
|
discard(response);
|
|
661
715
|
rebuildFor(rotated);
|
|
662
716
|
response = await send("key-401");
|
|
663
717
|
}
|
|
664
|
-
while ((response.status === 400 || response.status === 402) && hasKeyPoolFailover(activeProvider)) {
|
|
718
|
+
while ((response.status === 400 || response.status === 402) && distributedResponseOwnsKey && hasKeyPoolFailover(activeProvider)) {
|
|
665
719
|
const rotated = await rotateAnthropicBillingKeyOnResponse(response, config, route.providerName, activeProvider, { signal: upstream.signal });
|
|
666
720
|
if (!rotated) break;
|
|
667
721
|
billingRecoveryActive = true;
|
|
@@ -670,9 +724,11 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
670
724
|
rebuildFor(rotated);
|
|
671
725
|
response = await send("key-401");
|
|
672
726
|
}
|
|
727
|
+
if (pass === 0) retryPolicy = oauthBinding ? undefined : rateLimitRetryPolicyFor(activeProvider);
|
|
673
728
|
// A refusal this proxy synthesized for a reset replay is not a provider rate limit.
|
|
674
729
|
while (
|
|
675
730
|
response.status === 429
|
|
731
|
+
&& distributedResponseOwnsKey
|
|
676
732
|
&& !isNonReplayableResponse(response)
|
|
677
733
|
&& retryPolicy
|
|
678
734
|
&& retries < retryPolicy.attempts
|
|
@@ -687,13 +743,14 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
687
743
|
if (upstream.signal.aborted) throw upstream.signal.reason;
|
|
688
744
|
response = await send("rate-limit-429");
|
|
689
745
|
}
|
|
690
|
-
while (response.status === 429 && !isNonReplayableResponse(response) && hasKeyPoolFailover(activeProvider)) {
|
|
746
|
+
while (response.status === 429 && distributedResponseOwnsKey && !isNonReplayableResponse(response) && hasKeyPoolFailover(activeProvider)) {
|
|
691
747
|
const rotated = rotateProviderTransportOn429(config, route.providerName, activeProvider, {
|
|
692
748
|
retryAfter: response.headers.get("retry-after"),
|
|
693
749
|
now: Date.now(),
|
|
694
750
|
attemptedKey: activeProvider.apiKey,
|
|
695
751
|
attemptedSelection: activeProvider._apiKeyAttempt,
|
|
696
752
|
});
|
|
753
|
+
pendingDistributedFailure = undefined; // Rotation already records this physical failure.
|
|
697
754
|
if (!rotated) break;
|
|
698
755
|
// Rotation already recorded the cooldown; keep the terminal 429 when no send remains.
|
|
699
756
|
if (!keySendAvailable()) break;
|
|
@@ -701,13 +758,17 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
701
758
|
rebuildFor(rotated);
|
|
702
759
|
response = await send("key-429");
|
|
703
760
|
}
|
|
704
|
-
|
|
705
|
-
|
|
761
|
+
if (response === priorResponse || isNonReplayableResponse(response) || !keySendAvailable()) break;
|
|
762
|
+
// Billing class transitions share the physical-send ceiling; distributed-only
|
|
763
|
+
// transitions additionally retain their original bounded pool-pass allowance.
|
|
764
|
+
if (distributedResponseOwnsKey && (
|
|
706
765
|
(billingRecoveryActive && [401, 429].includes(response.status))
|
|
707
766
|
|| (activeProvider.adapter === "anthropic" && hasKeyPoolFailover(activeProvider) && [400, 402].includes(response.status))
|
|
708
767
|
)) continue;
|
|
709
|
-
|
|
768
|
+
if (!activeProvider._apiKeyAttempt?.distributed || !distributedResponseOwnsKey
|
|
769
|
+
|| (response.status !== 401 && response.status !== 429) || pass + 1 >= recoveryPasses) break;
|
|
710
770
|
}
|
|
771
|
+
settleDistributedFailure();
|
|
711
772
|
const oauthRetryKey = {};
|
|
712
773
|
const triedAccountIds = new Set<string>();
|
|
713
774
|
let oauthFailovers = 0;
|
|
@@ -745,7 +806,13 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
745
806
|
cleanupAbort();
|
|
746
807
|
upstream.abort();
|
|
747
808
|
if (req.signal.aborted) return fail(499, "Client cancelled request", "api_error");
|
|
809
|
+
settleDistributedFailure();
|
|
748
810
|
const sendError = error instanceof UpstreamRetryEvidenceError ? error.cause : error;
|
|
811
|
+
if (sendError instanceof RequestPacingQueueOverloadError) {
|
|
812
|
+
const refusal = fail(429, sendError.message, "rate_limit_error");
|
|
813
|
+
refusal.headers.set("Retry-After", String(sendError.retryAfterSeconds));
|
|
814
|
+
return refusal;
|
|
815
|
+
}
|
|
749
816
|
if (sendError instanceof SendBudgetExhaustedError) return fail(429, sendError.message, "send_budget_exhausted", "send_budget_exhausted");
|
|
750
817
|
if (sendError instanceof NativeMessagesSpendRefusal) {
|
|
751
818
|
const refusal = workflowRefusalResponse("workflow-spend-exhausted", logCtx);
|
|
@@ -790,15 +857,22 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
790
857
|
const renamed = activeRequest.oauthToolNames
|
|
791
858
|
? restoreOAuthToolNamesInSse(observed, activeRequest.oauthToolNames, translatorBudget)
|
|
792
859
|
: observed;
|
|
793
|
-
const
|
|
860
|
+
const echoed = echoRequestedModel(renamed, requestedModel);
|
|
861
|
+
let toolRefusal: string | undefined;
|
|
862
|
+
const source = clientDeclaredEmptyToolCatalog
|
|
863
|
+
? guardNativeMessagesEmptyToolCatalog(echoed, translatorBudget, message => {
|
|
864
|
+
toolRefusal = message;
|
|
865
|
+
logCtx.errorCode = UNDECLARED_TOOL_CALL_ERROR_CODE;
|
|
866
|
+
}, declaredInlineTools)
|
|
867
|
+
: echoed;
|
|
794
868
|
if (requestedStream) {
|
|
795
869
|
transferTurnToStream();
|
|
796
870
|
const relayed = tapAnthropicSseForLog(source, logCtx, (status, meta) => {
|
|
797
871
|
try {
|
|
798
872
|
cleanupAbort();
|
|
799
873
|
bindUsage(logCtx.usage);
|
|
800
|
-
finishLog(status,
|
|
801
|
-
if (meta.closeReason !== "terminal") upstream.abort();
|
|
874
|
+
finishLog(toolRefusal ? 502 : status, toolRefusal, toolRefusal ? { ...meta, terminalStatus: "failed" } : meta);
|
|
875
|
+
if (toolRefusal || meta.closeReason !== "terminal") upstream.abort();
|
|
802
876
|
} finally {
|
|
803
877
|
releaseStreamTurn();
|
|
804
878
|
}
|
|
@@ -829,6 +903,11 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
829
903
|
if (message.type === "error") {
|
|
830
904
|
const error = isRec(message.error) ? message.error : {};
|
|
831
905
|
const text = typeof error.message === "string" ? error.message : "upstream stream failed";
|
|
906
|
+
if (toolRefusal) {
|
|
907
|
+
upstream.abort();
|
|
908
|
+
finishLog(502, toolRefusal, { closeReason: "terminal", terminalStatus: "failed" });
|
|
909
|
+
return fail(502, toolRefusal, "api_error", UNDECLARED_TOOL_CALL_ERROR_CODE);
|
|
910
|
+
}
|
|
832
911
|
// The tap's own verdict (a reset, a stall, the byte cap) closes this row with the same meta
|
|
833
912
|
// as the streaming lane's row; a plain upstream error event keeps the non_stream row.
|
|
834
913
|
const tapMeta = tapState.meta;
|
|
@@ -880,6 +959,11 @@ export async function handleNativeMessages(options: HandleNativeMessagesOptions)
|
|
|
880
959
|
const message = activeRequest.oauthToolNames
|
|
881
960
|
? restoreOAuthToolNamesInMessage(parsedMessage, activeRequest.oauthToolNames)
|
|
882
961
|
: parsedMessage;
|
|
962
|
+
const undeclaredTool = clientDeclaredEmptyToolCatalog ? nativeMessagesClientToolName(message, declaredInlineTools) : undefined;
|
|
963
|
+
if (undeclaredTool !== undefined) {
|
|
964
|
+
logCtx.errorCode = UNDECLARED_TOOL_CALL_ERROR_CODE;
|
|
965
|
+
return fail(502, undeclaredToolCallMessage(undeclaredTool), "api_error", UNDECLARED_TOOL_CALL_ERROR_CODE);
|
|
966
|
+
}
|
|
883
967
|
bindUsage(anthropicUsageToOcx(isRec(message.usage) ? message.usage : undefined));
|
|
884
968
|
if (logIds) recordFirstOutput(logCtx, logIds.start);
|
|
885
969
|
try {
|