@bitkyc08/opencodex 2.80.0 → 2.82.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 +3 -3
- package/bin/ocx.mjs +166 -73
- package/gui/dist/assets/App-Ds_qL7o8.js +54 -0
- package/gui/dist/assets/Tray-BqHF5Trd.js +1 -0
- package/gui/dist/assets/{index-Brk6F3fn.css → index-BAbcj51J.css} +1 -1
- package/gui/dist/assets/index-D3FBCNiP.js +94 -0
- package/gui/dist/assets/quota-summary-DTBC8n7-.js +1 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/claude-green.svg +1 -0
- package/package.json +3 -2
- package/src/adapters/anthropic-model-contract.ts +8 -2
- package/src/adapters/anthropic.ts +8 -3
- package/src/adapters/codebuddy/mcp-server.ts +2 -25
- package/src/adapters/codebuddy/tool-bridge.ts +1 -7
- package/src/adapters/coding-agent/mcp-server.ts +33 -0
- package/src/adapters/coding-agent/protocol.ts +122 -17
- package/src/adapters/coding-agent/tool-catalog.ts +75 -0
- package/src/adapters/coding-agent/turn.ts +101 -44
- package/src/adapters/cursor/catalog.ts +8 -0
- package/src/adapters/cursor/effort-map.ts +2 -0
- package/src/adapters/devin/live-models.ts +2 -0
- package/src/adapters/kiro-retry.ts +9 -4
- package/src/adapters/openai-chat/messages.ts +7 -6
- package/src/adapters/openai-responses/compaction-search-history.ts +109 -0
- package/src/adapters/openai-responses/passthrough.ts +9 -4
- package/src/adapters/openai-responses/tool-output-recovery.ts +20 -0
- package/src/adapters/physical-send.ts +8 -5
- package/src/adapters/qoder/adapter.ts +41 -6
- package/src/adapters/qoder/scaffold-guard.ts +2 -3
- package/src/adapters/zed.ts +16 -1
- package/src/claude/agents-inject.ts +14 -3
- package/src/claude/context-windows.ts +19 -17
- package/src/claude/desktop-3p.ts +88 -12
- package/src/claude/desktop-profile.ts +2 -1
- package/src/claude/gateway-cache.ts +18 -1
- package/src/claude/inbound-cache-stabilize.ts +4 -9
- package/src/claude/inbound.ts +78 -3
- package/src/claude/intercept/cli-catalog.ts +3 -0
- package/src/claude/intercept/model-bindings.ts +1 -0
- package/src/claude/intercept/picker-ca-persistence.ts +7 -6
- package/src/claude/intercept/picker-listener.ts +71 -4
- package/src/claude/intercept/picker-models.ts +14 -6
- package/src/claude/intercept/settings.ts +3 -0
- package/src/claude/long-context.ts +66 -0
- package/src/claude/model-info.ts +19 -16
- package/src/claude/outbound.ts +94 -9
- package/src/claude/subagent-model.ts +40 -11
- package/src/cli/account-anthropic-threshold.ts +14 -5
- package/src/cli/account-api.ts +3 -1
- package/src/cli/account-extended.ts +13 -9
- package/src/cli/account-policy-dto.ts +1 -1
- package/src/cli/account-policy.ts +13 -4
- package/src/cli/account.ts +3 -3
- package/src/cli/agent.ts +9 -5
- package/src/cli/aside-profile-recovery.ts +33 -0
- package/src/cli/capabilities-accounts.ts +2 -2
- package/src/cli/capabilities-agents-routing.ts +24 -0
- package/src/cli/capabilities-base.ts +5 -5
- package/src/cli/capabilities-integrations.ts +18 -2
- package/src/cli/cli-path-diagnostics.ts +132 -0
- package/src/cli/codex-shim-autorestore.ts +3 -0
- package/src/cli/desktop-runtime-guidance.ts +65 -0
- package/src/cli/dispatch.ts +15 -1
- package/src/cli/doctor.ts +16 -3
- package/src/cli/help.ts +4 -1
- package/src/cli/index.ts +25 -14
- package/src/cli/integration-aside-sync.ts +2 -1
- package/src/cli/integration-plan-dto.ts +1 -0
- package/src/cli/integration-preview.ts +8 -1
- package/src/cli/integrations.ts +48 -6
- package/src/cli/message-args.ts +34 -0
- package/src/cli/message-command.ts +43 -0
- package/src/cli/message-runtime.ts +6 -0
- package/src/cli/observe.ts +3 -1
- package/src/cli/provider.ts +29 -6
- package/src/cli/registry.ts +24 -2
- package/src/cli/resolve.ts +25 -2
- package/src/cli/root.ts +4 -2
- package/src/cli/status.ts +64 -12
- package/src/cli/update-restart-child.ts +4 -2
- package/src/cli/update-restart-home.ts +28 -10
- package/src/cli/update-restart-service-record.ts +116 -0
- package/src/cli/update-restart-supervision.ts +96 -0
- package/src/cli/update-restart.ts +59 -13
- package/src/cli/v2.ts +27 -20
- package/src/cli/version-skew-notice.ts +77 -0
- package/src/clients/config-export/commandcode.ts +131 -0
- package/src/clients/config-export/contracts.ts +12 -0
- package/src/clients/config-export.ts +64 -1
- package/src/clients/lazycodex.ts +1 -1
- package/src/clients/omo-role-models.ts +32 -7
- package/src/codex/auth-api/account-list.ts +11 -3
- package/src/codex/auth-api/account-selection.ts +107 -0
- package/src/codex/auth-api/main-account-probe.ts +25 -8
- package/src/codex/auth-api/pool-mode-gate.ts +33 -9
- package/src/codex/auth-api/pool-quota-probe.ts +15 -1
- package/src/codex/auth-api/routes.ts +11 -49
- package/src/codex/auth-context.ts +20 -1
- package/src/codex/autostart-health.ts +12 -3
- package/src/codex/catalog/auto-review.ts +13 -6
- package/src/codex/catalog/build-entries.ts +33 -7
- package/src/codex/catalog/bundled.ts +155 -26
- package/src/codex/catalog/combo-member.ts +3 -2
- package/src/codex/catalog/control-plane.ts +45 -0
- package/src/codex/catalog/effort.ts +37 -6
- package/src/codex/catalog/gather-capture.ts +10 -3
- package/src/codex/catalog/model-hints.ts +15 -8
- package/src/codex/catalog/model-visibility.ts +3 -1
- package/src/codex/catalog/operator-tiers.ts +38 -0
- package/src/codex/catalog/parsing.ts +2 -1
- package/src/codex/catalog/provider-models.ts +58 -44
- package/src/codex/catalog/retained-sync.ts +7 -5
- package/src/codex/catalog/routed-gather.ts +15 -1
- package/src/codex/catalog-auto-refresh-sources.ts +3 -4
- package/src/codex/catalog-auto-refresh.ts +19 -0
- package/src/codex/catalog.ts +1 -1
- package/src/codex/codex-home-owner.ts +3 -0
- package/src/codex/config-write-lock.ts +333 -0
- package/src/codex/control-plane-models.ts +6 -0
- package/src/codex/convergence.ts +2 -1
- package/src/codex/features.ts +257 -200
- package/src/codex/inject/config-write-section.ts +34 -0
- package/src/codex/inject/multi-agent-v2.ts +14 -6
- package/src/codex/inject/remove.ts +36 -11
- package/src/codex/inject/restore.ts +85 -20
- package/src/codex/inject-coordination.ts +15 -6
- package/src/codex/inject.ts +62 -20
- package/src/codex/journal.ts +62 -17
- package/src/codex/main-account-cache.ts +43 -0
- package/src/codex/paths.ts +2 -0
- package/src/codex/prepared-home.ts +18 -0
- package/src/codex/prompt-journal.ts +25 -12
- package/src/codex/prompt-layers.ts +49 -26
- package/src/codex/prompt-lock-claim.ts +134 -0
- package/src/codex/prompt-lock-evidence.ts +26 -0
- package/src/codex/prompt-lock-io.ts +16 -0
- package/src/codex/prompt-lock-owner.ts +130 -0
- package/src/codex/prompt-lock.ts +84 -53
- package/src/codex/routing/failure-window.ts +146 -0
- package/src/codex/routing/selection.ts +4 -1
- package/src/codex/routing.ts +13 -17
- package/src/codex/runtime.ts +106 -18
- package/src/codex/shim.ts +45 -19
- package/src/combos/jev-decision-contract.ts +25 -2
- package/src/combos/jev-service-exchange.ts +281 -0
- package/src/combos/jev.ts +34 -219
- package/src/combos/types.ts +1 -1
- package/src/config/atomic-write.ts +1 -1
- package/src/config/codex-ws-reuse-setting.ts +10 -0
- package/src/config/diagnostics.ts +27 -16
- package/src/config/live-reconcile.ts +17 -0
- package/src/config/load-degrade.ts +42 -0
- package/src/config/rebase-provenance.ts +11 -0
- package/src/config/schema/anthropic-account-pool.ts +143 -0
- package/src/config/schema/config-schema.ts +11 -1
- package/src/config/schema/leaf-validators.ts +4 -0
- package/src/config.ts +2 -0
- package/src/generated/compatibility-version.json +566 -298
- package/src/generated/model-metadata.ts +7 -6
- package/src/grok/inject.ts +50 -4
- package/src/grok/sync.ts +2 -1
- package/src/images/loop.ts +30 -11
- package/src/integrations/aside-profiles.ts +10 -3
- package/src/integrations/catalog-refresh.ts +19 -3
- package/src/integrations/mutation-plan.ts +7 -0
- package/src/integrations/registry.ts +8 -0
- package/src/integrations/state.ts +9 -2
- package/src/integrations/writer.ts +17 -5
- package/src/lib/bun-path-runtime.d.mts +32 -0
- package/src/lib/bun-path-runtime.mjs +95 -0
- package/src/lib/bun-runtime-preflight.ts +140 -0
- package/src/lib/desktop-cli-handoff.d.mts +20 -0
- package/src/lib/desktop-cli-handoff.mjs +92 -0
- package/src/lib/desktop-cli-record.d.mts +29 -0
- package/src/lib/desktop-cli-record.mjs +102 -0
- package/src/lib/lab-live-route-production.ts +9 -1
- package/src/lib/request-execution-budget.ts +244 -58
- package/src/lib/spend-pool-alias-validation.ts +79 -0
- package/src/lib/spend-pool-continuity.ts +34 -0
- package/src/lib/spend-reservation-ledger.ts +412 -50
- package/src/lib/state-store-registrations.ts +20 -3
- package/src/lib/synced-state-location.ts +46 -6
- package/src/lib/test-home-guard.ts +87 -1
- package/src/lib/translator-budget.ts +17 -4
- package/src/lib/upstream-retry.ts +17 -5
- package/src/lib/windows-atomic-replace.ts +38 -16
- package/src/lib/windows-elevation.ts +6 -0
- package/src/lib/windows-secret-acl.ts +92 -25
- package/src/lib/winsw.ts +2 -3
- package/src/lib/workflow-budget.ts +53 -11
- package/src/messaging/budget.ts +45 -0
- package/src/messaging/discovery.ts +57 -0
- package/src/messaging/envelope.ts +49 -0
- package/src/messaging/input.ts +37 -0
- package/src/messaging/rpc.ts +196 -0
- package/src/messaging/send.ts +58 -0
- package/src/messaging/socket.ts +72 -0
- package/src/messaging/types.ts +29 -0
- package/src/oauth/anthropic-account-refusal.ts +90 -18
- package/src/oauth/anthropic-account-threshold.ts +8 -2
- package/src/oauth/anthropic-continuity.ts +15 -1
- package/src/oauth/anthropic-model-quota.ts +120 -48
- package/src/oauth/anthropic-model-routes.ts +11 -3
- package/src/oauth/anthropic-oauth-definitions.ts +98 -0
- package/src/oauth/anthropic-pool-config.ts +30 -0
- package/src/oauth/anthropic-rate-limit-policy.ts +64 -9
- package/src/oauth/anthropic-routing.ts +1202 -866
- package/src/oauth/anthropic-send-ownership.ts +41 -0
- package/src/oauth/anthropic.ts +4 -1
- package/src/oauth/chatgpt.ts +113 -41
- package/src/oauth/generic-account-failover.ts +3 -1
- package/src/oauth/health.ts +8 -6
- package/src/oauth/index.ts +96 -175
- package/src/oauth/kiro.ts +22 -9
- package/src/oauth/login-cli.ts +2 -0
- package/src/oauth/model-discovery-auth.ts +43 -0
- package/src/oauth/pool-kernel.ts +11 -5
- package/src/oauth/pool-settings-capability.ts +5 -3
- package/src/oauth/store-anthropic-instance.ts +87 -0
- package/src/oauth/store.ts +68 -10
- package/src/oauth/token-guardian.ts +2 -0
- package/src/oauth/types.ts +2 -0
- package/src/protocols/plan-snapshot.ts +5 -0
- package/src/protocols/settings.ts +20 -5
- package/src/providers/anthropic-instance-id.ts +47 -0
- package/src/providers/anthropic-instance.ts +48 -0
- package/src/providers/anthropic-reset-grant-ledger.ts +11 -1
- package/src/providers/azure-model-metadata.ts +115 -0
- package/src/providers/derive.ts +23 -0
- package/src/providers/kiro-models.ts +3 -0
- package/src/providers/label.ts +1 -1
- package/src/providers/model-rename-fields.ts +2 -0
- package/src/providers/quota/account-cache.ts +37 -11
- package/src/providers/quota/anthropic-account-quota.ts +93 -0
- package/src/providers/quota/anthropic-cooldown-recovery.ts +222 -111
- package/src/providers/quota/report-cache.ts +24 -1
- package/src/providers/quota/vendor-probes-key.ts +127 -17
- package/src/providers/quota/vendor-probes-oauth.ts +46 -14
- package/src/providers/quota.ts +23 -33
- package/src/providers/registry/entries-core.ts +35 -30
- package/src/providers/registry/model-ids.ts +1 -0
- package/src/providers/registry/model-seeds.ts +7 -4
- package/src/providers/registry/types.ts +3 -0
- package/src/providers/registry.ts +3 -3
- package/src/responses/reasoning-envelope.ts +29 -1
- package/src/responses/reasoning-replay-cache.ts +17 -1
- package/src/responses/spill-store.ts +20 -3
- package/src/responses/state/metrics.ts +95 -0
- package/src/responses/state/snapshot-codec.ts +6 -0
- package/src/responses/state/spill-failure.ts +12 -0
- package/src/responses/state/spill-queue.ts +13 -5
- package/src/responses/state/unforced-store-false.ts +55 -0
- package/src/responses/state.ts +68 -76
- package/src/responses/task-input.ts +17 -0
- package/src/router.ts +28 -4
- package/src/routing/compatibility/assemble.ts +1 -1
- package/src/routing/quota.ts +7 -3
- package/src/server/auth-cors.ts +5 -0
- package/src/server/background-lifecycle.ts +27 -0
- package/src/server/chat-completions.ts +7 -1
- package/src/server/chat-native.ts +64 -28
- package/src/server/claude-messages.ts +59 -8
- package/src/server/gui-static.ts +38 -4
- package/src/server/inbound-body-admission.ts +1 -0
- package/src/server/index/claude-intercept-lifecycle.ts +3 -1
- package/src/server/index/serve-options.ts +10 -2
- package/src/server/index/spend-ledger-lifecycle.ts +12 -5
- package/src/server/index/startup-warnings.ts +19 -0
- package/src/server/index.ts +5 -2
- package/src/server/inference/context.ts +1 -1
- package/src/server/lifecycle.ts +1 -1
- package/src/server/management/agent-settings-routes.ts +123 -38
- package/src/server/management/anthropic-account-threshold.ts +12 -9
- package/src/server/management/anthropic-pool-settings.ts +72 -0
- package/src/server/management/anthropic-reset-grant-routes.ts +98 -39
- package/src/server/management/codex-agent-role-routes.ts +4 -2
- package/src/server/management/codex-prompt-routes.ts +1 -0
- package/src/server/management/codex-role-auto-assign.ts +13 -2
- package/src/server/management/config-routes.ts +85 -14
- package/src/server/management/context.ts +2 -2
- package/src/server/management/decision-routes.ts +2 -1
- package/src/server/management/integration-routes.ts +25 -2
- package/src/server/management/oauth-account-routes.ts +79 -98
- package/src/server/management/provider-instance-ownership.ts +44 -0
- package/src/server/management/provider-routes.ts +21 -28
- package/src/server/management/route-registry.ts +3 -1
- package/src/server/management/routing-profile-routes.ts +4 -4
- package/src/server/management/shared.ts +3 -3
- package/src/server/management/system-restart.ts +44 -14
- package/src/server/management/system-routes.ts +24 -2
- package/src/server/management/vision-sidecar-options.ts +9 -6
- package/src/server/management/web-search-sidecar-options.ts +51 -2
- package/src/server/management-auth.ts +6 -0
- package/src/server/messages-native-eligibility.ts +3 -2
- package/src/server/messages-native-oauth.ts +91 -45
- package/src/server/messages-native-selector.ts +39 -0
- package/src/server/messages-native.ts +133 -38
- package/src/server/messages-response-headers.ts +14 -0
- package/src/server/request-log-conversation.ts +48 -5
- package/src/server/request-log.ts +36 -2
- package/src/server/responses/adapter-continuation.ts +31 -19
- package/src/server/responses/adapter-dispatch.ts +75 -24
- package/src/server/responses/antigravity-validation-refusal.ts +20 -6
- package/src/server/responses/codex-ws-exchange.ts +17 -2
- package/src/server/responses/codex-ws-pool.ts +100 -13
- package/src/server/responses/codex-ws-wire.ts +9 -0
- package/src/server/responses/combo-requested-effort.ts +3 -1
- package/src/server/responses/compact.ts +25 -8
- package/src/server/responses/compaction-recovery.ts +1 -1
- package/src/server/responses/core-codex-account.ts +22 -1
- package/src/server/responses/core-combo-native.ts +24 -4
- package/src/server/responses/core-combo.ts +38 -25
- package/src/server/responses/core-lifetime.ts +3 -36
- package/src/server/responses/core-normalize.ts +1 -0
- package/src/server/responses/core-options.ts +8 -1
- package/src/server/responses/core-replay.ts +78 -0
- package/src/server/responses/core.ts +3 -3
- package/src/server/responses/fetch-helpers.ts +26 -3
- package/src/server/responses/passthrough-delivery.ts +30 -4
- package/src/server/responses/passthrough-dispatch.ts +39 -9
- package/src/server/responses/request-prepare.ts +41 -5
- package/src/server/responses/request-send-budget.ts +150 -50
- package/src/server/responses/request-spend.ts +325 -33
- package/src/server/responses/request-transport.ts +132 -52
- package/src/server/responses/response-effects.ts +1 -0
- package/src/server/responses/run-turn-execution.ts +13 -3
- package/src/server/responses/sidecar-execution.ts +113 -22
- package/src/server/responses/sidecar-send-budget.ts +58 -0
- package/src/server/responses/ws-upstream.ts +19 -6
- package/src/server/responses-undeclared-tool-guard.ts +5 -1
- package/src/server/startup-health-cache.ts +2 -1
- package/src/server/workflow-refusal.ts +33 -0
- package/src/service/cli.ts +20 -4
- package/src/service/desktop-command-guard.ts +32 -0
- package/src/service/desktop-startup.ts +66 -40
- package/src/service/desktop-supervision.d.mts +26 -0
- package/src/service/desktop-supervision.mjs +140 -0
- package/src/service/managing-cli.ts +1 -0
- package/src/service/orchestration.ts +46 -20
- package/src/service/ownership-mutation-lease.d.mts +1 -1
- package/src/service/ownership-mutation-lease.mjs +5 -7
- package/src/service/repair.ts +25 -9
- package/src/service/state.ts +4 -3
- package/src/service/systemd.ts +17 -8
- package/src/service/windows-ops.ts +61 -22
- package/src/sidecar/anthropic-binding.ts +79 -0
- package/src/sidecar/auth.ts +76 -2
- package/src/storage/policy-job.ts +5 -1
- package/src/storage/policy-worker.ts +3 -1
- package/src/storage/policy.ts +9 -0
- package/src/types/anthropic-account-pool.ts +33 -0
- package/src/types/config.ts +33 -28
- package/src/types/provider.ts +5 -0
- package/src/types/request.ts +5 -0
- package/src/types/tools.ts +7 -0
- package/src/types/wire.ts +1 -0
- package/src/types.ts +4 -0
- package/src/update/index.ts +57 -9
- package/src/update/restart-ownership.ts +10 -3
- package/src/update/runtime-ownership.d.mts +6 -0
- package/src/update/runtime-ownership.mjs +23 -7
- package/src/usage/cost.ts +3 -2
- package/src/usage/expected-prices.ts +66 -14
- package/src/vision/anthropic-describe.ts +16 -3
- package/src/vision/index.ts +3 -0
- package/src/vision/plan.ts +19 -6
- package/src/web-search/alpha-search.ts +7 -1
- package/src/web-search/anthropic-executor.ts +16 -4
- package/src/web-search/index.ts +7 -3
- package/src/web-search/loop.ts +32 -7
- package/src/web-search/passthrough-bridge.ts +4 -1
- package/src/web-search/sidecar-providers.ts +4 -3
- package/gui/dist/assets/App-MbDVfUeC.js +0 -54
- package/gui/dist/assets/Tray-CzkxK82A.js +0 -1
- package/gui/dist/assets/index-UJt6npXk.js +0 -94
- package/gui/dist/assets/quota-summary-DU3sD6Z-.js +0 -1
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { createInferenceSendBudget } from "../inference/context";
|
|
1
2
|
import type { ResponsesRequestContext } from "./core-options";
|
|
2
|
-
import { createRequestExecutionBudget, isRequestExecutionBudget } from "../../lib/request-execution-budget";
|
|
3
|
+
import { claimDispatchSpendProof, createPhysicalSendReporter, createRequestExecutionBudget, isRequestExecutionBudget, reportDispatchSends } from "../../lib/request-execution-budget";
|
|
3
4
|
import {
|
|
4
5
|
chargeWorkflowSends,
|
|
5
6
|
workflowSendCeilingReached,
|
|
6
7
|
workflowSpendCeilingReached,
|
|
7
8
|
} from "../../lib/workflow-budget";
|
|
8
|
-
import { workflowRefusalResponse } from "../workflow-refusal";
|
|
9
|
+
import { poolContinuityRefusalReason, workflowRefusalResponse } from "../workflow-refusal";
|
|
9
10
|
import type { AttemptRecoveryKind, AttemptRecoveryWithheld } from "../../usage/log";
|
|
10
11
|
import { noteAttemptRecoveryWithheld, noteAttemptSend } from "../request-log";
|
|
11
|
-
import { TRANSIENT_RETRY_MAX_ATTEMPTS } from "../../lib/upstream-retry";
|
|
12
|
+
import { TRANSIENT_RETRY_MAX_ATTEMPTS, SendBudgetExhaustedError } from "../../lib/upstream-retry";
|
|
12
13
|
import type {
|
|
13
14
|
DispatchDecision,
|
|
14
15
|
DispatchIntent,
|
|
@@ -52,17 +53,42 @@ export function createResponsesSendBudget(
|
|
|
52
53
|
// fresh default of 3. It is now a holder carried on options, so a combo child inherits the
|
|
53
54
|
// parent's spend instead of starting over per target -- both halves of the measured
|
|
54
55
|
// amplification in #4546.
|
|
55
|
-
const sendBudget = options.sendBudget ??
|
|
56
|
+
const sendBudget = options.sendBudget ?? createInferenceSendBudget(req, logCtx);
|
|
56
57
|
// The root workflow is the user-visible task. A per-request cap cannot bound a fan-out that
|
|
57
58
|
// sends once per child seven hundred times, so every send charged to the request is charged
|
|
58
59
|
// to the root as well (#4546).
|
|
59
60
|
const workflowRootId = req.headers.get("x-codex-parent-thread-id")?.trim() || undefined;
|
|
60
|
-
|
|
61
|
+
// A child that owns its Combo booking settles that exact permit through the reporter, even
|
|
62
|
+
// when its caller handed ownership over only as `comboInitialSend`.
|
|
63
|
+
const inheritedPermit = options.compactionRecoveryPermit ?? options.comboDispatchPermit
|
|
64
|
+
?? options.comboInitialSend?.permit;
|
|
65
|
+
let pendingHopPermit: SingleUseDispatchPermit | undefined = options.compactionRecoveryPermit;
|
|
66
|
+
let initialPermit = options.comboInitialSend?.permit;
|
|
67
|
+
// Count this owner's physical sends, not later bookings made by other shared-ledger owners.
|
|
68
|
+
// Direct callers retain sends reported before this owner was constructed.
|
|
69
|
+
let targetSendsUsed = initialPermit ? 0 : Math.max(0,
|
|
70
|
+
sendBudget.used - (options.compactionRecoveryPermit ? 1 : 0));
|
|
71
|
+
/** Attribute reported physical sends to this owner; the prepaid booking is spent once reported. */
|
|
72
|
+
const noteTargetSends = (charged: number): void => {
|
|
73
|
+
targetSendsUsed += charged;
|
|
74
|
+
if (charged > 0) initialPermit = undefined;
|
|
75
|
+
};
|
|
76
|
+
const recordTransientSends = (used: number, permit?: SingleUseDispatchPermit): void => {
|
|
61
77
|
const charged = Math.max(0, used);
|
|
62
|
-
|
|
78
|
+
noteTargetSends(charged);
|
|
79
|
+
reportDispatchSends(sendBudget, charged, permit);
|
|
63
80
|
options.onCompactionRecoverySendsReported?.(charged);
|
|
64
81
|
chargeWorkflowSends(workflowRootId, charged);
|
|
65
82
|
};
|
|
83
|
+
const noteTransientSends = (used: number): void => recordTransientSends(used, pendingHopPermit ?? inheritedPermit);
|
|
84
|
+
// Capture at helper creation, before another leg can replace the pending handoff.
|
|
85
|
+
const transientSendReporter = (permit = pendingHopPermit ?? inheritedPermit) =>
|
|
86
|
+
createPhysicalSendReporter(sendBudget, () => ({ poolId: logCtx.spendPoolId ?? logCtx.provider,
|
|
87
|
+
identityId: logCtx.accountLogLabel }), permit, charged => {
|
|
88
|
+
noteTargetSends(Math.max(0, charged));
|
|
89
|
+
options.onCompactionRecoverySendsReported?.(charged);
|
|
90
|
+
chargeWorkflowSends(workflowRootId, charged);
|
|
91
|
+
});
|
|
66
92
|
// Refused before any dispatch, and deliberately not by evicting the root's ledger entry:
|
|
67
93
|
// dropping the record to make room would hand the fan-out a fresh allowance, which is the
|
|
68
94
|
// laundering this ceiling exists to stop. The client is told the task needs a new grant
|
|
@@ -78,7 +104,17 @@ export function createResponsesSendBudget(
|
|
|
78
104
|
// returns -- a refusal an operator cannot tell from an ordinary budget exhaustion, on a
|
|
79
105
|
// ceiling they configured themselves. Asked before dispatch, it names the scope and the
|
|
80
106
|
// number instead. Returns undefined and touches no ledger when no ceiling is configured.
|
|
81
|
-
|
|
107
|
+
// Passthrough reports sends after they leave. Invalid or conflicting identity evidence
|
|
108
|
+
// still refuses here as well as in reserve(), including requests with no workflow root.
|
|
109
|
+
// Positive unbound balances alone are instead overlaid on each candidate pool below.
|
|
110
|
+
const continuityRefusal = poolContinuityRefusalReason();
|
|
111
|
+
if (continuityRefusal) {
|
|
112
|
+
return workflowRefusalResponse(continuityRefusal, logCtx, undefined, workflowRootId);
|
|
113
|
+
}
|
|
114
|
+
const prepaid = isRequestExecutionBudget(sendBudget)
|
|
115
|
+
? claimDispatchSpendProof(sendBudget, options.compactionRecoveryPermit ?? options.comboDispatchPermit) : undefined;
|
|
116
|
+
const admissionPolicy = isRequestExecutionBudget(sendBudget) ? sendBudget.spendAdmissionPolicy : undefined;
|
|
117
|
+
const spentCeiling = workflowSpendCeilingReached(workflowRootId, undefined, logCtx.spendPoolId ?? logCtx.provider, prepaid, admissionPolicy);
|
|
82
118
|
if (spentCeiling) {
|
|
83
119
|
return workflowRefusalResponse(
|
|
84
120
|
"workflow-spend-exhausted",
|
|
@@ -115,6 +151,7 @@ export function createResponsesSendBudget(
|
|
|
115
151
|
// Ordinal 1 is skipped because the caller normally records it before dispatch. An adapter
|
|
116
152
|
// that reports every send asks for it to be counted here instead, so that the first send is
|
|
117
153
|
// logged where it actually happens rather than before admission could still refuse it.
|
|
154
|
+
targetSendsUsed += 1;
|
|
118
155
|
if (send.ordinal <= 1 && options.includeFirst !== true) return;
|
|
119
156
|
noteAttemptSend(logCtx.activeAttempt, inputTokens, send.recovery);
|
|
120
157
|
};
|
|
@@ -157,7 +194,6 @@ export function createResponsesSendBudget(
|
|
|
157
194
|
* refused and the request would answer with a synthetic 502 in place of the real 429 the hop
|
|
158
195
|
* was recovering from.
|
|
159
196
|
*/
|
|
160
|
-
let pendingHopPermit: SingleUseDispatchPermit | undefined = options.compactionRecoveryPermit;
|
|
161
197
|
/**
|
|
162
198
|
* The budget an adapter's OWN dispatch ladder reserves against.
|
|
163
199
|
*
|
|
@@ -171,19 +207,29 @@ export function createResponsesSendBudget(
|
|
|
171
207
|
* The hop hands its reservation down through `pendingHopPermit`, the same seam the
|
|
172
208
|
* passthrough ladder already uses, and this view spends it on the adapter's FIRST
|
|
173
209
|
* reservation. Every later send in that ladder is a new physical send and is charged
|
|
174
|
-
* normally.
|
|
175
|
-
*
|
|
176
|
-
* rather than left charged.
|
|
210
|
+
* normally. Claiming preserves the refundable single-use booking until physical dispatch;
|
|
211
|
+
* an abandoned replay releases only that exact booking.
|
|
177
212
|
*/
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
:
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
213
|
+
const permits = {
|
|
214
|
+
/** Transfer the initial booking once to the adapter dispatch owner. */
|
|
215
|
+
claimInitialPermit: () => {
|
|
216
|
+
const permit = initialPermit;
|
|
217
|
+
initialPermit = undefined;
|
|
218
|
+
return permit;
|
|
219
|
+
},
|
|
220
|
+
/** Transfer a pending recovery booking once, without creating a new allowance. */
|
|
221
|
+
claimHopPermit: () => {
|
|
222
|
+
const permit = pendingHopPermit;
|
|
223
|
+
pendingHopPermit = undefined;
|
|
224
|
+
return permit;
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
const adapterDispatchBudget = adapterSendBudget === undefined
|
|
228
|
+
? undefined : adapterDispatchBudgetView(adapterSendBudget, permits);
|
|
229
|
+
// Preserve the existing opted-in view for direct callers, including its admitted replacement
|
|
230
|
+
// of an already-settled hop. Exact-owned Combo and sidecar handoffs use the ordinary view.
|
|
231
|
+
const refundableAdapterDispatchBudget = adapterSendBudget === undefined
|
|
232
|
+
? undefined : adapterDispatchBudgetView(adapterSendBudget, permits, true);
|
|
187
233
|
/**
|
|
188
234
|
* How many sends a recovery leg may make, and the permit that authorises the last one.
|
|
189
235
|
*
|
|
@@ -268,17 +314,41 @@ export function createResponsesSendBudget(
|
|
|
268
314
|
return {
|
|
269
315
|
workflowRootId,
|
|
270
316
|
noteTransientSends,
|
|
317
|
+
transientSendReporter,
|
|
271
318
|
remainingTransientSendBudget,
|
|
319
|
+
/** Only this child's prepaid send, not every pending external booking, is spendable here. */
|
|
320
|
+
initialSendAllowance: (cap: number): number => Math.min(cap,
|
|
321
|
+
remainingTransientSendBudget(cap) + (initialPermit ? 1 : 0)),
|
|
322
|
+
/** At final executor admission, settle only the owning booking or reserve this send. */
|
|
323
|
+
noteInitialDispatch: (prepaid = initialPermit): void => {
|
|
324
|
+
if (prepaid) {
|
|
325
|
+
if (!prepaid.assumeCharge()) throw new SendBudgetExhaustedError();
|
|
326
|
+
if (prepaid === initialPermit) initialPermit = undefined;
|
|
327
|
+
} else if (adapterSendBudget && (options.comboInitialSend || options.compactionRecoveryPermit)) {
|
|
328
|
+
const decision = adapterSendBudget.reserveDispatch({ sendClass: "transient",
|
|
329
|
+
targetKey: adapterSendBudget.lastTargetKey ?? `${logCtx.provider}/${logCtx.model}` });
|
|
330
|
+
if (!decision.allowed || !decision.permit.use()) throw new SendBudgetExhaustedError();
|
|
331
|
+
} else {
|
|
332
|
+
// Legacy direct callers can prebook without handing over a permit; keep their reporter.
|
|
333
|
+
noteTransientSends(1);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
targetSendsUsed += 1;
|
|
337
|
+
options.onCompactionRecoverySendsReported?.(1);
|
|
338
|
+
chargeWorkflowSends(workflowRootId, 1);
|
|
339
|
+
},
|
|
340
|
+
/** Physical sends reported by this owner; unrelated shared reservations cannot consume it. */
|
|
341
|
+
get targetSendsUsed(): number { return targetSendsUsed; },
|
|
272
342
|
/**
|
|
273
|
-
*
|
|
343
|
+
* Charged sends, including open prepaid reservations, across this logical request.
|
|
274
344
|
*
|
|
275
|
-
* A live getter, not a snapshot
|
|
276
|
-
*
|
|
277
|
-
* nothing.
|
|
345
|
+
* A live getter, not a completed-send snapshot. Initial ladders use the child's own
|
|
346
|
+
* prepaid allowance and target-local count; shared admission keeps every booking spent.
|
|
278
347
|
*/
|
|
279
348
|
get sendsUsed(): number { return sendBudget.used; },
|
|
280
349
|
adapterSendBudget,
|
|
281
350
|
adapterDispatchBudget,
|
|
351
|
+
refundableAdapterDispatchBudget,
|
|
282
352
|
noteAdapterPhysicalSend,
|
|
283
353
|
noteAdapterRecoveryWithheld,
|
|
284
354
|
sendBudgetExhausted,
|
|
@@ -311,9 +381,21 @@ export type ResponsesSendBudget = Exclude<ReturnType<typeof createResponsesSendB
|
|
|
311
381
|
*/
|
|
312
382
|
function adapterDispatchBudgetView(
|
|
313
383
|
budget: RequestExecutionBudget,
|
|
314
|
-
hop: {
|
|
384
|
+
hop: {
|
|
385
|
+
claimInitialPermit: () => SingleUseDispatchPermit | undefined;
|
|
386
|
+
claimHopPermit: () => SingleUseDispatchPermit | undefined;
|
|
387
|
+
},
|
|
388
|
+
legacyHopReplacement = false,
|
|
315
389
|
): RequestExecutionBudget {
|
|
316
390
|
return {
|
|
391
|
+
get physicalStarted() { return budget.physicalStarted; },
|
|
392
|
+
get physicalLimit() { return budget.physicalLimit; },
|
|
393
|
+
get spendEnforced() { return budget.spendEnforced; },
|
|
394
|
+
get spendPolicyStarted() { return budget.spendPolicyStarted; },
|
|
395
|
+
get spendAdmissionPolicy() { return budget.spendAdmissionPolicy; },
|
|
396
|
+
startRequest: target => budget.startRequest?.(target),
|
|
397
|
+
claimPhysicalSend: () => budget.claimPhysicalSend?.(),
|
|
398
|
+
beginSpendProducer: () => budget.beginSpendProducer?.(),
|
|
317
399
|
get used(): number { return budget.used; },
|
|
318
400
|
set used(next: number) { budget.used = next; },
|
|
319
401
|
logicalRequestId: budget.logicalRequestId,
|
|
@@ -330,6 +412,19 @@ function adapterDispatchBudgetView(
|
|
|
330
412
|
// A dispatch whose upstream state is unknown is refused on its own merits. A hop that
|
|
331
413
|
// already paid does not make an unsafe replay safe, so that check stays with the budget.
|
|
332
414
|
if (intent.replaySafe !== false) {
|
|
415
|
+
// The Combo reserves a logical provider/model identity. The child's first actual
|
|
416
|
+
// endpoint is not a recovery transition; retain the original refundable permit.
|
|
417
|
+
const initialPermit = hop.claimInitialPermit();
|
|
418
|
+
if (initialPermit) {
|
|
419
|
+
budget.bindPrepaidTarget?.(intent.targetKey);
|
|
420
|
+
return { allowed: true, permit: {
|
|
421
|
+
sendClass: initialPermit.sendClass,
|
|
422
|
+
execute: run => initialPermit.execute ? initialPermit.execute(run) : run(),
|
|
423
|
+
use: () => initialPermit.assumeCharge(),
|
|
424
|
+
assumeCharge: () => initialPermit.assumeCharge(),
|
|
425
|
+
release: () => initialPermit.release(),
|
|
426
|
+
} };
|
|
427
|
+
}
|
|
333
428
|
const hopPermit = hop.claimHopPermit();
|
|
334
429
|
if (hopPermit && intent.targetKey !== budget.lastTargetKey) {
|
|
335
430
|
// The rotated credential can select a different regional endpoint. Replace the
|
|
@@ -338,32 +433,37 @@ function adapterDispatchBudgetView(
|
|
|
338
433
|
hopPermit.release();
|
|
339
434
|
return budget.reserveDispatch({ ...intent, sendClass: hopPermit.sendClass });
|
|
340
435
|
}
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
//
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
436
|
+
// Reservation precedes pacing and beforeDispatch. Transfer the exact open booking;
|
|
437
|
+
// only physical consumption closes external reporting and makes it non-refundable.
|
|
438
|
+
// The underlying permit enforces single use, including settlement by another owner.
|
|
439
|
+
if (hopPermit !== undefined) {
|
|
440
|
+
if (legacyHopReplacement) {
|
|
441
|
+
let settled = false;
|
|
442
|
+
let executionPermit = hopPermit;
|
|
443
|
+
const confirm = (): boolean => {
|
|
444
|
+
if (settled) return false;
|
|
445
|
+
settled = true;
|
|
446
|
+
if (hopPermit.assumeCharge()) return true;
|
|
447
|
+
// Preserve the old fallback for a permit another leg already settled.
|
|
448
|
+
const fresh = budget.reserveDispatch(intent);
|
|
449
|
+
if (!fresh.allowed) return false;
|
|
450
|
+
executionPermit = fresh.permit;
|
|
451
|
+
return fresh.permit.assumeCharge();
|
|
452
|
+
};
|
|
453
|
+
return { allowed: true, permit: {
|
|
351
454
|
sendClass: hopPermit.sendClass,
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
release: (): void => {},
|
|
365
|
-
},
|
|
366
|
-
};
|
|
455
|
+
execute: run => executionPermit.execute ? executionPermit.execute(run) : run(),
|
|
456
|
+
use: confirm, assumeCharge: confirm,
|
|
457
|
+
release: () => { if (!settled) { settled = true; hopPermit.release(); } },
|
|
458
|
+
} };
|
|
459
|
+
}
|
|
460
|
+
return { allowed: true, permit: {
|
|
461
|
+
sendClass: hopPermit.sendClass,
|
|
462
|
+
execute: run => hopPermit.execute ? hopPermit.execute(run) : run(),
|
|
463
|
+
use: () => hopPermit.assumeCharge(),
|
|
464
|
+
assumeCharge: () => hopPermit.assumeCharge(),
|
|
465
|
+
release: () => hopPermit.release(),
|
|
466
|
+
} };
|
|
367
467
|
}
|
|
368
468
|
}
|
|
369
469
|
return budget.reserveDispatch(intent);
|