@shop-os/modelkit 0.2.20 → 0.2.22

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.
@@ -295,6 +295,8 @@ interface CatalogCapabilities {
295
295
  acceptsSourceVideo?: boolean;
296
296
  /** Video rows: first/last frames and reference images are mutually exclusive inputs. */
297
297
  framesExcludeReferences?: boolean;
298
+ /** Video rows: a last frame is accepted only together with a first frame. */
299
+ lastFrameRequiresFirstFrame?: boolean;
298
300
  /** Text rows. `reasoning`: the model streams reasoning the UI should surface. */
299
301
  reasoning?: boolean;
300
302
  vision?: boolean;
@@ -848,6 +850,7 @@ declare const CatalogModelSchemaBase: z.ZodObject<{
848
850
  capabilities: z.ZodOptional<z.ZodObject<{
849
851
  acceptsSourceVideo: z.ZodOptional<z.ZodBoolean>;
850
852
  framesExcludeReferences: z.ZodOptional<z.ZodBoolean>;
853
+ lastFrameRequiresFirstFrame: z.ZodOptional<z.ZodBoolean>;
851
854
  reasoning: z.ZodOptional<z.ZodBoolean>;
852
855
  vision: z.ZodOptional<z.ZodBoolean>;
853
856
  contextWindow: z.ZodOptional<z.ZodNumber>;
package/dist/catalog.d.ts CHANGED
@@ -295,6 +295,8 @@ interface CatalogCapabilities {
295
295
  acceptsSourceVideo?: boolean;
296
296
  /** Video rows: first/last frames and reference images are mutually exclusive inputs. */
297
297
  framesExcludeReferences?: boolean;
298
+ /** Video rows: a last frame is accepted only together with a first frame. */
299
+ lastFrameRequiresFirstFrame?: boolean;
298
300
  /** Text rows. `reasoning`: the model streams reasoning the UI should surface. */
299
301
  reasoning?: boolean;
300
302
  vision?: boolean;
@@ -848,6 +850,7 @@ declare const CatalogModelSchemaBase: z.ZodObject<{
848
850
  capabilities: z.ZodOptional<z.ZodObject<{
849
851
  acceptsSourceVideo: z.ZodOptional<z.ZodBoolean>;
850
852
  framesExcludeReferences: z.ZodOptional<z.ZodBoolean>;
853
+ lastFrameRequiresFirstFrame: z.ZodOptional<z.ZodBoolean>;
851
854
  reasoning: z.ZodOptional<z.ZodBoolean>;
852
855
  vision: z.ZodOptional<z.ZodBoolean>;
853
856
  contextWindow: z.ZodOptional<z.ZodNumber>;
package/dist/catalog.js CHANGED
@@ -158,13 +158,16 @@ var GEMINI_RATIOS = [
158
158
  "5:4",
159
159
  "adaptive"
160
160
  ];
161
- function geminiImage(id, label, aliases, sizes, display, exposure, references) {
161
+ var GEMINI_PROMPT_MAX_CHARS = 5e4;
162
+ var GPT_IMAGE_PROMPT = { referenceSyntax: "numbered", maxChars: 32e3 };
163
+ function geminiImage(id, label, aliases, sizes, display, exposure, references, promptMaxChars) {
164
+ const prompt = { referenceSyntax: "caption" };
165
+ if (promptMaxChars !== void 0) prompt.maxChars = promptMaxChars;
162
166
  const constraints = {
163
167
  aspectRatios: [...GEMINI_RATIOS],
164
168
  sizes,
165
169
  supports: ["safetySettings", "temperature"],
166
- // google-image sends MediaRef.label as a text part beside each reference.
167
- prompt: { referenceSyntax: "caption" }
170
+ prompt
168
171
  };
169
172
  if (references !== void 0) constraints.references = references;
170
173
  const model = {
@@ -196,7 +199,8 @@ var IMAGE_MODELS = [
196
199
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
197
200
  },
198
201
  ["cowork", "space_builder"],
199
- { images: 14 }
202
+ { images: 14 },
203
+ GEMINI_PROMPT_MAX_CHARS
200
204
  ),
201
205
  geminiImage(
202
206
  "gemini-3.1-flash-image-preview",
@@ -210,7 +214,8 @@ var IMAGE_MODELS = [
210
214
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
211
215
  },
212
216
  ["cowork", "space_builder"],
213
- { images: 14 }
217
+ { images: 14 },
218
+ GEMINI_PROMPT_MAX_CHARS
214
219
  ),
215
220
  geminiImage(
216
221
  "gemini-3.1-flash-lite-image",
@@ -223,7 +228,8 @@ var IMAGE_MODELS = [
223
228
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
224
229
  },
225
230
  ["cowork", "space_builder"],
226
- { images: 14 }
231
+ { images: 14 },
232
+ GEMINI_PROMPT_MAX_CHARS
227
233
  ),
228
234
  // trigger-workflows validates 1K only; pricing seeds 2K/4K rows so allow all three.
229
235
  geminiImage(
@@ -261,7 +267,8 @@ var IMAGE_MODELS = [
261
267
  sizes: ["1K", "2K", "4K"],
262
268
  qualityOptions: ["auto", "low", "medium", "high"],
263
269
  references: { images: 16 },
264
- supports: ["quality", "count", "outputFormat"]
270
+ supports: ["quality", "count", "outputFormat"],
271
+ prompt: GPT_IMAGE_PROMPT
265
272
  },
266
273
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
267
274
  usage: { ...IMAGE_USAGE, slug: "gpt" },
@@ -296,7 +303,8 @@ var IMAGE_MODELS = [
296
303
  sizes: ["1K", "2K", "4K"],
297
304
  qualityOptions: ["auto", "low", "medium", "high", "xhigh", "max"],
298
305
  references: { images: 16 },
299
- supports: ["quality", "count", "outputFormat"]
306
+ supports: ["quality", "count", "outputFormat"],
307
+ prompt: GPT_IMAGE_PROMPT
300
308
  },
301
309
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
302
310
  usage: { ...IMAGE_USAGE },
@@ -330,7 +338,8 @@ var IMAGE_MODELS = [
330
338
  sizes: ["1K", "2K", "4K"],
331
339
  qualityOptions: ["auto", "low", "medium", "high", "xhigh", "max"],
332
340
  references: { images: 16 },
333
- supports: ["quality", "count", "outputFormat"]
341
+ supports: ["quality", "count", "outputFormat"],
342
+ prompt: GPT_IMAGE_PROMPT
334
343
  },
335
344
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
336
345
  usage: { ...IMAGE_USAGE },
@@ -453,7 +462,9 @@ var IMAGE_MODELS = [
453
462
  sizes: ["1K"],
454
463
  references: { images: 8 },
455
464
  // flux-2-pro's job type always returns image/png; only the seed is forwarded.
456
- supports: ["seed"]
465
+ supports: ["seed"],
466
+ // Prodia's flux-2-pro schema gives the prompt a maxLength of 32,768.
467
+ prompt: { referenceSyntax: "numbered", maxChars: 32768 }
457
468
  },
458
469
  defaults: { size: "1K", aspectRatio: "1:1" },
459
470
  usage: { ...IMAGE_USAGE },
@@ -1247,12 +1258,17 @@ var TEXT_MODELS = [
1247
1258
  var VIDEO_USAGE = { unit: "seconds" };
1248
1259
  var SEEDANCE_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16", "adaptive"];
1249
1260
  var KLING_RATIOS = ["16:9", "9:16", "1:1", "adaptive"];
1261
+ var KLING_OMNI_RATIOS = ["16:9", "9:16", "1:1"];
1250
1262
  var OMNI_RATIOS = ["16:9", "9:16"];
1251
1263
  var GROK_RATIOS = ["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"];
1252
1264
  var H3_RATIOS = ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"];
1253
1265
  var H3_REFERENCE_RATIOS = ["adaptive", ...H3_RATIOS];
1254
1266
  var NEGATIVE_PROMPT = "blur, distort, and low quality";
1255
1267
  var FRAMES_EXCLUDE_REFERENCES = { framesExcludeReferences: true };
1268
+ var KLING_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
1269
+ var SEEDANCE_PROMPT = { referenceSyntax: "numbered", maxChars: 3e4 };
1270
+ var H3_PROMPT = { referenceSyntax: "numbered", maxChars: 5e4 };
1271
+ var OMNI_PROMPT = { referenceSyntax: "caption", maxChars: 5e4 };
1256
1272
  var BYTEDANCE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/3bba5d81-4e57-4e71-911b-cdfa05acca2c_compressed.png";
1257
1273
  var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
1258
1274
  var VIDEO_MODELS = [
@@ -1273,9 +1289,13 @@ var VIDEO_MODELS = [
1273
1289
  constraints: {
1274
1290
  aspectRatios: [...OMNI_RATIOS],
1275
1291
  resolutions: ["720p", "1080p", "4k"],
1292
+ // Veo also takes 4 and 6, but must be 8 at 1080p/4k or with reference images;
1293
+ // [8] until the kit has a rule that forces it there (CHANGELOG 0.2.21).
1276
1294
  durations: [8],
1277
1295
  references: { images: 3 },
1278
1296
  supports: ["lastFrame", "seed"],
1297
+ // 1,024 text tokens; 3,000 characters assumes ~2.9 characters per token.
1298
+ prompt: { referenceSyntax: "numbered", maxChars: 3e3 },
1279
1299
  audio: "always"
1280
1300
  },
1281
1301
  defaults: { durationSeconds: 8, resolution: "720p", aspectRatio: "16:9" },
@@ -1286,7 +1306,8 @@ var VIDEO_MODELS = [
1286
1306
  description: "Google's highest-quality video generation model. Supports up to 4K resolution and 8-second clips with reference image conditioning.",
1287
1307
  logo: GOOGLE_LOGO2
1288
1308
  },
1289
- capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
1309
+ // Veo's lastFrame "must be used in combination with the image parameter".
1310
+ capabilities: { ...FRAMES_EXCLUDE_REFERENCES, lastFrameRequiresFirstFrame: true }
1290
1311
  },
1291
1312
  {
1292
1313
  id: "veo-3.1-fast",
@@ -1371,8 +1392,7 @@ var VIDEO_MODELS = [
1371
1392
  references: { images: 6, videos: 1, videoSeconds: { max: 10 } },
1372
1393
  sourceVideoSeconds: { max: 10 },
1373
1394
  supports: [],
1374
- // generateOmniVideo sends MediaRef.label as a text part beside each image.
1375
- prompt: { referenceSyntax: "caption" },
1395
+ prompt: OMNI_PROMPT,
1376
1396
  audio: "always"
1377
1397
  },
1378
1398
  defaults: {},
@@ -1406,10 +1426,10 @@ var VIDEO_MODELS = [
1406
1426
  // extension can upload a <= 10 s source with task "extend"; later ones
1407
1427
  // chain by `previousInteractionId` (the API rejects the id together
1408
1428
  // with a video task, so those calls carry the prompt alone).
1409
- supports: ["videoExtension"],
1429
+ // First-to-last-frame interpolation: `<LAST_FRAME>` goes with `<FIRST_FRAME>`.
1430
+ supports: ["videoExtension", "lastFrame"],
1410
1431
  extension: { segmentSeconds: 10, maxTotalSeconds: 40 },
1411
- // generateOmniVideo sends MediaRef.label as a text part beside each image.
1412
- prompt: { referenceSyntax: "caption" },
1432
+ prompt: OMNI_PROMPT,
1413
1433
  audio: "always"
1414
1434
  },
1415
1435
  defaults: {},
@@ -1420,7 +1440,7 @@ var VIDEO_MODELS = [
1420
1440
  logo: GOOGLE_LOGO2,
1421
1441
  description: "Google Gemini Omni Flash 1.1 conversational video generation, editing and extension; text, image, and up to 10-second video input, 3-10 second output at up to 4K and 24 FPS, extendable to 40 seconds."
1422
1442
  },
1423
- capabilities: { acceptsSourceVideo: true }
1443
+ capabilities: { acceptsSourceVideo: true, lastFrameRequiresFirstFrame: true }
1424
1444
  },
1425
1445
  {
1426
1446
  // vibe-triggers and Space Builder drop the ratio when a frame is wired; Cowork always sends it.
@@ -1446,7 +1466,9 @@ var VIDEO_MODELS = [
1446
1466
  },
1447
1467
  sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
1448
1468
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1449
- supports: ["generateAudio", "seed", "lastFrame", "watermark"],
1469
+ // No seed: 2.x echoes it but does not honour it (two seeded runs differed, 2026-10-01).
1470
+ supports: ["generateAudio", "lastFrame", "watermark"],
1471
+ prompt: SEEDANCE_PROMPT,
1450
1472
  audio: "optional"
1451
1473
  },
1452
1474
  defaults: {
@@ -1486,7 +1508,9 @@ var VIDEO_MODELS = [
1486
1508
  },
1487
1509
  sourceVideoSeconds: { min: 2, max: 15, inReferenceTotal: true },
1488
1510
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1489
- supports: ["generateAudio", "seed", "lastFrame", "watermark"],
1511
+ // No seed: 2.x echoes it but does not honour it (two seeded runs differed, 2026-10-01).
1512
+ supports: ["generateAudio", "lastFrame", "watermark"],
1513
+ prompt: SEEDANCE_PROMPT,
1490
1514
  audio: "optional"
1491
1515
  },
1492
1516
  defaults: {
@@ -1505,7 +1529,6 @@ var VIDEO_MODELS = [
1505
1529
  capabilities: { acceptsSourceVideo: true, ...FRAMES_EXCLUDE_REFERENCES }
1506
1530
  },
1507
1531
  {
1508
- // generateAudio defaults to false here (trigger-workflows); Space Builder defaults it to true.
1509
1532
  // omni_reference_task_type edit/extend: adaptive ratio, edit sends duration -1.
1510
1533
  id: "seedance-2.5",
1511
1534
  aliases: ["seedance-2-5", "dreamina-seedance-2-5-260628"],
@@ -1527,14 +1550,16 @@ var VIDEO_MODELS = [
1527
1550
  },
1528
1551
  sourceVideoSeconds: { min: 2, max: 30, editMin: 4, inReferenceTotal: true },
1529
1552
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1530
- supports: ["generateAudio", "seed", "lastFrame", "watermark", "taskType"],
1553
+ // No seed: 2.x echoes it but does not honour it (two seeded runs differed, 2026-10-01).
1554
+ supports: ["generateAudio", "lastFrame", "watermark", "taskType"],
1555
+ prompt: SEEDANCE_PROMPT,
1531
1556
  audio: "optional"
1532
1557
  },
1533
1558
  defaults: {
1534
1559
  durationSeconds: 5,
1535
1560
  resolution: "720p",
1536
1561
  aspectRatio: "16:9",
1537
- generateAudio: false
1562
+ generateAudio: true
1538
1563
  },
1539
1564
  usage: { ...VIDEO_USAGE },
1540
1565
  pricingKind: "video_per_second",
@@ -1546,7 +1571,6 @@ var VIDEO_MODELS = [
1546
1571
  capabilities: { acceptsSourceVideo: true, ...FRAMES_EXCLUDE_REFERENCES }
1547
1572
  },
1548
1573
  {
1549
- // Cowork allows 7 reference images and durations 4/6/8/10; Space Builder allows 5 and 1-15s.
1550
1574
  id: "grok-imagine",
1551
1575
  aliases: ["grok-imagine-video", "grokImagine"],
1552
1576
  label: "Grok Imagine",
@@ -1560,7 +1584,8 @@ var VIDEO_MODELS = [
1560
1584
  resolutions: ["480p", "720p"],
1561
1585
  durations: { min: 1, max: 15 },
1562
1586
  durationPresets: [4, 6, 8, 10],
1563
- references: { images: 5 },
1587
+ // xAI: "A maximum of 7 reference images can be provided per request."
1588
+ references: { images: 7 },
1564
1589
  supports: [],
1565
1590
  // xAI can switch sound off (generate_audio); xai-video.ts never sends it.
1566
1591
  audio: "always"
@@ -1585,16 +1610,16 @@ var VIDEO_MODELS = [
1585
1610
  providerModelId: "kling-video/v2.5-turbo/pro/image-to-video",
1586
1611
  lifecycle: "active",
1587
1612
  exposure: ["cowork", "space_builder"],
1613
+ // The endpoint has no aspect_ratio or last_image_url: the start image sets the framing.
1588
1614
  constraints: {
1589
- aspectRatios: [...KLING_RATIOS],
1590
1615
  durations: [5, 10],
1591
1616
  requires: ["firstFrame"],
1592
- supports: ["cfgScale", "negativePrompt", "lastFrame"],
1617
+ supports: ["cfgScale", "negativePrompt"],
1618
+ prompt: KLING_PROMPT,
1593
1619
  audio: "never"
1594
1620
  },
1595
1621
  defaults: {
1596
1622
  durationSeconds: 5,
1597
- aspectRatio: "16:9",
1598
1623
  cfgScale: 0.5,
1599
1624
  negativePrompt: NEGATIVE_PROMPT
1600
1625
  },
@@ -1603,7 +1628,7 @@ var VIDEO_MODELS = [
1603
1628
  display: {
1604
1629
  provider: "kuaishou",
1605
1630
  logo: "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/kling-color.png",
1606
- description: "Kuaishou Kling 2.5 Turbo Pro image-to-video; animates a single input image from a text prompt with an optional end image, 5- or 10-second clips."
1631
+ description: "Kuaishou Kling 2.5 Turbo Pro image-to-video; animates a single input image from a text prompt, 5- or 10-second clips."
1607
1632
  },
1608
1633
  capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
1609
1634
  },
@@ -1617,19 +1642,18 @@ var VIDEO_MODELS = [
1617
1642
  providerModelId: "kling-video/v3.0/pro/image-to-video",
1618
1643
  lifecycle: "active",
1619
1644
  exposure: ["cowork", "space_builder"],
1645
+ // The endpoint has no aspect_ratio or negative_prompt; sound is "on"/"off" (default on).
1620
1646
  constraints: {
1621
- aspectRatios: [...KLING_RATIOS],
1622
1647
  durations: { min: 3, max: 15 },
1623
1648
  requires: ["firstFrame"],
1624
- supports: ["cfgScale", "negativePrompt", "lastFrame"],
1625
- // Higgsfield has a `sound` switch (default on); KlingCreate doesn't send it.
1626
- audio: "always"
1649
+ supports: ["cfgScale", "lastFrame", "generateAudio"],
1650
+ prompt: KLING_PROMPT,
1651
+ audio: "optional"
1627
1652
  },
1628
1653
  defaults: {
1629
1654
  durationSeconds: 5,
1630
- aspectRatio: "16:9",
1631
1655
  cfgScale: 0.5,
1632
- negativePrompt: NEGATIVE_PROMPT
1656
+ generateAudio: true
1633
1657
  },
1634
1658
  usage: { ...VIDEO_USAGE },
1635
1659
  pricingKind: "video_per_second",
@@ -1641,7 +1665,7 @@ var VIDEO_MODELS = [
1641
1665
  capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
1642
1666
  },
1643
1667
  {
1644
- // mode standard/pro selects 720p/1080p; the endpoint takes no separate resolution.
1668
+ // mode standard/pro/4k selects 720p/1080p/4K; the endpoint takes no separate resolution.
1645
1669
  // Replicate: "Max 7 [images] without video, 4 with video"; 4K does not support
1646
1670
  // reference_video. No `videos` limit yet: the adapter sends no reference video,
1647
1671
  // so `imagesWithVideo` stays dormant until one is wired through.
@@ -1654,22 +1678,25 @@ var VIDEO_MODELS = [
1654
1678
  lifecycle: "active",
1655
1679
  exposure: ["cowork", "space_builder"],
1656
1680
  constraints: {
1657
- aspectRatios: [...KLING_RATIOS],
1658
- resolutions: ["720p", "1080p"],
1681
+ aspectRatios: [...KLING_OMNI_RATIOS],
1682
+ resolutions: ["720p", "1080p", "4k"],
1659
1683
  durations: { min: 3, max: 15 },
1660
1684
  references: { images: 7, imagesWithVideo: 4 },
1661
1685
  supports: ["generateAudio", "lastFrame"],
1686
+ prompt: KLING_PROMPT,
1662
1687
  audio: "optional"
1663
1688
  },
1664
- defaults: { durationSeconds: 5, aspectRatio: "16:9", generateAudio: false, mode: "pro" },
1689
+ defaults: { durationSeconds: 5, aspectRatio: "16:9", generateAudio: true, mode: "pro" },
1665
1690
  usage: { unit: "compute_seconds" },
1666
1691
  pricingKind: "video_per_second",
1667
1692
  display: {
1668
1693
  provider: "kuaishou",
1669
1694
  logo: "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/kling-color.png",
1670
- description: "Kuaishou Kling Video 3.0 Omni unified generation and editing from text, start/end images, up to 7 reference images, and reference video; up to 15 seconds at up to 1080p."
1671
- },
1672
- capabilities: {}
1695
+ description: "Kuaishou Kling Video 3.0 Omni unified generation and editing from text, start/end images, up to 7 reference images, and reference video; up to 15 seconds at up to 4K."
1696
+ }
1697
+ // end_image "Requires start_image", but no lastFrameRequiresFirstFrame: SpaceLab resolves
1698
+ // replicate rows in error mode, so the flag would refuse its end-frame-only nodes, which
1699
+ // the adapter sends as start_image.
1673
1700
  },
1674
1701
  {
1675
1702
  id: "minimax-h3",
@@ -1684,7 +1711,10 @@ var VIDEO_MODELS = [
1684
1711
  aspectRatios: [...H3_RATIOS],
1685
1712
  resolutions: ["480p", "768p", "2k", "4k"],
1686
1713
  durations: { min: 5, max: 15 },
1714
+ // fal's image-to-video endpoint has no aspect_ratio; the frame sets it.
1715
+ ratioIgnoredWith: ["firstFrame"],
1687
1716
  supports: ["seed", "promptExpansion", "lastFrame", "safetyChecker"],
1717
+ prompt: H3_PROMPT,
1688
1718
  audio: "always"
1689
1719
  },
1690
1720
  defaults: {
@@ -1713,9 +1743,12 @@ var VIDEO_MODELS = [
1713
1743
  exposure: ["cowork", "space_builder"],
1714
1744
  constraints: {
1715
1745
  aspectRatios: [...H3_RATIOS],
1716
- resolutions: ["480p", "768p"],
1746
+ resolutions: ["480p", "768p", "1080p"],
1717
1747
  durations: { min: 5, max: 15 },
1748
+ // fal's image-to-video endpoint has no aspect_ratio; the frame sets it.
1749
+ ratioIgnoredWith: ["firstFrame"],
1718
1750
  supports: ["seed", "promptExpansion", "lastFrame", "safetyChecker"],
1751
+ prompt: H3_PROMPT,
1719
1752
  audio: "always"
1720
1753
  },
1721
1754
  defaults: {
@@ -1729,7 +1762,7 @@ var VIDEO_MODELS = [
1729
1762
  display: {
1730
1763
  provider: "minimax",
1731
1764
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/f4c2e906-28b7-4a4a-b491-df8fef7808ed.png",
1732
- description: "High-speed MiniMax H3 Max variant for text-to-video and image-to-video (first/last frame) only, up to 768p."
1765
+ description: "High-speed MiniMax H3 Max variant for text-to-video and image-to-video (first/last frame) only, up to 1080p."
1733
1766
  },
1734
1767
  capabilities: { ...FRAMES_EXCLUDE_REFERENCES }
1735
1768
  },
@@ -1746,6 +1779,8 @@ var VIDEO_MODELS = [
1746
1779
  aspectRatios: [...H3_REFERENCE_RATIOS],
1747
1780
  resolutions: ["480p", "768p", "2k", "4k"],
1748
1781
  durations: { min: 5, max: 15 },
1782
+ // A start frame routes to image-to-video, which has no aspect_ratio.
1783
+ ratioIgnoredWith: ["firstFrame"],
1749
1784
  references: {
1750
1785
  images: 9,
1751
1786
  videos: 3,
@@ -1755,6 +1790,7 @@ var VIDEO_MODELS = [
1755
1790
  videoSeconds: { min: 2, max: 15, total: 15 }
1756
1791
  },
1757
1792
  supports: ["seed", "promptExpansion", "safetyChecker"],
1793
+ prompt: H3_PROMPT,
1758
1794
  audio: "always"
1759
1795
  },
1760
1796
  defaults: {
@@ -1785,8 +1821,10 @@ var VIDEO_MODELS = [
1785
1821
  exposure: ["cowork", "space_builder"],
1786
1822
  constraints: {
1787
1823
  aspectRatios: [...H3_REFERENCE_RATIOS],
1788
- resolutions: ["480p", "768p"],
1824
+ resolutions: ["480p", "768p", "1080p"],
1789
1825
  durations: { min: 5, max: 15 },
1826
+ // A start frame routes to image-to-video, which has no aspect_ratio.
1827
+ ratioIgnoredWith: ["firstFrame"],
1790
1828
  references: {
1791
1829
  images: 9,
1792
1830
  videos: 3,
@@ -1796,6 +1834,7 @@ var VIDEO_MODELS = [
1796
1834
  videoSeconds: { min: 2, max: 15, total: 15 }
1797
1835
  },
1798
1836
  supports: ["seed", "promptExpansion", "safetyChecker"],
1837
+ prompt: H3_PROMPT,
1799
1838
  audio: "always"
1800
1839
  },
1801
1840
  defaults: {
@@ -2344,6 +2383,7 @@ var CatalogDisplaySchema = z3.looseObject({
2344
2383
  var CatalogCapabilitiesSchema = z3.looseObject({
2345
2384
  acceptsSourceVideo: z3.boolean().optional(),
2346
2385
  framesExcludeReferences: z3.boolean().optional(),
2386
+ lastFrameRequiresFirstFrame: z3.boolean().optional(),
2347
2387
  reasoning: z3.boolean().optional(),
2348
2388
  vision: z3.boolean().optional(),
2349
2389
  contextWindow: z3.number().optional()
@@ -2925,6 +2965,24 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
2925
2965
  });
2926
2966
  delete merged.sourceVideo;
2927
2967
  }
2968
+ if (merged.lastFrame !== void 0 && merged.firstFrame === void 0 && model.capabilities?.lastFrameRequiresFirstFrame) {
2969
+ if (onUnsupported === "error") {
2970
+ throw new ModelKitError({
2971
+ code: "missing_input",
2972
+ message: `${model.id} takes an end frame only together with a start frame`,
2973
+ model: model.id,
2974
+ retryable: false
2975
+ });
2976
+ }
2977
+ warnings.push({
2978
+ code: "option_ignored",
2979
+ field: "lastFrame",
2980
+ to: "firstFrame",
2981
+ message: `end frame used as start frame: ${model.id} needs a start frame with an end frame`
2982
+ });
2983
+ merged.firstFrame = merged.lastFrame;
2984
+ delete merged.lastFrame;
2985
+ }
2928
2986
  const hasFrames = merged.firstFrame !== void 0 || merged.lastFrame !== void 0;
2929
2987
  const hasRefs = compact(merged.referenceImages).length + compact(merged.referenceVideos).length + compact(merged.referenceAudios).length > 0;
2930
2988
  if (hasFrames && hasRefs && model.capabilities?.framesExcludeReferences) {