/** * xskill.ts — a thin REST client for the apiz.ai / suitui-ai aggregator (also * branded "xskill" / "速推" / "NEX AI"), which fronts the fal.ai post-production * models we need: Topaz video upscale and OmniHuman audio-driven lip-sync. * * It is NOT a per-scene generation route (those go through the storyboard → * execute pipeline). It is the async-task client the new `finish` / `lipsync` * commands call directly: * xskillSubmit(modelId, params) → taskId * → xskillAwait(taskId) polls until completed → the output URL * → xskillDownload(url, dest). * * The HTTP contract (verified against the live API + the MCP tool schemas): * POST {base}/api/v3/tasks/create Bearer { model_id, params } → { task_id, status } * GET {base}/api/v3/tasks/{task_id} Bearer → { status, result } * status ∈ pending | processing | completed | failed * output URL lives in `result` — `result.video.url` (video) / `result.images[].url` (image). * The key is read from APIZ_API_KEY (the official CLI's var) or XSKILL_API_KEY * (kept for continuity); its form is `sk-...`. Transports are injectable so the * whole client is unit-testable offline. */ export declare const XSKILL_BASE = "https://api.apiz.ai"; export declare const XSKILL_SUBMIT_PATH = "/api/v3/tasks/create"; export declare const xskillTaskPath: (taskId: string) => string; export type XskillTaskStatus = 'pending' | 'processing' | 'completed' | 'failed'; /** Minimal fetch surface for JSON submit/poll — injectable for offline tests. */ export type XskillFetchLike = (url: string, init: { method: string; headers: Record; body?: string; }) => Promise<{ ok: boolean; status: number; text(): Promise; }>; /** Fetch surface for binary download — injectable for offline tests. */ export type XskillDownloadFetchLike = (url: string) => Promise<{ ok: boolean; status: number; arrayBuffer(): Promise; }>; export interface XskillClientOptions { /** Explicit key; falls back to APIZ_API_KEY / XSKILL_API_KEY. */ apiKey?: string; /** Base URL override (default {@link XSKILL_BASE}). */ baseUrl?: string; env?: NodeJS.ProcessEnv; fetchImpl?: XskillFetchLike; /** Transient-retry budget for 429/5xx/network errors (default 3). */ maxRetries?: number; /** Base backoff between retries, ms (default 800; grows linearly). */ retryBackoffMs?: number; } /** Resolve the API key from options/env, or throw a clear, actionable error. */ export declare function resolveXskillApiKey(options?: XskillClientOptions): string; /** * A failed xskill HTTP exchange, carrying the status (0 = network error — the * request may or may not have reached the server) and the response/error body * so callers can discriminate failure modes instead of regexing messages. */ export declare class XskillHttpError extends Error { readonly status: number; readonly body: string; constructor(status: number, body: string); } /** * Submit an async task. Body is `{ model_id, params }`. If the API rejects * `model_id` with a 4xx validation error, it retries once with the alternate * `model` field name (both appear in the CLI docs). Returns the task id. */ export declare function xskillSubmit(modelId: string, parameters: Record, options?: XskillClientOptions): Promise; export interface XskillTaskResult { status: XskillTaskStatus; /** Model-specific output container (`result.video.url`, `result.images[].url`, …). */ result: Record | undefined; /** The full parsed response, for diagnostics. */ raw: Record; } /** Poll a task once. Returns the normalized status + result container. */ export declare function xskillPoll(taskId: string, options?: XskillClientOptions): Promise; /** Extract the first output media URL from a task `result` container. */ export declare function extractOutputUrl(result: Record | undefined): string | null; export interface XskillAwaitOptions extends XskillClientOptions { /** Poll interval, ms (default 5000). */ pollIntervalMs?: number; /** Give up after this long, ms (default 600000 = 10 min). */ timeoutMs?: number; /** Called after each poll with the latest status (for progress logging). */ onTick?: (status: XskillTaskStatus, elapsedMs: number) => void; /** Injected clock (ms) for deterministic tests; defaults to Date.now. */ now?: () => number; } export interface XskillCompleted { taskId: string; videoUrl: string; result: Record; } /** * Poll `taskId` until it completes. Resolves with the output URL on `completed`, * throws on `failed` or when `timeoutMs` elapses. Pure of wall-clock except the * injected `now`/`sleep` (overridable for tests). */ export declare function xskillAwait(taskId: string, options?: XskillAwaitOptions): Promise; /** Download a completed output URL to `dest`. Uses global fetch unless injected. */ export declare function xskillDownload(url: string, dest: string, options?: { fetchImpl?: XskillDownloadFetchLike; }): Promise; //# sourceMappingURL=xskill.d.ts.map