/** pi-ai 1.5.0 retry classification and the commit observer adapter. */ function buildProviderErrorPattern(patterns) { return new RegExp(patterns.join("|"), "i"); } const NON_RETRYABLE_PROVIDER_LIMIT_ERROR_PATTERN = buildProviderErrorPattern([ // OpenCode Go/free-tier limits returned as 429 JSON error types by OpenCode's // Zen API. These are subscription/account limits, not transient throttles. "GoUsageLimitError", "FreeUsageLimitError", // OpenCode Go subscription-limit text asks users to enable available-balance // usage after rolling/weekly/monthly limits are reached. "Monthly usage limit reached", "available balance", // Generic quota/budget/billing exhaustion. `insufficient_quota` is OpenAI's // quota/billing error code; the other strings cover common gateway wording. "insufficient_quota", "out of budget", "quota exceeded", "billing", // Sign in with ChatGPT: the subscription's shared usage limit, which resets // after hours rather than seconds. "subscription_sharing_usage_limit_exceeded", // Sign in with ChatGPT on a ChatGPT Business plan: a usage limit set by the // workspace admin. Only the admin can raise it. "subscription_sharing_workplace_individual_usage_limit_exceeded", // Zhipu/Z.ai (open.bigmodel.cn) error code 1308: the plan's usage limit is // reached, sent as HTTP 429. It resets after hours, not seconds (#11537). '"code"\\s*:\\s*"?1308(?![0-9])', ]); const RETRYABLE_PROVIDER_ERROR_PATTERN = buildProviderErrorPattern([ // Generic provider load, HTTP status, and server-side transient failures. "overloaded", "server_busy", "servers are currently busy", "currently experiencing high demand", "model is at capacity", "rate.?limit", "too many requests", // Status codes must not be part of a longer word or number, e.g. a request id or byte count (#11057). "(? void) { const observation = session.observeCommits({ advance, end: () => {} }) return () => observation.detach() } import type { AssistantMessage } from '@earendil-works/pi-ai' /** * Whether a model error is a rate limit Pi retries: HTTP 429, "rate limit", "too many requests". Retrying sooner only * hits the limit again, so Ultimate pauses until the user presses Play, and the held run continues through Pi's retry. * Quota, usage-limit and billing errors are on Pi's no-retry list: they end the run at once and fail as usual. * Overloaded servers (529) are the provider's capacity, not the account's limit. */ export const rateLimited = (error: string) => /(?