import { rotationCandidates, type ModelRoster } from "../models/roster.js"; import type { MicroAgentErrorClass } from "../backends/micro-agent-backend.js"; /** * Failures the provider owns, as opposed to failures the work owns. Only these justify * retrying the same task on a different model: a contract violation is the model's actual * answer, a missing credential is the operator's problem, and an abort was deliberate — * rotating on any of them would hide the thing the user needs to see. */ export const ROTATABLE_ERROR_CLASSES: readonly MicroAgentErrorClass[] = ["rate-limited", "provider-5xx", "timeout", "model-unavailable"]; export function isRotatableFailure(errorClass: MicroAgentErrorClass): boolean { return ROTATABLE_ERROR_CLASSES.includes(errorClass); } /** The next declared model to try, preferring peers at or above the failed model's rank. */ export function nextRotationModel(roster: ModelRoster, model: string, critical: boolean, exhausted: ReadonlySet): string | undefined { return rotationCandidates(roster, model, critical).find((candidate) => !exhausted.has(candidate)); }