/** * Rate-limit retry for `agent exec` (doc/agent-exec-protocol.md §3.4, rev 20). * * A turn whose runner failed on a transient provider rate limit (HTTP 429 — * `code: "rate-limited"`, see provider-limit.ts; exhausted quota or billing * stays `quota` and is never retried) is run again, up to * RATE_LIMIT_MAX_ATTEMPTS attempts in all, after an exponential backoff with * jitter (~2s, ~4s) or the provider's own Retry-After hint, each wait capped * at 30s. Before each retry the caller gets * {"type":"status","phase":"notice","message":"Rate limited (429) by ; retrying in Ns (attempt 2/3)"} * The failed attempt's `error` and `done` are held back, so the caller sees * one `start` and one `done` for the whole turn. * * Safety: a retry starts the turn from scratch only when the failed attempts * ran no tool (no `tool_activity` start, no `tool_call`) — nothing to redo * twice. When tools ran and the runtime resumes (`agent scan`'s `resume`) a * session it bound, the retry resumes that session with RESUME_PROMPT; * otherwise the turn fails without a retry. A runtime with no tool signal * (`tool_activity_fidelity: "none"`) counts as having run tools. * * No multiplied retries: when the runtime's CLI already retried the 429 * itself (pi's auto_retry, aider's litellm backoff, codex's "exceeded retry * limit"), the turn fails at once. All waits stay inside `--timeout`: each * attempt gets the time left, and a wait that would outlast it ends the turn. * A `cancel` frame or SIGINT/SIGTERM during a wait ends it as `cancelled`. * * After the last attempt: `error {code:"rate-limited", fatal:true}` with * "Rate limited by (429) after 3 attempts. Free models are rate-limited; * try again later or pick another model." and `done {exit_code: 1}`. */ import type { RateLimitHit } from './agent-exec-errors.js'; import type { AgentExecOptions } from './agent-exec-options.js'; export declare const RATE_LIMIT_MAX_ATTEMPTS = 3; /** The prompt a resumed retry sends in place of the original one. */ export declare const RESUME_PROMPT: string; /** Shared between the wrapper and one attempt (agent-exec.ts's runAgentExecOnce). */ export interface AttemptContext { /** 1-based attempt number; above 1 the attempt skips `start`. */ attempt: number; /** Set by the attempt when it failed on a transient rate limit. */ rateLimit?: RateLimitHit; } type Attempt = (opts: AgentExecOptions, ctx: AttemptContext) => Promise; /** Backoff before attempt `next` (2, 3, …): the provider's hint, else * 2s·2^(next-2) ±20% jitter; capped at 30s. */ export declare function backoffMs(next: number, retryAfterMs?: number, random?: () => number): number; /** Run `once` until it succeeds, fails for another reason, or the rate-limit * retry budget is spent (see the module doc). Returns the exit code. */ export declare function runWithRateLimitRetry(opts: AgentExecOptions, once: Attempt): Promise; export {}; //# sourceMappingURL=agent-exec-retry.d.ts.map