diff --git a/scripts/test-layout/layout.json b/scripts/test-layout/layout.json index 9925e111815..4868047c94f 100644 --- a/scripts/test-layout/layout.json +++ b/scripts/test-layout/layout.json @@ -76,6 +76,9 @@ "owner-registry-acl.test.ts": "config", "minimax-combo-image-input.test.ts": "providers", "web-search-forced-declaration.test.ts": "web-search", + "web-search-loop-iteration-usage.test.ts": "web-search", + "web-search-loop-error-usage.test.ts": "web-search", + "web-search-rotation-usage-attribution.test.ts": "web-search", "claude-devin-output-order.test.ts": "claude-integration", "codex-config-preservation.test.ts": "codex-integration", "codex-credits.test.ts": "codex-integration", diff --git a/src/images/loop.ts b/src/images/loop.ts index cc33a556bae..36ac172d9f6 100644 --- a/src/images/loop.ts +++ b/src/images/loop.ts @@ -325,6 +325,12 @@ export interface ImageBridgeDeps { waitForRequestSlot?: (signal?: AbortSignal) => Promise; /** Raw adapter usage at the terminal event, pre wire-normalization (see bridgeToResponsesSSE onUsage). */ onUsage?: (usage: OcxUsage | undefined) => void; + /** + * After an `on429` rotation, offered the usage of the hidden iterations the left credential + * served. Returning true means it was billed to that credential's attempt, so `onUsage` will not + * report it again; the client terminal still includes it. + */ + onRotatedUsage?: (usage: OcxUsage) => boolean; /** * Optional 429 failover for the routed (non-xAI) model. Return a rebuilt adapter for the * rotated credential, or null when the pool is exhausted. Async hooks support OAuth refresh; @@ -383,6 +389,10 @@ export async function runWithImageBridge(deps: ImageBridgeDeps): Promise