import * as z from "zod"; import { Id } from "./ids.js"; import { MediaCheckSchema, MediaPlatformIdSchema, MediaSkippedTargetSchema, } from "./media-platforms.js"; import { MediaPresetIdSchema } from "./media-presets.js"; /** What a media job does. Generation runs on the configured image/video backend, edits run locally. */ export const MediaOperationSchema = z.enum([ "generate_image", "generate_video", "edit_image", "edit_video", "export_video", "transcribe", "analyze_video", ]); export type MediaOperation = z.infer; /** `waiting` means the job is queued behind another GPU job or for free GPU memory. */ export const MediaJobStatusSchema = z.enum([ "queued", "waiting", "running", "done", "failed", "cancelled", ]); export type MediaJobStatus = z.infer; export const MEDIA_JOB_ACTIVE_STATUSES = [ "queued", "waiting", "running", ] as const satisfies readonly MediaJobStatus[]; export const MediaOutputKindSchema = z.enum(["image", "video", "audio", "file"]); export type MediaOutputKind = z.infer; export const MediaOutputSchema = z.object({ artifactId: Id, kind: MediaOutputKindSchema, mimeType: z.string(), name: z.string(), size: z.number().int().nonnegative(), width: z.number().int().positive().optional(), height: z.number().int().positive().optional(), durationMs: z.number().int().nonnegative().optional(), posterArtifactId: Id.optional(), /** The artifact this output was made from, for version history. */ parentArtifactId: Id.optional(), preset: MediaPresetIdSchema.optional(), /** The platform it was exported for, and how it measured against that platform's limits. */ platform: MediaPlatformIdSchema.optional(), check: MediaCheckSchema.optional(), }); export type MediaOutput = z.infer; /** The live media card a job keeps up to date in the conversation. */ export const MediaJobBlockSchema = z.object({ kind: z.literal("media"), jobId: Id, operation: MediaOperationSchema, status: MediaJobStatusSchema, /** Short label: the prompt, or what the edit does. */ title: z.string(), progress: z.number().min(0).max(1).optional(), error: z.string().optional(), outputs: z.array(MediaOutputSchema), /** Platforms an export did not render, each with the reason. */ skipped: z.array(MediaSkippedTargetSchema).optional(), }); export type MediaJobBlock = z.infer; export const VideoBlockSchema = z.object({ kind: z.literal("video"), artifactId: Id, mimeType: z.string(), name: z.string(), size: z.number().int().nonnegative(), durationMs: z.number().int().nonnegative().optional(), width: z.number().int().positive().optional(), height: z.number().int().positive().optional(), posterArtifactId: Id.optional(), }); export type VideoBlock = z.infer; export const AudioBlockSchema = z.object({ kind: z.literal("audio"), artifactId: Id, mimeType: z.string(), name: z.string(), size: z.number().int().nonnegative(), durationMs: z.number().int().nonnegative().optional(), }); export type AudioBlock = z.infer;