@shop-os/modelkit 0.1.11 → 0.2.2

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.
package/dist/catalog.cjs CHANGED
@@ -20,7 +20,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/catalog-entry.ts
21
21
  var catalog_entry_exports = {};
22
22
  __export(catalog_entry_exports, {
23
+ ADAPTER_IDS: () => ADAPTER_IDS,
23
24
  Catalog: () => Catalog,
25
+ CatalogModelSchema: () => CatalogModelSchema,
26
+ CatalogSchema: () => CatalogSchema,
24
27
  IMAGE_MODELS: () => IMAGE_MODELS,
25
28
  MODELS: () => MODELS,
26
29
  ModelKitError: () => ModelKitError,
@@ -28,7 +31,11 @@ __export(catalog_entry_exports, {
28
31
  TEXT_MODELS: () => TEXT_MODELS,
29
32
  VIDEO_MODELS: () => VIDEO_MODELS,
30
33
  isModelKitError: () => isModelKitError,
34
+ liveCatalog: () => liveCatalog,
35
+ liveState: () => liveState,
31
36
  nearestAspectRatio: () => nearestAspectRatio,
37
+ primeCatalog: () => primeCatalog,
38
+ resetLiveCatalog: () => resetLiveCatalog,
32
39
  resolveAudioOptions: () => resolveAudioOptions,
33
40
  resolveImageOptions: () => resolveImageOptions,
34
41
  resolveOptions: () => resolveOptions,
@@ -131,6 +138,14 @@ var Catalog = class _Catalog {
131
138
  ...rows
132
139
  ]);
133
140
  }
141
+ /** Atomically swap every row. Builds the maps first so a bad batch throws before anything changes. */
142
+ replace(rows) {
143
+ const next = new _Catalog(rows);
144
+ this.byId.clear();
145
+ this.byAlias.clear();
146
+ for (const [id, model] of next.byId) this.byId.set(id, model);
147
+ for (const [alias, id] of next.byAlias) this.byAlias.set(alias, id);
148
+ }
134
149
  };
135
150
 
136
151
  // src/catalog/image.ts
@@ -148,7 +163,7 @@ var GEMINI_RATIOS = [
148
163
  "5:4",
149
164
  "adaptive"
150
165
  ];
151
- function geminiImage(id, label, aliases, sizes, display, exposure) {
166
+ function geminiImage(id, label, aliases, sizes, display, exposure, references) {
152
167
  const model = {
153
168
  id,
154
169
  aliases,
@@ -161,7 +176,8 @@ function geminiImage(id, label, aliases, sizes, display, exposure) {
161
176
  constraints: {
162
177
  aspectRatios: [...GEMINI_RATIOS],
163
178
  sizes,
164
- supports: ["safetySettings", "temperature"]
179
+ supports: ["safetySettings", "temperature"],
180
+ ...references ? { references } : {}
165
181
  },
166
182
  defaults: { size: "1K", aspectRatio: "1:1" },
167
183
  usage: { ...IMAGE_USAGE, slug: "gemini" },
@@ -181,7 +197,8 @@ var IMAGE_MODELS = [
181
197
  description: "Create stunning, production-quality visuals with exceptional realism, detail, and typography. Best for campaigns, e-commerce, product photography, and hero creatives.",
182
198
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
183
199
  },
184
- "catalog"
200
+ "catalog",
201
+ { images: 14 }
185
202
  ),
186
203
  geminiImage(
187
204
  "gemini-3.1-flash-image-preview",
@@ -194,7 +211,8 @@ var IMAGE_MODELS = [
194
211
  description: "Generate high-quality images at speed. Perfect for brainstorming, moodboards, concept testing, creative exploration, and large batch workflows.",
195
212
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
196
213
  },
197
- "catalog"
214
+ "catalog",
215
+ { images: 14 }
198
216
  ),
199
217
  geminiImage(
200
218
  "gemini-3.1-flash-lite-image",
@@ -206,14 +224,15 @@ var IMAGE_MODELS = [
206
224
  description: "The fastest and most affordable image model. Ideal for rapid drafts, bulk exploration, and iterative concept testing at 1K resolution.",
207
225
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
208
226
  },
209
- "catalog"
227
+ "catalog",
228
+ { images: 14 }
210
229
  ),
211
230
  // trigger-workflows validates 1K only; pricing seeds 2K/4K rows so allow all three.
212
231
  geminiImage(
213
232
  "gemini-2.5-flash-image",
214
233
  "Gemini 2.5 Flash Image",
215
234
  [],
216
- ["1K", "2K", "4K"],
235
+ ["1K"],
217
236
  {
218
237
  provider: "google",
219
238
  description: "Nano Banana (legacy Gemini 2.5 Flash Image) native image generation and editing model for high-volume, low-latency creative workflows."
@@ -244,7 +263,7 @@ var IMAGE_MODELS = [
244
263
  sizes: ["1K", "2K", "4K"],
245
264
  qualityOptions: ["auto", "low", "medium", "high"],
246
265
  references: { images: 16 },
247
- supports: ["quality", "count"]
266
+ supports: ["quality", "count", "outputFormat"]
248
267
  },
249
268
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
250
269
  usage: { ...IMAGE_USAGE, slug: "gpt" },
@@ -264,7 +283,7 @@ var IMAGE_MODELS = [
264
283
  adapter: "openai-image",
265
284
  providerModelId: "gpt-image-2.5-sunburst",
266
285
  lifecycle: "active",
267
- exposure: "internal",
286
+ exposure: "catalog",
268
287
  constraints: {
269
288
  exactSizes: {
270
289
  "1:1": "1024x1024",
@@ -277,9 +296,9 @@ var IMAGE_MODELS = [
277
296
  },
278
297
  aspectRatios: ["1:1", "3:2", "2:3", "16:9", "9:16", "4:5", "5:4", "adaptive"],
279
298
  sizes: ["1K", "2K", "4K"],
280
- qualityOptions: ["auto", "low", "medium", "high"],
299
+ qualityOptions: ["auto", "low", "medium", "high", "xhigh", "max"],
281
300
  references: { images: 16 },
282
- supports: ["quality", "count"]
301
+ supports: ["quality", "count", "outputFormat"]
283
302
  },
284
303
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
285
304
  usage: { ...IMAGE_USAGE },
@@ -298,7 +317,7 @@ var IMAGE_MODELS = [
298
317
  adapter: "openai-image",
299
318
  providerModelId: "gpt-image-2.5-flare",
300
319
  lifecycle: "active",
301
- exposure: "internal",
320
+ exposure: "catalog",
302
321
  constraints: {
303
322
  exactSizes: {
304
323
  "1:1": "1024x1024",
@@ -311,9 +330,9 @@ var IMAGE_MODELS = [
311
330
  },
312
331
  aspectRatios: ["1:1", "3:2", "2:3", "16:9", "9:16", "4:5", "5:4", "adaptive"],
313
332
  sizes: ["1K", "2K", "4K"],
314
- qualityOptions: ["auto", "low", "medium", "high"],
333
+ qualityOptions: ["auto", "low", "medium", "high", "xhigh", "max"],
315
334
  references: { images: 16 },
316
- supports: ["quality", "count"]
335
+ supports: ["quality", "count", "outputFormat"]
317
336
  },
318
337
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
319
338
  usage: { ...IMAGE_USAGE },
@@ -343,8 +362,6 @@ var IMAGE_MODELS = [
343
362
  "2:3",
344
363
  "3:4",
345
364
  "9:16",
346
- "4:5",
347
- "5:4",
348
365
  "9:21",
349
366
  "adaptive"
350
367
  ],
@@ -376,7 +393,7 @@ var IMAGE_MODELS = [
376
393
  references: { images: 10 },
377
394
  // Ark's Images API has no output-format, quality or count field; only
378
395
  // the seed is forwarded, so anything else must warn, not vanish.
379
- supports: ["seed"]
396
+ supports: ["seed", "outputFormat"]
380
397
  },
381
398
  defaults: { size: "1K", aspectRatio: "1:1" },
382
399
  usage: { ...IMAGE_USAGE },
@@ -412,7 +429,7 @@ var IMAGE_MODELS = [
412
429
  "21:9",
413
430
  "9:21"
414
431
  ],
415
- sizes: ["1K", "2K", "4K"],
432
+ sizes: ["2K", "4K"],
416
433
  references: { images: 10 },
417
434
  supports: ["seed"]
418
435
  },
@@ -464,7 +481,7 @@ var IMAGE_MODELS = [
464
481
  aspectRatios: ["1:1", "2:3", "3:2", "4:3", "3:4", "4:5", "5:4", "9:16", "16:9", "21:9"],
465
482
  sizes: ["1K", "2K", "4K"],
466
483
  requires: ["references"],
467
- supports: ["seed"]
484
+ supports: []
468
485
  },
469
486
  defaults: { size: "1K", aspectRatio: "1:1" },
470
487
  usage: { ...IMAGE_USAGE },
@@ -489,7 +506,7 @@ var IMAGE_MODELS = [
489
506
  aspectRatios: ["1:1", "2:3", "3:4", "4:3", "9:16", "16:9", "21:9"],
490
507
  sizes: ["1K"],
491
508
  requires: ["references"],
492
- supports: ["seed"]
509
+ supports: []
493
510
  },
494
511
  defaults: { size: "1K", aspectRatio: "1:1" },
495
512
  usage: { ...IMAGE_USAGE },
@@ -541,7 +558,6 @@ var IMAGE_MODELS = [
541
558
  aspectRatios: ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"],
542
559
  sizes: [],
543
560
  references: { images: 1 },
544
- requires: ["references"],
545
561
  supports: []
546
562
  },
547
563
  defaults: { aspectRatio: "1:1" },
@@ -1260,7 +1276,7 @@ var VIDEO_MODELS = [
1260
1276
  resolutions: ["720p", "1080p", "4k"],
1261
1277
  durations: [8],
1262
1278
  references: { images: 3 },
1263
- supports: ["lastFrame"]
1279
+ supports: ["lastFrame", "seed"]
1264
1280
  },
1265
1281
  defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
1266
1282
  usage: { ...VIDEO_USAGE, slug: "veo" },
@@ -1288,9 +1304,9 @@ var VIDEO_MODELS = [
1288
1304
  constraints: {
1289
1305
  aspectRatios: [...OMNI_RATIOS],
1290
1306
  resolutions: ["720p", "1080p", "4k"],
1291
- durations: [4, 8],
1307
+ durations: [4, 6, 8],
1292
1308
  references: { images: 3 },
1293
- supports: ["lastFrame"]
1309
+ supports: ["lastFrame", "seed"]
1294
1310
  },
1295
1311
  defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
1296
1312
  usage: { ...VIDEO_USAGE },
@@ -1317,9 +1333,8 @@ var VIDEO_MODELS = [
1317
1333
  constraints: {
1318
1334
  aspectRatios: [...OMNI_RATIOS],
1319
1335
  resolutions: ["720p", "1080p"],
1320
- durations: [4, 8],
1321
- references: { images: 3 },
1322
- supports: ["lastFrame"]
1336
+ durations: [4, 6, 8],
1337
+ supports: ["lastFrame", "seed"]
1323
1338
  },
1324
1339
  defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
1325
1340
  usage: { ...VIDEO_USAGE },
@@ -1351,7 +1366,7 @@ var VIDEO_MODELS = [
1351
1366
  // reference clip keeps its own framing.
1352
1367
  aspectRatios: [...OMNI_RATIOS],
1353
1368
  durations: [3, 4, 5, 6, 7, 8, 9, 10],
1354
- references: { images: 6, videos: 1 },
1369
+ references: { images: 6, videos: 3 },
1355
1370
  supports: []
1356
1371
  },
1357
1372
  defaults: {},
@@ -1377,7 +1392,7 @@ var VIDEO_MODELS = [
1377
1392
  aspectRatios: [...OMNI_RATIOS],
1378
1393
  resolutions: ["360p", "720p", "1080p", "4k"],
1379
1394
  durations: [3, 4, 5, 6, 7, 8, 9, 10],
1380
- references: { images: 6, videos: 1 },
1395
+ references: { images: 6, videos: 3 },
1381
1396
  supports: []
1382
1397
  },
1383
1398
  defaults: {},
@@ -1406,7 +1421,7 @@ var VIDEO_MODELS = [
1406
1421
  durations: { min: 4, max: 15 },
1407
1422
  durationPresets: [4, 6, 8, 10, 12, 15],
1408
1423
  references: { images: 9, videos: 3, audios: 3, audioOnly: false },
1409
- ratioIgnoredWith: ["firstFrame"],
1424
+ ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1410
1425
  supports: ["generateAudio", "seed", "lastFrame", "watermark"]
1411
1426
  },
1412
1427
  defaults: {
@@ -1438,7 +1453,7 @@ var VIDEO_MODELS = [
1438
1453
  resolutions: ["480p", "720p"],
1439
1454
  durations: { min: 4, max: 15 },
1440
1455
  references: { images: 9, videos: 3, audios: 3, audioOnly: false },
1441
- ratioIgnoredWith: ["firstFrame"],
1456
+ ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1442
1457
  supports: ["generateAudio", "seed", "lastFrame", "watermark"]
1443
1458
  },
1444
1459
  defaults: {
@@ -1471,7 +1486,7 @@ var VIDEO_MODELS = [
1471
1486
  resolutions: ["480p", "720p", "1080p"],
1472
1487
  durations: { min: 4, max: 30 },
1473
1488
  references: { images: 30, videos: 10, audios: 10 },
1474
- ratioIgnoredWith: ["firstFrame"],
1489
+ ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1475
1490
  supports: ["generateAudio", "seed", "lastFrame", "watermark"]
1476
1491
  },
1477
1492
  defaults: {
@@ -1590,18 +1605,7 @@ var VIDEO_MODELS = [
1590
1605
  lifecycle: "active",
1591
1606
  exposure: "catalog",
1592
1607
  constraints: {
1593
- aspectRatios: [
1594
- "1:1",
1595
- "16:9",
1596
- "9:16",
1597
- "4:3",
1598
- "3:4",
1599
- "3:2",
1600
- "2:3",
1601
- "21:9",
1602
- "4:5",
1603
- "adaptive"
1604
- ],
1608
+ aspectRatios: [...KLING_RATIOS],
1605
1609
  resolutions: ["720p", "1080p"],
1606
1610
  durations: { min: 3, max: 15 },
1607
1611
  references: { images: 7 },
@@ -1821,6 +1825,397 @@ var MODELS = [
1821
1825
  ...OTHER_MODELS
1822
1826
  ];
1823
1827
 
1828
+ // src/catalog/schema.ts
1829
+ var import_zod = require("zod");
1830
+ var ADAPTER_IDS = [
1831
+ "ai-sdk-text",
1832
+ "google-image",
1833
+ "openai-image",
1834
+ "google-genai",
1835
+ "ark",
1836
+ "fal",
1837
+ "replicate",
1838
+ "prodia",
1839
+ "higgsfield",
1840
+ "xai-video"
1841
+ ];
1842
+ var ModelTypeSchema = import_zod.z.enum(["text", "image", "video", "audio", "upscale", "bg-remove"]);
1843
+ var LifecycleSchema = import_zod.z.enum(["active", "deprecated", "retired"]);
1844
+ var AdapterSchema = import_zod.z.enum(ADAPTER_IDS);
1845
+ var AspectRatioSchema = import_zod.z.enum([
1846
+ "1:1",
1847
+ "16:9",
1848
+ "9:16",
1849
+ "4:3",
1850
+ "3:4",
1851
+ "3:2",
1852
+ "2:3",
1853
+ "4:5",
1854
+ "5:4",
1855
+ "21:9",
1856
+ "9:21",
1857
+ "97:30",
1858
+ "adaptive"
1859
+ ]);
1860
+ var ImageSizeSchema = import_zod.z.enum(["512", "1K", "2K", "4K"]);
1861
+ var VideoResolutionSchema = import_zod.z.enum(["360p", "480p", "720p", "768p", "1080p", "2k", "4k"]);
1862
+ var ImageQualitySchema = import_zod.z.enum(["auto", "low", "medium", "high", "xhigh", "max"]);
1863
+ var OutputFormatSchema = import_zod.z.enum(["png", "jpeg", "webp"]);
1864
+ var RequiredInputSchema = import_zod.z.enum(["firstFrame", "sourceVideo", "references"]);
1865
+ var SupportedOptionSchema = import_zod.z.enum([
1866
+ "seed",
1867
+ "quality",
1868
+ "negativePrompt",
1869
+ "cfgScale",
1870
+ "generateAudio",
1871
+ "promptExpansion",
1872
+ "lastFrame",
1873
+ "count",
1874
+ "outputFormat",
1875
+ "scaleFactor",
1876
+ "safetySettings",
1877
+ "temperature",
1878
+ "upscale",
1879
+ "watermark",
1880
+ "safetyChecker",
1881
+ "instrumental"
1882
+ ]);
1883
+ var UsageUnitSchema = import_zod.z.enum([
1884
+ "tokens",
1885
+ "images",
1886
+ "seconds",
1887
+ "reported_cost_usd",
1888
+ "compute_seconds"
1889
+ ]);
1890
+ var PricingKindSchema = import_zod.z.enum(["token", "image_size", "video_per_second", "flat"]);
1891
+ var ProviderOptionValueSchema = import_zod.z.lazy(
1892
+ () => import_zod.z.union([
1893
+ import_zod.z.string(),
1894
+ import_zod.z.number(),
1895
+ import_zod.z.boolean(),
1896
+ import_zod.z.array(ProviderOptionValueSchema),
1897
+ import_zod.z.record(import_zod.z.string(), ProviderOptionValueSchema)
1898
+ ])
1899
+ );
1900
+ var ProviderOptionsSchema = import_zod.z.record(import_zod.z.string(), import_zod.z.record(import_zod.z.string(), ProviderOptionValueSchema));
1901
+ var ReferenceLimitsSchema = import_zod.z.looseObject({
1902
+ images: import_zod.z.number().optional(),
1903
+ videos: import_zod.z.number().optional(),
1904
+ audios: import_zod.z.number().optional(),
1905
+ total: import_zod.z.number().optional(),
1906
+ audioOnly: import_zod.z.boolean().optional()
1907
+ });
1908
+ var ModelConstraintsSchema = import_zod.z.looseObject({
1909
+ aspectRatios: import_zod.z.array(AspectRatioSchema).optional(),
1910
+ sizes: import_zod.z.array(ImageSizeSchema).optional(),
1911
+ resolutions: import_zod.z.array(VideoResolutionSchema).optional(),
1912
+ durations: import_zod.z.union([import_zod.z.looseObject({ min: import_zod.z.number(), max: import_zod.z.number() }), import_zod.z.array(import_zod.z.number())]).optional(),
1913
+ durationPresets: import_zod.z.array(import_zod.z.number()).optional(),
1914
+ qualityOptions: import_zod.z.array(import_zod.z.string()).optional(),
1915
+ exactSizes: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
1916
+ references: ReferenceLimitsSchema.optional(),
1917
+ requires: import_zod.z.array(RequiredInputSchema).optional(),
1918
+ supports: import_zod.z.array(SupportedOptionSchema).optional(),
1919
+ ratioIgnoredWith: import_zod.z.array(import_zod.z.enum(["firstFrame", "sourceVideo"])).optional()
1920
+ });
1921
+ var MediaRefSchema = import_zod.z.union([
1922
+ import_zod.z.looseObject({ url: import_zod.z.string(), label: import_zod.z.string().optional() }),
1923
+ import_zod.z.looseObject({
1924
+ bytes: import_zod.z.instanceof(Uint8Array),
1925
+ mime: import_zod.z.string(),
1926
+ label: import_zod.z.string().optional()
1927
+ })
1928
+ ]);
1929
+ var ImageSafetySettingSchema = import_zod.z.looseObject({ category: import_zod.z.string(), threshold: import_zod.z.string() });
1930
+ var UpscaleOptionsSchema = import_zod.z.looseObject({
1931
+ enhanceModel: import_zod.z.string().optional(),
1932
+ subjectDetection: import_zod.z.string().optional(),
1933
+ faceEnhancement: import_zod.z.boolean().optional(),
1934
+ faceEnhancementCreativity: import_zod.z.number().optional(),
1935
+ faceEnhancementStrength: import_zod.z.number().optional()
1936
+ });
1937
+ var DefaultsSchema = import_zod.z.looseObject({
1938
+ references: import_zod.z.array(MediaRefSchema).optional(),
1939
+ aspectRatio: AspectRatioSchema.optional(),
1940
+ size: ImageSizeSchema.optional(),
1941
+ exactSize: import_zod.z.string().optional(),
1942
+ quality: ImageQualitySchema.optional(),
1943
+ seed: import_zod.z.number().optional(),
1944
+ count: import_zod.z.number().optional(),
1945
+ outputFormat: OutputFormatSchema.optional(),
1946
+ scaleFactor: import_zod.z.number().optional(),
1947
+ safetySettings: import_zod.z.array(ImageSafetySettingSchema).optional(),
1948
+ temperature: import_zod.z.number().optional(),
1949
+ upscale: UpscaleOptionsSchema.optional(),
1950
+ firstFrame: MediaRefSchema.optional(),
1951
+ lastFrame: MediaRefSchema.optional(),
1952
+ sourceVideo: MediaRefSchema.optional(),
1953
+ referenceImages: import_zod.z.array(MediaRefSchema).optional(),
1954
+ referenceVideos: import_zod.z.array(MediaRefSchema).optional(),
1955
+ referenceAudios: import_zod.z.array(MediaRefSchema).optional(),
1956
+ resolution: VideoResolutionSchema.optional(),
1957
+ durationSeconds: import_zod.z.number().optional(),
1958
+ generateAudio: import_zod.z.boolean().optional(),
1959
+ negativePrompt: import_zod.z.string().optional(),
1960
+ cfgScale: import_zod.z.number().optional(),
1961
+ promptExpansion: import_zod.z.enum(["fast", "balanced", "quality"]).optional(),
1962
+ watermark: import_zod.z.boolean().optional(),
1963
+ safetyChecker: import_zod.z.boolean().optional(),
1964
+ mode: import_zod.z.enum(["standard", "pro"]).optional(),
1965
+ instrumental: import_zod.z.boolean().optional()
1966
+ });
1967
+ var CatalogDisplaySchema = import_zod.z.looseObject({
1968
+ provider: import_zod.z.string(),
1969
+ description: import_zod.z.string(),
1970
+ logo: import_zod.z.string().optional(),
1971
+ costTier: import_zod.z.union([import_zod.z.literal(1), import_zod.z.literal(2), import_zod.z.literal(3)]).optional(),
1972
+ recommended: import_zod.z.boolean().optional(),
1973
+ sortOrder: import_zod.z.number().optional(),
1974
+ chat: import_zod.z.looseObject({
1975
+ providerOptions: ProviderOptionsSchema.optional(),
1976
+ temperature: import_zod.z.number().optional()
1977
+ }).optional()
1978
+ });
1979
+ var CatalogCapabilitiesSchema = import_zod.z.looseObject({
1980
+ acceptsSourceVideo: import_zod.z.boolean().optional(),
1981
+ framesExcludeReferences: import_zod.z.boolean().optional(),
1982
+ reasoning: import_zod.z.boolean().optional(),
1983
+ vision: import_zod.z.boolean().optional(),
1984
+ contextWindow: import_zod.z.number().optional()
1985
+ });
1986
+ var CatalogModelSchemaBase = import_zod.z.looseObject({
1987
+ id: import_zod.z.string().min(1),
1988
+ aliases: import_zod.z.array(import_zod.z.string()).default([]),
1989
+ label: import_zod.z.string().min(1),
1990
+ type: ModelTypeSchema,
1991
+ adapter: AdapterSchema,
1992
+ providerModelId: import_zod.z.string().min(1),
1993
+ lifecycle: LifecycleSchema,
1994
+ replacedBy: import_zod.z.string().optional(),
1995
+ exposure: import_zod.z.enum(["catalog", "internal"]),
1996
+ constraints: ModelConstraintsSchema,
1997
+ defaults: DefaultsSchema,
1998
+ providerOptions: ProviderOptionsSchema.optional(),
1999
+ usage: import_zod.z.looseObject({
2000
+ unit: UsageUnitSchema,
2001
+ slug: import_zod.z.string().optional(),
2002
+ providerLabel: import_zod.z.string().optional()
2003
+ }),
2004
+ pricingKind: PricingKindSchema,
2005
+ display: CatalogDisplaySchema.optional(),
2006
+ capabilities: CatalogCapabilitiesSchema.optional()
2007
+ }).superRefine((row, ctx) => {
2008
+ if (row.lifecycle === "active" && !row.display) {
2009
+ ctx.addIssue({
2010
+ code: "custom",
2011
+ path: ["display"],
2012
+ message: "active rows need display"
2013
+ });
2014
+ }
2015
+ if (row.lifecycle === "active" && row.type === "text" && !row.capabilities?.contextWindow) {
2016
+ ctx.addIssue({
2017
+ code: "custom",
2018
+ path: ["capabilities", "contextWindow"],
2019
+ message: "active text rows need contextWindow"
2020
+ });
2021
+ }
2022
+ if (row.replacedBy !== void 0 && row.replacedBy === row.id) {
2023
+ ctx.addIssue({
2024
+ code: "custom",
2025
+ path: ["replacedBy"],
2026
+ message: "replacedBy must not equal id"
2027
+ });
2028
+ }
2029
+ });
2030
+ var CatalogModelSchema = CatalogModelSchemaBase;
2031
+ var CatalogSchema = import_zod.z.array(CatalogModelSchemaBase).superRefine((rows, ctx) => {
2032
+ const seenIds = /* @__PURE__ */ new Map();
2033
+ rows.forEach((row, index) => {
2034
+ if (seenIds.has(row.id)) {
2035
+ ctx.addIssue({
2036
+ code: "custom",
2037
+ path: [index, "id"],
2038
+ message: `Duplicate model id "${row.id}"`
2039
+ });
2040
+ } else {
2041
+ seenIds.set(row.id, index);
2042
+ }
2043
+ });
2044
+ const seenAliases = /* @__PURE__ */ new Map();
2045
+ rows.forEach((row, index) => {
2046
+ row.aliases.forEach((alias, aliasIndex) => {
2047
+ const path = [index, "aliases", aliasIndex];
2048
+ if (alias === row.id || seenIds.has(alias)) {
2049
+ ctx.addIssue({
2050
+ code: "custom",
2051
+ path,
2052
+ message: `Alias "${alias}" collides with a model id`
2053
+ });
2054
+ return;
2055
+ }
2056
+ if (seenAliases.has(alias)) {
2057
+ ctx.addIssue({
2058
+ code: "custom",
2059
+ path,
2060
+ message: `Duplicate alias "${alias}"`
2061
+ });
2062
+ } else {
2063
+ seenAliases.set(alias, index);
2064
+ }
2065
+ });
2066
+ });
2067
+ });
2068
+
2069
+ // src/catalog/live.ts
2070
+ var KEY = /* @__PURE__ */ Symbol.for("@shop-os/modelkit/live-catalog");
2071
+ var store = globalThis;
2072
+ var liveState = store[KEY] ??= {
2073
+ catalog: new Catalog(MODELS),
2074
+ memo: void 0,
2075
+ timer: void 0,
2076
+ revision: void 0,
2077
+ origin: "snapshot"
2078
+ };
2079
+ var liveCatalog = liveState.catalog;
2080
+
2081
+ // src/catalog/load.ts
2082
+ function rowCount() {
2083
+ return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
2084
+ }
2085
+ function authHeaders(auth) {
2086
+ return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
2087
+ }
2088
+ function describeError(err) {
2089
+ return err instanceof Error ? err.message : String(err);
2090
+ }
2091
+ function parseEnvelope(json) {
2092
+ if (typeof json !== "object" || json === null || !("rows" in json)) {
2093
+ throw new Error("invalid catalog response: missing rows");
2094
+ }
2095
+ const rows = CatalogSchema.parse(json.rows);
2096
+ const rev = json.revision;
2097
+ if (typeof rev === "string") return { rows, revision: rev };
2098
+ return { rows };
2099
+ }
2100
+ function logPrimed(logger, result) {
2101
+ const { origin: loggedOrigin, rowCount: loggedCount, revision: loggedRevision } = result;
2102
+ logger.info("[modelkit] catalog primed", {
2103
+ origin: loggedOrigin,
2104
+ rowCount: loggedCount,
2105
+ revision: loggedRevision
2106
+ });
2107
+ }
2108
+ async function fetchRemote(source, logger) {
2109
+ const fetchImpl = source.fetch ?? globalThis.fetch;
2110
+ const headers = authHeaders(source.auth);
2111
+ if (liveState.revision !== void 0) headers["If-None-Match"] = `"${liveState.revision}"`;
2112
+ const res = await fetchImpl(`${source.baseUrl}/models/catalog`, {
2113
+ headers,
2114
+ signal: AbortSignal.timeout(source.timeoutMs ?? 1e4)
2115
+ });
2116
+ if (res.status === 304) return { kept: true };
2117
+ if (!res.ok) throw new Error(`catalog fetch failed with status ${res.status}`);
2118
+ const json = await res.json();
2119
+ const { rows, revision: rev } = parseEnvelope(json);
2120
+ if (rev === void 0) return { rows, fromCache: false };
2121
+ return { rows, revision: rev, fromCache: false };
2122
+ }
2123
+ async function writeCache(source, logger, rows, rev) {
2124
+ if (!source.cache) return;
2125
+ try {
2126
+ await source.cache.set(JSON.stringify({ rows, revision: rev }));
2127
+ } catch (err) {
2128
+ logger.warn("[modelkit] catalog cache write failed", err);
2129
+ }
2130
+ }
2131
+ async function prime(source, logger) {
2132
+ try {
2133
+ const fetched = await fetchRemote(source, logger);
2134
+ if ("kept" in fetched) {
2135
+ const result2 = { origin: liveState.origin, rowCount: rowCount() };
2136
+ if (liveState.revision !== void 0) result2.revision = liveState.revision;
2137
+ logPrimed(logger, result2);
2138
+ return result2;
2139
+ }
2140
+ liveCatalog.replace(fetched.rows);
2141
+ liveState.origin = "remote";
2142
+ liveState.revision = fetched.revision;
2143
+ await writeCache(source, logger, fetched.rows, fetched.revision);
2144
+ const result = { origin: liveState.origin, rowCount: rowCount() };
2145
+ if (fetched.revision !== void 0) result.revision = fetched.revision;
2146
+ logPrimed(logger, result);
2147
+ return result;
2148
+ } catch (err) {
2149
+ logger.warn("[modelkit] catalog remote failed, trying cache", err);
2150
+ const error = describeError(err);
2151
+ try {
2152
+ const cached = await source.cache?.get();
2153
+ if (!cached) throw new Error("no cached catalog");
2154
+ const { rows, revision: rev } = parseEnvelope(JSON.parse(cached));
2155
+ liveCatalog.replace(rows);
2156
+ liveState.origin = "last-good";
2157
+ liveState.revision = rev;
2158
+ const result = {
2159
+ origin: liveState.origin,
2160
+ rowCount: rowCount(),
2161
+ error
2162
+ };
2163
+ if (rev !== void 0) result.revision = rev;
2164
+ logPrimed(logger, result);
2165
+ return result;
2166
+ } catch (cacheErr) {
2167
+ logger.warn("[modelkit] catalog cache failed, using snapshot", cacheErr);
2168
+ liveCatalog.replace([...MODELS]);
2169
+ liveState.origin = "snapshot";
2170
+ liveState.revision = void 0;
2171
+ const result = {
2172
+ origin: liveState.origin,
2173
+ rowCount: rowCount(),
2174
+ error
2175
+ };
2176
+ logPrimed(logger, result);
2177
+ return result;
2178
+ }
2179
+ }
2180
+ }
2181
+ async function refresh(source, logger) {
2182
+ try {
2183
+ const fetched = await fetchRemote(source, logger);
2184
+ if ("kept" in fetched) return;
2185
+ liveCatalog.replace(fetched.rows);
2186
+ liveState.origin = "remote";
2187
+ liveState.revision = fetched.revision;
2188
+ await writeCache(source, logger, fetched.rows, fetched.revision);
2189
+ } catch (err) {
2190
+ logger.warn("[modelkit] catalog refresh failed, keeping current rows", err);
2191
+ }
2192
+ }
2193
+ function primeCatalog(source) {
2194
+ const memo = liveState.memo;
2195
+ if (memo) return memo;
2196
+ const logger = source.logger ?? console;
2197
+ liveState.memo = prime(source, logger).then((result) => {
2198
+ const ttlMs = source.ttlMs ?? 3e5;
2199
+ if (ttlMs > 0 && liveState.timer === void 0) {
2200
+ liveState.timer = setInterval(() => void refresh(source, logger), ttlMs);
2201
+ const maybeUnref = liveState.timer;
2202
+ maybeUnref.unref?.();
2203
+ }
2204
+ return result;
2205
+ });
2206
+ return liveState.memo;
2207
+ }
2208
+ function resetLiveCatalog() {
2209
+ if (liveState.timer !== void 0) {
2210
+ clearInterval(liveState.timer);
2211
+ liveState.timer = void 0;
2212
+ }
2213
+ liveState.memo = void 0;
2214
+ liveState.revision = void 0;
2215
+ liveState.origin = "snapshot";
2216
+ liveCatalog.replace([...MODELS]);
2217
+ }
2218
+
1824
2219
  // src/resolve-options.ts
1825
2220
  var SIZE_ORDER = ["512", "1K", "2K", "4K"];
1826
2221
  var RESOLUTION_ORDER = ["360p", "480p", "720p", "768p", "1080p", "2k", "4k"];