@shop-os/modelkit 0.2.0 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -219,8 +219,9 @@ interface CatalogDisplay {
219
219
  /** Chat picker highlight flag. */
220
220
  recommended?: boolean;
221
221
  /**
222
- * Picker position: lower comes first; rows without one keep catalog order
223
- * after the ordered ones. Set it to surface a new model at the top.
222
+ * Picker position: higher comes first; rows without one keep catalog order
223
+ * after the ordered ones. Give a new model the next number up to surface
224
+ * it at the top.
224
225
  */
225
226
  sortOrder?: number;
226
227
  /**
@@ -429,6 +430,23 @@ declare const ADAPTER_IDS: readonly ["ai-sdk-text", "google-image", "openai-imag
429
430
  declare const CatalogModelSchema: z.ZodType<CatalogModel>;
430
431
  declare const CatalogSchema: z.ZodType<CatalogModel[]>;
431
432
 
433
+ type CatalogOrigin = "remote" | "last-good" | "snapshot";
434
+ interface PrimeCatalogResult {
435
+ origin: CatalogOrigin;
436
+ rowCount: number;
437
+ revision?: string;
438
+ error?: string;
439
+ }
440
+ interface LiveCatalogState {
441
+ catalog: Catalog;
442
+ memo: Promise<PrimeCatalogResult> | undefined;
443
+ timer: (ReturnType<typeof setInterval> & {
444
+ unref?: () => void;
445
+ }) | undefined;
446
+ revision: string | undefined;
447
+ origin: CatalogOrigin;
448
+ }
449
+ declare const liveState: LiveCatalogState;
432
450
  declare const liveCatalog: Catalog;
433
451
 
434
452
  interface CatalogCache {
@@ -450,16 +468,14 @@ interface CatalogSource {
450
468
  fetch?: typeof fetch;
451
469
  logger?: Pick<Console, "debug" | "info" | "warn" | "error">;
452
470
  }
453
- type CatalogOrigin = "remote" | "last-good" | "snapshot";
454
- interface PrimeCatalogResult {
455
- origin: CatalogOrigin;
456
- rowCount: number;
471
+
472
+ interface CatalogEnvelope {
473
+ rows: CatalogModel[];
457
474
  revision?: string;
458
- error?: string;
459
475
  }
460
476
  /** Fetch, validate, swap into liveCatalog. Never throws. Second call returns the same promise. */
461
477
  declare function primeCatalog(source: CatalogSource): Promise<PrimeCatalogResult>;
462
- /** Test seam: stop the refresh timer and reset liveCatalog to MODELS and clear the memo. */
478
+ /** Test seam: stop the refresh timer, reset liveCatalog to MODELS and clear the memo. */
463
479
  declare function resetLiveCatalog(): void;
464
480
 
465
481
  declare const IMAGE_MODELS: CatalogModel[];
@@ -516,4 +532,4 @@ declare function isModelKitError(err: unknown): err is ModelKitError;
516
532
  /** Resolve caller options against a catalog row, dispatching on `model.type`. */
517
533
  declare function resolveOptions(model: CatalogModel, request: ImageRequest | VideoRequest | AudioRequest, onUnsupported?: OnUnsupported): ResolveResult<ImageRequest | VideoRequest | AudioRequest>;
518
534
 
519
- export { ADAPTER_IDS, type AdapterEndpoints, type AdapterId, type AspectRatio, type AudioRequest, type AudioResult, type CallContext, Catalog, type CatalogAuth, type CatalogCache, type CatalogCapabilities, type CatalogDisplay, type CatalogModel, CatalogModelSchema, type CatalogOrigin, CatalogSchema, type CatalogSource, type GeneratedImage, IMAGE_MODELS, type ImageBytes, type ImageCallOptions, type ImageCallResult, type ImageQuality, type ImageRequest, type ImageResult, type ImageSafetySetting, type ImageSize, type JsonObject, type JsonPrimitive, type JsonValue, type Lifecycle, MODELS, type MediaPart, type MediaRef, type ModelConstraints, type ModelKitConfig, ModelKitError, type ModelKitErrorCode, type ModelKitErrorInit, type ModelType, OTHER_MODELS, type OnUnsupported, type OutputFormat, type PricingKind, type PrimeCatalogResult, type ProviderErrorBody, type ProviderKeyName, type ProviderKeys, type ProviderOptionValue, type ProviderOptions, type ReferenceLimits, type RequiredInput, type ResolveResult, type Routing, type SupportedOption, TEXT_MODELS, type UpscaleOptions, type UsageEvent, type UsageModality, type UsageUnit, VIDEO_MODELS, type VideoCallJob, type VideoCallOptions, type VideoJob, type VideoModel, type VideoRequest, type VideoResolution, type VideoResult, type Warning, isModelKitError, liveCatalog, nearestAspectRatio, primeCatalog, resetLiveCatalog, resolveAudioOptions, resolveImageOptions, resolveOptions, resolveVideoOptions };
535
+ export { ADAPTER_IDS, type AdapterEndpoints, type AdapterId, type AspectRatio, type AudioRequest, type AudioResult, type CallContext, Catalog, type CatalogAuth, type CatalogCache, type CatalogCapabilities, type CatalogDisplay, type CatalogEnvelope, type CatalogModel, CatalogModelSchema, type CatalogOrigin, CatalogSchema, type CatalogSource, type GeneratedImage, IMAGE_MODELS, type ImageBytes, type ImageCallOptions, type ImageCallResult, type ImageQuality, type ImageRequest, type ImageResult, type ImageSafetySetting, type ImageSize, type JsonObject, type JsonPrimitive, type JsonValue, type Lifecycle, type LiveCatalogState, MODELS, type MediaPart, type MediaRef, type ModelConstraints, type ModelKitConfig, ModelKitError, type ModelKitErrorCode, type ModelKitErrorInit, type ModelType, OTHER_MODELS, type OnUnsupported, type OutputFormat, type PricingKind, type PrimeCatalogResult, type ProviderErrorBody, type ProviderKeyName, type ProviderKeys, type ProviderOptionValue, type ProviderOptions, type ReferenceLimits, type RequiredInput, type ResolveResult, type Routing, type SupportedOption, TEXT_MODELS, type UpscaleOptions, type UsageEvent, type UsageModality, type UsageUnit, VIDEO_MODELS, type VideoCallJob, type VideoCallOptions, type VideoJob, type VideoModel, type VideoRequest, type VideoResolution, type VideoResult, type Warning, isModelKitError, liveCatalog, liveState, nearestAspectRatio, primeCatalog, resetLiveCatalog, resolveAudioOptions, resolveImageOptions, resolveOptions, resolveVideoOptions };
package/dist/catalog.d.ts CHANGED
@@ -219,8 +219,9 @@ interface CatalogDisplay {
219
219
  /** Chat picker highlight flag. */
220
220
  recommended?: boolean;
221
221
  /**
222
- * Picker position: lower comes first; rows without one keep catalog order
223
- * after the ordered ones. Set it to surface a new model at the top.
222
+ * Picker position: higher comes first; rows without one keep catalog order
223
+ * after the ordered ones. Give a new model the next number up to surface
224
+ * it at the top.
224
225
  */
225
226
  sortOrder?: number;
226
227
  /**
@@ -429,6 +430,23 @@ declare const ADAPTER_IDS: readonly ["ai-sdk-text", "google-image", "openai-imag
429
430
  declare const CatalogModelSchema: z.ZodType<CatalogModel>;
430
431
  declare const CatalogSchema: z.ZodType<CatalogModel[]>;
431
432
 
433
+ type CatalogOrigin = "remote" | "last-good" | "snapshot";
434
+ interface PrimeCatalogResult {
435
+ origin: CatalogOrigin;
436
+ rowCount: number;
437
+ revision?: string;
438
+ error?: string;
439
+ }
440
+ interface LiveCatalogState {
441
+ catalog: Catalog;
442
+ memo: Promise<PrimeCatalogResult> | undefined;
443
+ timer: (ReturnType<typeof setInterval> & {
444
+ unref?: () => void;
445
+ }) | undefined;
446
+ revision: string | undefined;
447
+ origin: CatalogOrigin;
448
+ }
449
+ declare const liveState: LiveCatalogState;
432
450
  declare const liveCatalog: Catalog;
433
451
 
434
452
  interface CatalogCache {
@@ -450,16 +468,14 @@ interface CatalogSource {
450
468
  fetch?: typeof fetch;
451
469
  logger?: Pick<Console, "debug" | "info" | "warn" | "error">;
452
470
  }
453
- type CatalogOrigin = "remote" | "last-good" | "snapshot";
454
- interface PrimeCatalogResult {
455
- origin: CatalogOrigin;
456
- rowCount: number;
471
+
472
+ interface CatalogEnvelope {
473
+ rows: CatalogModel[];
457
474
  revision?: string;
458
- error?: string;
459
475
  }
460
476
  /** Fetch, validate, swap into liveCatalog. Never throws. Second call returns the same promise. */
461
477
  declare function primeCatalog(source: CatalogSource): Promise<PrimeCatalogResult>;
462
- /** Test seam: stop the refresh timer and reset liveCatalog to MODELS and clear the memo. */
478
+ /** Test seam: stop the refresh timer, reset liveCatalog to MODELS and clear the memo. */
463
479
  declare function resetLiveCatalog(): void;
464
480
 
465
481
  declare const IMAGE_MODELS: CatalogModel[];
@@ -516,4 +532,4 @@ declare function isModelKitError(err: unknown): err is ModelKitError;
516
532
  /** Resolve caller options against a catalog row, dispatching on `model.type`. */
517
533
  declare function resolveOptions(model: CatalogModel, request: ImageRequest | VideoRequest | AudioRequest, onUnsupported?: OnUnsupported): ResolveResult<ImageRequest | VideoRequest | AudioRequest>;
518
534
 
519
- export { ADAPTER_IDS, type AdapterEndpoints, type AdapterId, type AspectRatio, type AudioRequest, type AudioResult, type CallContext, Catalog, type CatalogAuth, type CatalogCache, type CatalogCapabilities, type CatalogDisplay, type CatalogModel, CatalogModelSchema, type CatalogOrigin, CatalogSchema, type CatalogSource, type GeneratedImage, IMAGE_MODELS, type ImageBytes, type ImageCallOptions, type ImageCallResult, type ImageQuality, type ImageRequest, type ImageResult, type ImageSafetySetting, type ImageSize, type JsonObject, type JsonPrimitive, type JsonValue, type Lifecycle, MODELS, type MediaPart, type MediaRef, type ModelConstraints, type ModelKitConfig, ModelKitError, type ModelKitErrorCode, type ModelKitErrorInit, type ModelType, OTHER_MODELS, type OnUnsupported, type OutputFormat, type PricingKind, type PrimeCatalogResult, type ProviderErrorBody, type ProviderKeyName, type ProviderKeys, type ProviderOptionValue, type ProviderOptions, type ReferenceLimits, type RequiredInput, type ResolveResult, type Routing, type SupportedOption, TEXT_MODELS, type UpscaleOptions, type UsageEvent, type UsageModality, type UsageUnit, VIDEO_MODELS, type VideoCallJob, type VideoCallOptions, type VideoJob, type VideoModel, type VideoRequest, type VideoResolution, type VideoResult, type Warning, isModelKitError, liveCatalog, nearestAspectRatio, primeCatalog, resetLiveCatalog, resolveAudioOptions, resolveImageOptions, resolveOptions, resolveVideoOptions };
535
+ export { ADAPTER_IDS, type AdapterEndpoints, type AdapterId, type AspectRatio, type AudioRequest, type AudioResult, type CallContext, Catalog, type CatalogAuth, type CatalogCache, type CatalogCapabilities, type CatalogDisplay, type CatalogEnvelope, type CatalogModel, CatalogModelSchema, type CatalogOrigin, CatalogSchema, type CatalogSource, type GeneratedImage, IMAGE_MODELS, type ImageBytes, type ImageCallOptions, type ImageCallResult, type ImageQuality, type ImageRequest, type ImageResult, type ImageSafetySetting, type ImageSize, type JsonObject, type JsonPrimitive, type JsonValue, type Lifecycle, type LiveCatalogState, MODELS, type MediaPart, type MediaRef, type ModelConstraints, type ModelKitConfig, ModelKitError, type ModelKitErrorCode, type ModelKitErrorInit, type ModelType, OTHER_MODELS, type OnUnsupported, type OutputFormat, type PricingKind, type PrimeCatalogResult, type ProviderErrorBody, type ProviderKeyName, type ProviderKeys, type ProviderOptionValue, type ProviderOptions, type ReferenceLimits, type RequiredInput, type ResolveResult, type Routing, type SupportedOption, TEXT_MODELS, type UpscaleOptions, type UsageEvent, type UsageModality, type UsageUnit, VIDEO_MODELS, type VideoCallJob, type VideoCallOptions, type VideoJob, type VideoModel, type VideoRequest, type VideoResolution, type VideoResult, type Warning, isModelKitError, liveCatalog, liveState, nearestAspectRatio, primeCatalog, resetLiveCatalog, resolveAudioOptions, resolveImageOptions, resolveOptions, resolveVideoOptions };
package/dist/catalog.js CHANGED
@@ -118,7 +118,13 @@ var GEMINI_RATIOS = [
118
118
  "5:4",
119
119
  "adaptive"
120
120
  ];
121
- function geminiImage(id, label, aliases, sizes, display, exposure) {
121
+ function geminiImage(id, label, aliases, sizes, display, exposure, references) {
122
+ const constraints = {
123
+ aspectRatios: [...GEMINI_RATIOS],
124
+ sizes,
125
+ supports: ["safetySettings", "temperature"]
126
+ };
127
+ if (references !== void 0) constraints.references = references;
122
128
  const model = {
123
129
  id,
124
130
  aliases,
@@ -128,11 +134,7 @@ function geminiImage(id, label, aliases, sizes, display, exposure) {
128
134
  providerModelId: id,
129
135
  lifecycle: "active",
130
136
  exposure,
131
- constraints: {
132
- aspectRatios: [...GEMINI_RATIOS],
133
- sizes,
134
- supports: ["safetySettings", "temperature"]
135
- },
137
+ constraints,
136
138
  defaults: { size: "1K", aspectRatio: "1:1" },
137
139
  usage: { ...IMAGE_USAGE, slug: "gemini" },
138
140
  pricingKind: "image_size",
@@ -151,7 +153,8 @@ var IMAGE_MODELS = [
151
153
  description: "Create stunning, production-quality visuals with exceptional realism, detail, and typography. Best for campaigns, e-commerce, product photography, and hero creatives.",
152
154
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
153
155
  },
154
- "catalog"
156
+ "catalog",
157
+ { images: 14 }
155
158
  ),
156
159
  geminiImage(
157
160
  "gemini-3.1-flash-image-preview",
@@ -164,7 +167,8 @@ var IMAGE_MODELS = [
164
167
  description: "Generate high-quality images at speed. Perfect for brainstorming, moodboards, concept testing, creative exploration, and large batch workflows.",
165
168
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
166
169
  },
167
- "catalog"
170
+ "catalog",
171
+ { images: 14 }
168
172
  ),
169
173
  geminiImage(
170
174
  "gemini-3.1-flash-lite-image",
@@ -176,14 +180,15 @@ var IMAGE_MODELS = [
176
180
  description: "The fastest and most affordable image model. Ideal for rapid drafts, bulk exploration, and iterative concept testing at 1K resolution.",
177
181
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
178
182
  },
179
- "catalog"
183
+ "catalog",
184
+ { images: 14 }
180
185
  ),
181
186
  // trigger-workflows validates 1K only; pricing seeds 2K/4K rows so allow all three.
182
187
  geminiImage(
183
188
  "gemini-2.5-flash-image",
184
189
  "Gemini 2.5 Flash Image",
185
190
  [],
186
- ["1K", "2K", "4K"],
191
+ ["1K"],
187
192
  {
188
193
  provider: "google",
189
194
  description: "Nano Banana (legacy Gemini 2.5 Flash Image) native image generation and editing model for high-volume, low-latency creative workflows."
@@ -214,7 +219,7 @@ var IMAGE_MODELS = [
214
219
  sizes: ["1K", "2K", "4K"],
215
220
  qualityOptions: ["auto", "low", "medium", "high"],
216
221
  references: { images: 16 },
217
- supports: ["quality", "count"]
222
+ supports: ["quality", "count", "outputFormat"]
218
223
  },
219
224
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
220
225
  usage: { ...IMAGE_USAGE, slug: "gpt" },
@@ -234,7 +239,7 @@ var IMAGE_MODELS = [
234
239
  adapter: "openai-image",
235
240
  providerModelId: "gpt-image-2.5-sunburst",
236
241
  lifecycle: "active",
237
- exposure: "internal",
242
+ exposure: "catalog",
238
243
  constraints: {
239
244
  exactSizes: {
240
245
  "1:1": "1024x1024",
@@ -247,15 +252,16 @@ var IMAGE_MODELS = [
247
252
  },
248
253
  aspectRatios: ["1:1", "3:2", "2:3", "16:9", "9:16", "4:5", "5:4", "adaptive"],
249
254
  sizes: ["1K", "2K", "4K"],
250
- qualityOptions: ["auto", "low", "medium", "high"],
255
+ qualityOptions: ["auto", "low", "medium", "high", "xhigh", "max"],
251
256
  references: { images: 16 },
252
- supports: ["quality", "count"]
257
+ supports: ["quality", "count", "outputFormat"]
253
258
  },
254
259
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
255
260
  usage: { ...IMAGE_USAGE },
256
261
  pricingKind: "image_size",
257
262
  display: {
258
263
  provider: "openai",
264
+ sortOrder: 20,
259
265
  description: "OpenAI's most capable GPT Image 2.5 tier, built for editing precision; takes text and image input and outputs images in low, medium, high, xhigh, or max quality."
260
266
  }
261
267
  },
@@ -268,7 +274,7 @@ var IMAGE_MODELS = [
268
274
  adapter: "openai-image",
269
275
  providerModelId: "gpt-image-2.5-flare",
270
276
  lifecycle: "active",
271
- exposure: "internal",
277
+ exposure: "catalog",
272
278
  constraints: {
273
279
  exactSizes: {
274
280
  "1:1": "1024x1024",
@@ -281,15 +287,16 @@ var IMAGE_MODELS = [
281
287
  },
282
288
  aspectRatios: ["1:1", "3:2", "2:3", "16:9", "9:16", "4:5", "5:4", "adaptive"],
283
289
  sizes: ["1K", "2K", "4K"],
284
- qualityOptions: ["auto", "low", "medium", "high"],
290
+ qualityOptions: ["auto", "low", "medium", "high", "xhigh", "max"],
285
291
  references: { images: 16 },
286
- supports: ["quality", "count"]
292
+ supports: ["quality", "count", "outputFormat"]
287
293
  },
288
294
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
289
295
  usage: { ...IMAGE_USAGE },
290
296
  pricingKind: "image_size",
291
297
  display: {
292
298
  provider: "openai",
299
+ sortOrder: 10,
293
300
  description: "OpenAI's fastest GPT Image 2.5 tier for high-quality everyday image generation and editing; takes text and image input and outputs images."
294
301
  }
295
302
  },
@@ -313,8 +320,6 @@ var IMAGE_MODELS = [
313
320
  "2:3",
314
321
  "3:4",
315
322
  "9:16",
316
- "4:5",
317
- "5:4",
318
323
  "9:21",
319
324
  "adaptive"
320
325
  ],
@@ -346,7 +351,7 @@ var IMAGE_MODELS = [
346
351
  references: { images: 10 },
347
352
  // Ark's Images API has no output-format, quality or count field; only
348
353
  // the seed is forwarded, so anything else must warn, not vanish.
349
- supports: ["seed"]
354
+ supports: ["seed", "outputFormat"]
350
355
  },
351
356
  defaults: { size: "1K", aspectRatio: "1:1" },
352
357
  usage: { ...IMAGE_USAGE },
@@ -382,7 +387,7 @@ var IMAGE_MODELS = [
382
387
  "21:9",
383
388
  "9:21"
384
389
  ],
385
- sizes: ["1K", "2K", "4K"],
390
+ sizes: ["2K", "4K"],
386
391
  references: { images: 10 },
387
392
  supports: ["seed"]
388
393
  },
@@ -434,7 +439,7 @@ var IMAGE_MODELS = [
434
439
  aspectRatios: ["1:1", "2:3", "3:2", "4:3", "3:4", "4:5", "5:4", "9:16", "16:9", "21:9"],
435
440
  sizes: ["1K", "2K", "4K"],
436
441
  requires: ["references"],
437
- supports: ["seed"]
442
+ supports: []
438
443
  },
439
444
  defaults: { size: "1K", aspectRatio: "1:1" },
440
445
  usage: { ...IMAGE_USAGE },
@@ -459,7 +464,7 @@ var IMAGE_MODELS = [
459
464
  aspectRatios: ["1:1", "2:3", "3:4", "4:3", "9:16", "16:9", "21:9"],
460
465
  sizes: ["1K"],
461
466
  requires: ["references"],
462
- supports: ["seed"]
467
+ supports: []
463
468
  },
464
469
  defaults: { size: "1K", aspectRatio: "1:1" },
465
470
  usage: { ...IMAGE_USAGE },
@@ -511,7 +516,6 @@ var IMAGE_MODELS = [
511
516
  aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"],
512
517
  sizes: [],
513
518
  references: { images: 1 },
514
- requires: ["references"],
515
519
  supports: []
516
520
  },
517
521
  defaults: { aspectRatio: "1:1" },
@@ -1230,7 +1234,7 @@ var VIDEO_MODELS = [
1230
1234
  resolutions: ["720p", "1080p", "4k"],
1231
1235
  durations: [8],
1232
1236
  references: { images: 3 },
1233
- supports: ["lastFrame"]
1237
+ supports: ["lastFrame", "seed"]
1234
1238
  },
1235
1239
  defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
1236
1240
  usage: { ...VIDEO_USAGE, slug: "veo" },
@@ -1258,9 +1262,9 @@ var VIDEO_MODELS = [
1258
1262
  constraints: {
1259
1263
  aspectRatios: [...OMNI_RATIOS],
1260
1264
  resolutions: ["720p", "1080p", "4k"],
1261
- durations: [4, 8],
1265
+ durations: [4, 6, 8],
1262
1266
  references: { images: 3 },
1263
- supports: ["lastFrame"]
1267
+ supports: ["lastFrame", "seed"]
1264
1268
  },
1265
1269
  defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
1266
1270
  usage: { ...VIDEO_USAGE },
@@ -1287,9 +1291,8 @@ var VIDEO_MODELS = [
1287
1291
  constraints: {
1288
1292
  aspectRatios: [...OMNI_RATIOS],
1289
1293
  resolutions: ["720p", "1080p"],
1290
- durations: [4, 8],
1291
- references: { images: 3 },
1292
- supports: ["lastFrame"]
1294
+ durations: [4, 6, 8],
1295
+ supports: ["lastFrame", "seed"]
1293
1296
  },
1294
1297
  defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
1295
1298
  usage: { ...VIDEO_USAGE },
@@ -1321,7 +1324,7 @@ var VIDEO_MODELS = [
1321
1324
  // reference clip keeps its own framing.
1322
1325
  aspectRatios: [...OMNI_RATIOS],
1323
1326
  durations: [3, 4, 5, 6, 7, 8, 9, 10],
1324
- references: { images: 6, videos: 1 },
1327
+ references: { images: 6, videos: 3 },
1325
1328
  supports: []
1326
1329
  },
1327
1330
  defaults: {},
@@ -1347,7 +1350,7 @@ var VIDEO_MODELS = [
1347
1350
  aspectRatios: [...OMNI_RATIOS],
1348
1351
  resolutions: ["360p", "720p", "1080p", "4k"],
1349
1352
  durations: [3, 4, 5, 6, 7, 8, 9, 10],
1350
- references: { images: 6, videos: 1 },
1353
+ references: { images: 6, videos: 3 },
1351
1354
  supports: []
1352
1355
  },
1353
1356
  defaults: {},
@@ -1376,7 +1379,7 @@ var VIDEO_MODELS = [
1376
1379
  durations: { min: 4, max: 15 },
1377
1380
  durationPresets: [4, 6, 8, 10, 12, 15],
1378
1381
  references: { images: 9, videos: 3, audios: 3, audioOnly: false },
1379
- ratioIgnoredWith: ["firstFrame"],
1382
+ ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1380
1383
  supports: ["generateAudio", "seed", "lastFrame", "watermark"]
1381
1384
  },
1382
1385
  defaults: {
@@ -1408,7 +1411,7 @@ var VIDEO_MODELS = [
1408
1411
  resolutions: ["480p", "720p"],
1409
1412
  durations: { min: 4, max: 15 },
1410
1413
  references: { images: 9, videos: 3, audios: 3, audioOnly: false },
1411
- ratioIgnoredWith: ["firstFrame"],
1414
+ ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1412
1415
  supports: ["generateAudio", "seed", "lastFrame", "watermark"]
1413
1416
  },
1414
1417
  defaults: {
@@ -1441,7 +1444,7 @@ var VIDEO_MODELS = [
1441
1444
  resolutions: ["480p", "720p", "1080p"],
1442
1445
  durations: { min: 4, max: 30 },
1443
1446
  references: { images: 30, videos: 10, audios: 10 },
1444
- ratioIgnoredWith: ["firstFrame"],
1447
+ ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1445
1448
  supports: ["generateAudio", "seed", "lastFrame", "watermark"]
1446
1449
  },
1447
1450
  defaults: {
@@ -1560,18 +1563,7 @@ var VIDEO_MODELS = [
1560
1563
  lifecycle: "active",
1561
1564
  exposure: "catalog",
1562
1565
  constraints: {
1563
- aspectRatios: [
1564
- "1:1",
1565
- "16:9",
1566
- "9:16",
1567
- "4:3",
1568
- "3:4",
1569
- "3:2",
1570
- "2:3",
1571
- "21:9",
1572
- "4:5",
1573
- "adaptive"
1574
- ],
1566
+ aspectRatios: [...KLING_RATIOS],
1575
1567
  resolutions: ["720p", "1080p"],
1576
1568
  durations: { min: 3, max: 15 },
1577
1569
  references: { images: 7 },
@@ -2033,30 +2025,34 @@ var CatalogSchema = z.array(CatalogModelSchemaBase).superRefine((rows, ctx) => {
2033
2025
  });
2034
2026
 
2035
2027
  // src/catalog/live.ts
2036
- var liveCatalog = new Catalog(MODELS);
2028
+ var KEY = /* @__PURE__ */ Symbol.for("@shop-os/modelkit/live-catalog");
2029
+ var store = globalThis;
2030
+ var liveState = store[KEY] ??= {
2031
+ catalog: new Catalog(MODELS),
2032
+ memo: void 0,
2033
+ timer: void 0,
2034
+ revision: void 0,
2035
+ origin: "snapshot"
2036
+ };
2037
+ var liveCatalog = liveState.catalog;
2037
2038
 
2038
2039
  // src/catalog/load.ts
2039
- var memo;
2040
- var timer;
2041
- var revision;
2042
- var origin = "snapshot";
2040
+ import { z as z2 } from "zod";
2043
2041
  function rowCount() {
2044
2042
  return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
2045
2043
  }
2046
2044
  function authHeaders(auth) {
2047
2045
  return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
2048
2046
  }
2049
- function describeError(err) {
2050
- return err instanceof Error ? err.message : String(err);
2051
- }
2052
- function parseEnvelope(json) {
2053
- if (typeof json !== "object" || json === null || !("rows" in json)) {
2054
- throw new Error("invalid catalog response: missing rows");
2055
- }
2056
- const rows = CatalogSchema.parse(json.rows);
2057
- const rev = json.revision;
2058
- if (typeof rev === "string") return { rows, revision: rev };
2059
- return { rows };
2047
+ var EnvelopeSchema = z2.object({
2048
+ rows: CatalogSchema,
2049
+ revision: z2.string().optional()
2050
+ });
2051
+ function toEnvelope(data) {
2052
+ if (data.rows.length === 0) throw new Error("invalid catalog response: no rows");
2053
+ const envelope = { rows: data.rows };
2054
+ if (data.revision !== void 0) envelope.revision = data.revision;
2055
+ return envelope;
2060
2056
  }
2061
2057
  function logPrimed(logger, result) {
2062
2058
  const { origin: loggedOrigin, rowCount: loggedCount, revision: loggedRevision } = result;
@@ -2069,7 +2065,7 @@ function logPrimed(logger, result) {
2069
2065
  async function fetchRemote(source, logger) {
2070
2066
  const fetchImpl = source.fetch ?? globalThis.fetch;
2071
2067
  const headers = authHeaders(source.auth);
2072
- if (revision !== void 0) headers["If-None-Match"] = `"${revision}"`;
2068
+ if (liveState.revision !== void 0) headers["If-None-Match"] = `"${liveState.revision}"`;
2073
2069
  const res = await fetchImpl(`${source.baseUrl}/models/catalog`, {
2074
2070
  headers,
2075
2071
  signal: AbortSignal.timeout(source.timeoutMs ?? 1e4)
@@ -2077,7 +2073,9 @@ async function fetchRemote(source, logger) {
2077
2073
  if (res.status === 304) return { kept: true };
2078
2074
  if (!res.ok) throw new Error(`catalog fetch failed with status ${res.status}`);
2079
2075
  const json = await res.json();
2080
- const { rows, revision: rev } = parseEnvelope(json);
2076
+ const parsed = EnvelopeSchema.safeParse(json);
2077
+ if (!parsed.success) throw new Error("invalid catalog response: missing rows");
2078
+ const { rows, revision: rev } = toEnvelope(parsed.data);
2081
2079
  if (rev === void 0) return { rows, fromCache: false };
2082
2080
  return { rows, revision: rev, fromCache: false };
2083
2081
  }
@@ -2093,40 +2091,46 @@ async function prime(source, logger) {
2093
2091
  try {
2094
2092
  const fetched = await fetchRemote(source, logger);
2095
2093
  if ("kept" in fetched) {
2096
- const result2 = { origin, rowCount: rowCount() };
2097
- if (revision !== void 0) result2.revision = revision;
2094
+ const result2 = { origin: liveState.origin, rowCount: rowCount() };
2095
+ if (liveState.revision !== void 0) result2.revision = liveState.revision;
2098
2096
  logPrimed(logger, result2);
2099
2097
  return result2;
2100
2098
  }
2101
2099
  liveCatalog.replace(fetched.rows);
2102
- origin = "remote";
2103
- revision = fetched.revision;
2100
+ liveState.origin = "remote";
2101
+ liveState.revision = fetched.revision;
2104
2102
  await writeCache(source, logger, fetched.rows, fetched.revision);
2105
- const result = { origin, rowCount: rowCount() };
2103
+ const result = { origin: liveState.origin, rowCount: rowCount() };
2106
2104
  if (fetched.revision !== void 0) result.revision = fetched.revision;
2107
2105
  logPrimed(logger, result);
2108
2106
  return result;
2109
2107
  } catch (err) {
2110
2108
  logger.warn("[modelkit] catalog remote failed, trying cache", err);
2111
- const error = describeError(err);
2109
+ const error = err instanceof Error ? err.message : String(err);
2112
2110
  try {
2113
2111
  const cached = await source.cache?.get();
2114
2112
  if (!cached) throw new Error("no cached catalog");
2115
- const { rows, revision: rev } = parseEnvelope(JSON.parse(cached));
2113
+ const cachedParsed = EnvelopeSchema.safeParse(JSON.parse(cached));
2114
+ if (!cachedParsed.success) throw new Error("invalid catalog response: missing rows");
2115
+ const { rows, revision: rev } = toEnvelope(cachedParsed.data);
2116
2116
  liveCatalog.replace(rows);
2117
- origin = "last-good";
2118
- revision = rev;
2119
- const result = { origin, rowCount: rowCount(), error };
2117
+ liveState.origin = "last-good";
2118
+ liveState.revision = rev;
2119
+ const result = {
2120
+ origin: liveState.origin,
2121
+ rowCount: rowCount(),
2122
+ error
2123
+ };
2120
2124
  if (rev !== void 0) result.revision = rev;
2121
2125
  logPrimed(logger, result);
2122
2126
  return result;
2123
2127
  } catch (cacheErr) {
2124
2128
  logger.warn("[modelkit] catalog cache failed, using snapshot", cacheErr);
2125
2129
  liveCatalog.replace([...MODELS]);
2126
- origin = "snapshot";
2127
- revision = void 0;
2130
+ liveState.origin = "snapshot";
2131
+ liveState.revision = void 0;
2128
2132
  const result = {
2129
- origin,
2133
+ origin: liveState.origin,
2130
2134
  rowCount: rowCount(),
2131
2135
  error
2132
2136
  };
@@ -2140,35 +2144,35 @@ async function refresh(source, logger) {
2140
2144
  const fetched = await fetchRemote(source, logger);
2141
2145
  if ("kept" in fetched) return;
2142
2146
  liveCatalog.replace(fetched.rows);
2143
- origin = "remote";
2144
- revision = fetched.revision;
2147
+ liveState.origin = "remote";
2148
+ liveState.revision = fetched.revision;
2145
2149
  await writeCache(source, logger, fetched.rows, fetched.revision);
2146
2150
  } catch (err) {
2147
2151
  logger.warn("[modelkit] catalog refresh failed, keeping current rows", err);
2148
2152
  }
2149
2153
  }
2150
2154
  function primeCatalog(source) {
2151
- if (memo) return memo;
2155
+ if (liveState.memo) return liveState.memo;
2152
2156
  const logger = source.logger ?? console;
2153
- memo = prime(source, logger).then((result) => {
2157
+ const pending = prime(source, logger).then((result) => {
2154
2158
  const ttlMs = source.ttlMs ?? 3e5;
2155
- if (ttlMs > 0 && timer === void 0) {
2156
- timer = setInterval(() => void refresh(source, logger), ttlMs);
2157
- const maybeUnref = timer;
2158
- maybeUnref.unref?.();
2159
+ if (ttlMs > 0 && liveState.timer === void 0) {
2160
+ liveState.timer = setInterval(() => void refresh(source, logger), ttlMs);
2161
+ liveState.timer.unref?.();
2159
2162
  }
2160
2163
  return result;
2161
2164
  });
2162
- return memo;
2165
+ liveState.memo = pending;
2166
+ return pending;
2163
2167
  }
2164
2168
  function resetLiveCatalog() {
2165
- if (timer !== void 0) {
2166
- clearInterval(timer);
2167
- timer = void 0;
2169
+ if (liveState.timer !== void 0) {
2170
+ clearInterval(liveState.timer);
2171
+ liveState.timer = void 0;
2168
2172
  }
2169
- memo = void 0;
2170
- revision = void 0;
2171
- origin = "snapshot";
2173
+ liveState.memo = void 0;
2174
+ liveState.revision = void 0;
2175
+ liveState.origin = "snapshot";
2172
2176
  liveCatalog.replace([...MODELS]);
2173
2177
  }
2174
2178
 
@@ -2566,6 +2570,7 @@ export {
2566
2570
  VIDEO_MODELS,
2567
2571
  isModelKitError,
2568
2572
  liveCatalog,
2573
+ liveState,
2569
2574
  nearestAspectRatio,
2570
2575
  primeCatalog,
2571
2576
  resetLiveCatalog,