diff --git a/src/adapters/image.ts b/src/adapters/image.ts index 89136aa..3a16e34 100644 --- a/src/adapters/image.ts +++ b/src/adapters/image.ts @@ -1,7 +1,10 @@ import type { ImageModels } from "@decartai/sdk"; import type { GeneratedImage, ImageGenerationOptions, ImageGenerationResult } from "@tanstack/ai"; import { BaseImageAdapter } from "@tanstack/ai/adapters"; -import type { DecartImageProviderOptions } from "../image/image-provider-options"; +import type { + DecartImageModelProviderOptionsByName, + DecartImageProviderOptions, +} from "../image/image-provider-options"; import { validatePrompt } from "../image/image-provider-options"; import type { DecartImageModel } from "../model-meta"; import { blobToBase64, createClient, generateId, getDecartApiKeyFromEnv, mapSizeToResolution, models } from "../utils"; @@ -11,13 +14,26 @@ export interface DecartImageConfig { baseUrl?: string; } -export class DecartImageAdapter extends BaseImageAdapter { +/** + * Decart Image Generation Adapter + * + * Tree-shakeable adapter for Decart image generation functionality. + * Supports lucy-pro-t2i model. + * + * Features: + * - Model-specific type-safe provider options + * - Resolution and orientation configuration + * - Seed support for reproducible generation + */ +export class DecartImageAdapter< + TModel extends DecartImageModel, +> extends BaseImageAdapter { readonly kind = "image" as const; readonly name = "decart" as const; private client: ReturnType; - constructor(config: DecartImageConfig, model: DecartImageModel) { + constructor(config: DecartImageConfig, model: TModel) { super(config, model); this.client = createClient(config); } @@ -50,15 +66,18 @@ export class DecartImageAdapter extends BaseImageAdapter( + model: TModel, apiKey: string, config?: Omit, -): DecartImageAdapter { +): DecartImageAdapter { return new DecartImageAdapter({ apiKey, ...config }, model); } -export function decartImage(model: DecartImageModel, config?: Omit): DecartImageAdapter { +export function decartImage( + model: TModel, + config?: Omit, +): DecartImageAdapter { const apiKey = getDecartApiKeyFromEnv(); return createDecartImage(model, apiKey, config); } diff --git a/src/adapters/video.ts b/src/adapters/video.ts index c00da4a..3412f8b 100644 --- a/src/adapters/video.ts +++ b/src/adapters/video.ts @@ -11,13 +11,15 @@ export interface DecartVideoConfig { baseUrl?: string; } -export class DecartVideoAdapter extends BaseVideoAdapter { +export class DecartVideoAdapter< + TModel extends DecartVideoModel, +> extends BaseVideoAdapter { readonly kind = "video" as const; readonly name = "decart" as const; private client: ReturnType; - constructor(config: DecartVideoConfig, model: DecartVideoModel) { + constructor(config: DecartVideoConfig, model: TModel) { super(config, model); this.client = createClient(config); } @@ -66,15 +68,18 @@ export class DecartVideoAdapter extends BaseVideoAdapter( + model: TModel, apiKey: string, config?: Omit, -): DecartVideoAdapter { +): DecartVideoAdapter { return new DecartVideoAdapter({ apiKey, ...config }, model); } -export function decartVideo(model: DecartVideoModel, config?: Omit): DecartVideoAdapter { +export function decartVideo( + model: TModel, + config?: Omit, +): DecartVideoAdapter { const apiKey = getDecartApiKeyFromEnv(); return createDecartVideo(model, apiKey, config); } diff --git a/src/image/image-provider-options.ts b/src/image/image-provider-options.ts index a005c27..f7873e7 100644 --- a/src/image/image-provider-options.ts +++ b/src/image/image-provider-options.ts @@ -1,9 +1,16 @@ +export type DecartImageResolution = "720p"; +export type DecartImageOrientation = "portrait" | "landscape"; + export interface DecartImageProviderOptions { seed?: number; - resolution?: "720p" | "480p"; - orientation?: "portrait" | "landscape"; + resolution?: DecartImageResolution; + orientation?: DecartImageOrientation; } +export type DecartImageModelProviderOptionsByName = { + "lucy-pro-t2i": DecartImageProviderOptions; +}; + export function validatePrompt(prompt: string): void { if (!prompt || prompt.length === 0) { throw new Error("Prompt cannot be empty."); diff --git a/src/index.ts b/src/index.ts index f0ee7dc..eb4b396 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,12 +10,25 @@ export { type DecartVideoConfig, decartVideo, } from "./adapters/video"; -export type { DecartImageProviderOptions } from "./image/image-provider-options"; +export type { + DecartImageModelProviderOptionsByName, + DecartImageOrientation, + DecartImageProviderOptions, + DecartImageResolution, +} from "./image/image-provider-options"; export { DECART_IMAGE_MODELS, DECART_VIDEO_MODELS, type DecartImageModel, + type DecartModelInputModalitiesByName, type DecartVideoModel, + LUCY_PRO_T2I, + LUCY_PRO_T2V, } from "./model-meta"; export { VERSION } from "./version"; -export type { DecartVideoProviderOptions } from "./video/video-provider-options"; +export type { + DecartVideoModelProviderOptionsByName, + DecartVideoOrientation, + DecartVideoProviderOptions, + DecartVideoResolution, +} from "./video/video-provider-options"; diff --git a/src/model-meta.ts b/src/model-meta.ts index c357558..a61aac9 100644 --- a/src/model-meta.ts +++ b/src/model-meta.ts @@ -1,5 +1,65 @@ -export const DECART_IMAGE_MODELS = ["lucy-pro-t2i"] as const; +import type { DecartImageProviderOptions } from "./image/image-provider-options"; +import type { DecartVideoProviderOptions } from "./video/video-provider-options"; + +interface DecartModelMeta { + name: string; + supports: { + input: ReadonlyArray<"text" | "image" | "video">; + output: ReadonlyArray<"image" | "video">; + endpoints: ReadonlyArray<"image-generation" | "video">; + }; + pricing: { + resolution720p: number; + resolution480p?: number; + unit: "per-image" | "per-second"; + }; + providerOptions?: TProviderOptions; +} + +/** + * Lucy Pro T2I - Text-to-Image generation model. + * + * @see https://docs.platform.decart.ai/models/image/image-generation + */ +export const LUCY_PRO_T2I = { + name: "lucy-pro-t2i", + supports: { + input: ["text"] as const, + output: ["image"] as const, + endpoints: ["image-generation"] as const, + }, + pricing: { + resolution720p: 0.02, + unit: "per-image" as const, + }, +} as const satisfies DecartModelMeta; + +/** + * Lucy Pro T2V - Text-to-Video generation model. + * + * @see https://docs.platform.decart.ai/models/video/video-generation + */ +export const LUCY_PRO_T2V = { + name: "lucy-pro-t2v", + supports: { + input: ["text"] as const, + output: ["video"] as const, + endpoints: ["video"] as const, + }, + pricing: { + resolution720p: 0.08, + resolution480p: 0.04, + unit: "per-second" as const, + }, +} as const satisfies DecartModelMeta; + +export const DECART_IMAGE_MODELS = [LUCY_PRO_T2I.name] as const; export type DecartImageModel = (typeof DECART_IMAGE_MODELS)[number]; -export const DECART_VIDEO_MODELS = ["lucy-pro-t2v"] as const; +export const DECART_VIDEO_MODELS = [LUCY_PRO_T2V.name] as const; export type DecartVideoModel = (typeof DECART_VIDEO_MODELS)[number]; + +export type DecartModelInputModalitiesByName = { + [LUCY_PRO_T2I.name]: typeof LUCY_PRO_T2I.supports.input; + [LUCY_PRO_T2V.name]: typeof LUCY_PRO_T2V.supports.input; +}; diff --git a/src/video/video-provider-options.ts b/src/video/video-provider-options.ts index 22af024..3094b8b 100644 --- a/src/video/video-provider-options.ts +++ b/src/video/video-provider-options.ts @@ -1,9 +1,16 @@ +export type DecartVideoResolution = "720p" | "480p"; +export type DecartVideoOrientation = "portrait" | "landscape"; + export interface DecartVideoProviderOptions { seed?: number; - resolution?: "720p" | "480p"; - orientation?: string; + resolution?: DecartVideoResolution; + orientation?: DecartVideoOrientation; } +export type DecartVideoModelProviderOptionsByName = { + "lucy-pro-t2v": DecartVideoProviderOptions; +}; + export function validatePrompt(prompt: string | undefined): void { if (!prompt || prompt.length === 0) { throw new Error("Prompt is required");