import { Journal } from "./journal.js"; import { Fixture, HandlerDefaults, VideoResponse } from "./types.js"; import * as http$1 from "node:http"; //#region src/openrouter-video.d.ts declare const OPENROUTER_VIDEO_MAX_ENTRIES = 10000; type OpenRouterVideoStatus = "pending" | "in_progress" | "completed" | "failed"; interface OpenRouterVideoReplayJob { kind: "replay"; jobId: string; status: OpenRouterVideoStatus; /** Number of status polls the caller has made against this job. */ pollCount: number; /** Poll-count threshold for `pending → in_progress` transition. */ pollsBeforeInProgress: number; /** Poll-count threshold for the transition to the terminal status. */ pollsBeforeCompleted: number; /** The matched fixture's video object (terminal status, bytes, cost, error). */ video: VideoResponse["video"]; /** * Latch for the empty-`error` authoring warn on failed polls — a polling * loop must surface the fixture defect once per job, not once per poll. */ emptyErrorWarned?: boolean; /** * Latch for the per-download fixture-defect warns on the content endpoint * (b64 corruption / empty b64 / ignored url). The job's `video` is * immutable after submit, so the warn set is identical on every download — * surface it once per job, not once per re-download. */ contentWarnsLatched?: boolean; } /** * A job whose lifecycle is proxied live upstream (record mode, no fixture * matched at submit). Every client poll is forwarded 1:1 to * `upstreamPollingUrl`; when the upstream reports a terminal status the * entry is captured as a fixture and MUTATED into a terminal * OpenRouterVideoReplayJob — so the content endpoint serves it like any * replay job. Under `record.proxyOnly` nothing is ever captured or mutated: * the job stays `kind: "record"` (terminal statuses included) and the * content endpoint live-proxies the stored upstream `unsigned_urls`. */ interface OpenRouterVideoRecordJob { kind: "record"; /** The mock-issued jobId the client polls with. */ jobId: string; /** * Last upstream status relayed to the client. Terminal values occur under * proxyOnly (the job stays a live proxy forever) and during the capturing * window — `completed` is set synchronously with `capturing` so the content * endpoint can live-proxy downloads while the eager capture is in flight. * Outside those two cases the capturing path mutates the entry into a * replay job at the terminal poll. */ status: OpenRouterVideoStatus; /** Upstream's own job id (recorded as the fixture's video.id). */ upstreamJobId: string; /** Origin-validated absolute upstream URL proxied on every client poll. */ upstreamPollingUrl: string; /** * Match snapshot built at submit time (post requestTransform). Its `model` * is the submitted model as recorded by the standard model-normalization * rules — date suffixes stripped unless `recordFullModelVersion`; model-less * submits record the assumed default model. */ match: Fixture["match"]; /** * Upstream content URLs from a completed poll, stored under proxyOnly and * during the capturing window so the content endpoint can live-proxy the * bytes (never cached). Stored UNFILTERED — positions must line up with the * indexes the rewritten relay handed the client — so entries may be * non-strings; the content proxy skips unusable entries at use time. */ upstreamUnsignedUrls?: unknown[]; /** * Set synchronously before the first await of the eager-capture sequence so * a concurrent completed poll relays the upstream body instead of starting * a second capture/persist. */ capturing?: boolean; /** * Latches for the per-poll upstream-defect warns in rewriteRecordPollBody * (mirrors emptyErrorWarned): a polling loop must surface each defect once * per job, not once per poll. */ nonArrayUrlsWarned?: boolean; badCostWarned?: boolean; } type OpenRouterVideoJob = OpenRouterVideoReplayJob | OpenRouterVideoRecordJob; /** * Per-testId job state for the OpenRouter video handler. Mirrors * FalQueueStateMap (fal.ts): lazy TTL eviction on `get`, FIFO eviction of the * oldest entries on `set` when over capacity, no background sweep timer. * Deliberate divergences from FalQueueStateMap: * - lifetime: this map is per-server-instance (cleared on server * close/reset) while FalQueueStateMap is module-global; * - `set()` refreshes: delete-before-set moves a re-inserted key to the * back of the FIFO order AND resets its createdAt, so a refreshed entry * gets a fresh TTL — FalQueueStateMap's plain overwrite keeps the * original insertion slot and is never used as a TTL refresh. * Keys are `${testId}:${jobId}`. */ declare class OpenRouterVideoJobMap { private readonly entries; private worldGeneration; /** * Monotonic world-generation counter, incremented by `clear()` (a fixtures * reset). Identity checks (`jobs.get(key) === job`) can only guard * continuations whose job was ALREADY inserted — a continuation that has * not inserted yet (the submit proxy's upstream fetch) captures this value * before its await and compares after, so it can detect that the world it * belongs to was reset mid-flight and skip seeding the new world. */ get generation(): number; get(key: string): OpenRouterVideoJob | undefined; set(key: string, job: OpenRouterVideoJob): void; delete(key: string): boolean; clear(): void; get size(): number; } declare function handleOpenRouterVideoStatus(req: http$1.IncomingMessage, res: http$1.ServerResponse, jobId: string, fixtures: Fixture[], journal: Journal, defaults: HandlerDefaults, setCorsHeaders: (res: http$1.ServerResponse) => void, jobs: OpenRouterVideoJobMap): Promise; declare function handleOpenRouterVideoContent(req: http$1.IncomingMessage, res: http$1.ServerResponse, jobId: string, journal: Journal, defaults: HandlerDefaults, setCorsHeaders: (res: http$1.ServerResponse) => void, jobs: OpenRouterVideoJobMap): Promise; /** * Synthesizes the OpenRouter video model listing from loaded fixtures — * video-endpoint fixtures with a string `match.model` (mirrors the Ollama * `/api/tags` synthesis in server.ts). Falls back to a default model set when * no video fixtures are loaded. Note video models do not appear in the plain * `/api/v1/models` listing on the real API, hence the dedicated route. * * With `record.providers.openrouter` configured the listing is proxied * upstream instead and relayed verbatim on success (journaled * source:"proxy", never recorded as a fixture); an upstream failure warns * and falls back to the synthesis below. Strict mode disables the proxy — * a strict request is always served the synthesized listing (strict means * "nothing reaches an upstream"). */ declare function handleOpenRouterVideoModels(req: http$1.IncomingMessage, res: http$1.ServerResponse, fixtures: Fixture[], journal: Journal, defaults: HandlerDefaults, setCorsHeaders: (res: http$1.ServerResponse) => void): Promise; declare function handleOpenRouterVideoCreate(req: http$1.IncomingMessage, res: http$1.ServerResponse, raw: string, fixtures: Fixture[], journal: Journal, defaults: HandlerDefaults, setCorsHeaders: (res: http$1.ServerResponse) => void, jobs: OpenRouterVideoJobMap): Promise; /** * Default cap on the DECODED byte size embedded as `b64` in a recorded * fixture (32 MB). Override per-server via * `record.openRouterVideo.maxContentBytes` (0 = unlimited; negative or * non-integer values are treated as the default, with a createServer warn). * The cap protects disk AND memory: a capture whose upstream response * DECLARES an over-cap Content-Length is skipped without downloading, while * a response with no declared length is read as a stream with the byte count * enforced during the read — on exceed the download aborts with nothing * oversized retained in memory. In both cases the fixture is persisted * without `b64` and the same-session job serves the placeholder MP4. */ declare const OPENROUTER_VIDEO_DEFAULT_MAX_CONTENT_BYTES: number; //#endregion export { OPENROUTER_VIDEO_DEFAULT_MAX_CONTENT_BYTES, OPENROUTER_VIDEO_MAX_ENTRIES, OpenRouterVideoJobMap, handleOpenRouterVideoContent, handleOpenRouterVideoCreate, handleOpenRouterVideoModels, handleOpenRouterVideoStatus }; //# sourceMappingURL=openrouter-video.d.ts.map