SPB Git

Repository Public

types.ts 3.6 KB 80 lines typescript

1import type { z } from "zod";23/** Provider-neutral interfaces. Application code depends on these, never on a vendor SDK. */45export type CostSource = "ticks" | "computed" | "unknown";6export interface Usage { costUsd: number | null; source: CostSource; inputTokens?: number; outputTokens?: number }78export class ProviderError extends Error {9  constructor(message: string, readonly opts: { status?: number; code?: string; retryable: boolean; billed?: boolean } = { retryable: false }) {10    super(message);11    this.name = "ProviderError";12  }13  get retryable() { return this.opts.retryable; }14}1516export interface LLMRequest<T extends z.ZodType> {17  name: string;18  schema: T;19  system: string;20  user: string;21  /** JPEG/PNG images for multimodal critique. */22  images?: { bytes: Buffer; mime: string }[];23  effort?: "none" | "low" | "medium" | "high" | "xhigh";24  model?: string;25}26export interface LLMResult<T> { data: T; usage: Usage; model: string }27export interface LLMProvider {28  generateStructured<T extends z.ZodType>(req: LLMRequest<T>): Promise<LLMResult<z.infer<T>>>;29  /** Same call shape; kept separate so a different (vision) model can be routed. */30  critique<T extends z.ZodType>(req: LLMRequest<T>): Promise<LLMResult<z.infer<T>>>;31  /** Structured answer grounded by web search; `citations` are the URLs the provider reports. */32  research<T extends z.ZodType>(req: LLMRequest<T>): Promise<LLMResult<z.infer<T>> & { citations: string[] }>;33}3435export type AspectRatio = "9:16" | "1:1" | "16:9";36export interface ImageRequest { prompt: string; aspectRatio: AspectRatio; resolution?: "1k" | "1.5k" | "2k"; quality?: "low" | "medium"; model?: string }37export interface ImageResult { bytes: Buffer; mime: string; usage: Usage; model: string }38export interface ImageProvider {39  generate(req: ImageRequest): Promise<ImageResult>;40  edit(req: ImageRequest & { image: { bytes: Buffer; mime: string } }): Promise<ImageResult>;41}4243export type VideoResolution = "480p" | "720p" | "1080p";44export interface VideoRequest {45  model: string;46  prompt: string;47  duration: number;48  resolution: VideoResolution;49  aspectRatio?: AspectRatio;50  image?: { bytes: Buffer; mime: string };51  referenceImages?: { bytes: Buffer; mime: string }[];52}53export interface VideoStatus {54  status: "pending" | "done" | "failed";55  progress: number | null;56  url?: string;57  duration?: number;58  moderationOk?: boolean;59  usage: Usage;60  error?: { code: string; message: string };61}62export interface VideoProvider {63  /** Submits and returns the provider request id: persist it before polling. */64  submit(req: VideoRequest): Promise<{ requestId: string }>;65  poll(requestId: string): Promise<VideoStatus>;66  download(url: string): Promise<Buffer>;67  textToVideo(req: Omit<VideoRequest, "image" | "referenceImages">): Promise<{ requestId: string }>;68  imageToVideo(req: VideoRequest & { image: { bytes: Buffer; mime: string } }): Promise<{ requestId: string }>;69  referenceToVideo(req: VideoRequest & { referenceImages: { bytes: Buffer; mime: string }[] }): Promise<{ requestId: string }>;70  editVideo?(req: { model: string; prompt: string; videoUrl: string }): Promise<{ requestId: string }>;71}7273export interface SpeechRequest { text: string; voiceId: string; language: "en" | "fr"; speed?: number }74export interface CharTiming { char: string; start: number; end: number }75export interface SpeechResult { bytes: Buffer; mime: string; duration: number; chars: CharTiming[]; usage: Usage }76export interface SpeechProvider {77  synthesize(req: SpeechRequest): Promise<SpeechResult>;78  voices(): Promise<{ id: string; name: string; gender: string }[]>;79}80
Files main
Menu

Theme