import type { ApiClient } from '../http/client.js'; import type { ProgressReporter } from '../progress.js'; export interface GenerateOptions { /** Optional ONLY for a listing-image request, where the style preset supplies the prompt. */ prompt?: string; source: string; size?: string; sourceImageUuid?: string; /** Listing photography: edit THIS product's own rendered mockup (#183). */ sourceProductUuid?: string; /** Listing-photo preset (on_model | detail | flat_lay | lifestyle). Composes the prompt. */ listingStyle?: string; /** Which of the product's existing listing images to edit. Defaults to its best mockup. */ sourceImageUrl?: string; workspace?: string; } /** Does this request edit an existing image? Both an explicit source image and a listing-photo * request do — and an edit can only ever fall back to an edit-capable model. */ export declare function isEditRequest(opts: GenerateOptions): boolean; export interface GeneratedImage { image_uuid: string; image_url: string; source_used: string; } /** One rung of a fallback attempt: the model that was tried and why it was abandoned. */ export interface FallbackAttempt { source: string; reason: string; /** The structured error code of the failure (e.g. model_rate_limited), for honest attribution. */ code?: string; } export interface GenerateWithFallbackOptions extends GenerateOptions { /** The ordered ladder of sources to try (from fallbackLadder). The first is the primary. */ sources: string[]; /** Disable falling back: try only the first source and rethrow its error. */ noFallback?: boolean; } export interface GeneratedImageWithFallback extends GeneratedImage { /** The models that were tried-and-abandoned before the one that succeeded (empty on first try). */ fallback_trail: FallbackAttempt[]; } export interface GenerateDeps { progress?: ProgressReporter; sleep?: (ms: number) => Promise; signal?: AbortSignal; timeoutMs?: number; intervalMs?: number; } export declare function runGeneration(api: ApiClient, opts: GenerateOptions, deps?: GenerateDeps): Promise; /** * Run a generation with a model-fallback ladder (epic #67). Tries each source in `opts.sources`; * on a rate-limit/transient failure (isFallbackableError) it records the attempt and moves to the * next model; a NON-fallbackable error (validation / auth / forbidden / not_found) rethrows * immediately. The per-model transient retries are already exhausted inside the ApiClient before * runGeneration throws, so reaching the fallback here means the model itself is throttled/down. * * The ladder is short (≤3 sync fallbacks), so the wall-clock cost of exhausting it is bounded even * though the first source may be an async-polled model. * * A CONTENT BLOCK takes a second, wider path. Content guards are provider-specific — a prompt one * vendor refuses on recitation grounds routinely renders elsewhere — so on the first * `content_blocked` the short ladder is EXTENDED IN PLACE with a provider-diverse sweep of every * remaining model (contentBlockSweep). This is affordable precisely because a refusal is fast: * ~4.2s measured, quicker than a ~6.0s success, since the model never generates anything. */ export declare function runGenerationWithFallback(api: ApiClient, opts: GenerateWithFallbackOptions, deps?: GenerateDeps): Promise;