@shop-os/modelkit 0.2.21 → 0.2.23

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/CHANGELOG.md CHANGED
@@ -9,6 +9,30 @@ header in the release PR.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.2.23] - Unreleased
13
+
14
+ ### Added
15
+ - `billedAudio(row, requested?)` on `@shop-os/modelkit/catalog`, next to `outputAudio`: whether a video request is billed as having sound. `always` rows are true, `never` rows false; an `optional` row takes `requested`, then the row's `defaults.generateAudio`, then true. A row with no valid `constraints.audio` is true. Every fallback is true because pro-backend's base video price is the sound-on price and a silent rate applies only to a line item that says `with_audio: false`, so a guess can overcharge but never undercharge. Callers (cowork Studio and chat, vibe-api's pricing classifier) pass the same `requested` value they dispatch with, so the billed and the generated sound cannot drift apart.
16
+
17
+ ## [0.2.22] - Unreleased
18
+
19
+ ### Added
20
+ - `constraints.prompt.maxChars` on every bundled row with a documented prompt limit, so Studio accepts prompts longer than its 5,000-character default where the model takes them. Each row keeps its reference syntax (`numbered`, or `caption` on the Gemini rows):
21
+ - `seedance-2.0`, `seedance-2.0-fast`, `seedance-2.5`: 30000. BytePlus caps the prompt at 10,000 tokens; 30,000 characters assumes English prompts at about 3 characters per token, with margin. A CJK prompt can reach the token limit sooner.
22
+ - `gpt-image-2`, `gpt-image-2.5-flare`, `gpt-image-2.5-sunburst`: 32000 (OpenAI images API: 32,000 characters for GPT image models).
23
+ - `flux-2-pro`: 32768 (Prodia schema `maxLength`).
24
+ - `minimax-h3`, `minimax-h3-max`, `minimax-h3-reference`, `minimax-h3-max-reference`: 50000 (fal schema `maxLength` 50,000).
25
+ - `gemini-3-pro-image-preview`, `gemini-3.1-flash-image-preview`, `gemini-3.1-flash-lite-image`, `gemini-omni-flash`, `gemini-omni-1.1-flash`: 50000. Their token budgets are far above this; 50,000 is cowork's global prompt ceiling.
26
+ - Unchanged: `kling-2.5`, `kling-3.0`, `kling-v3-omni-video` at 2500 and `veo-3.1` at 3000. No limit on `grok-imagine`, `muse-image-1.0`, `seedream-5-0-pro` or any other row without a documented one, so Studio keeps its 5,000 default there.
27
+
28
+ ### Live rows to edit after publish
29
+ Apps read the pro-backend `model_catalog` rows, not this file. Edit an environment's rows only after the companion cowork + spacelab-mcp change (Studio's global prompt ceiling raised from 5,000 to 50,000) is deployed there. Before that, cowork's projection would report `maxPromptChars: 30000`, while its request schema and spacelab-mcp still refuse anything over 5,000. After pro-backend is on 0.2.22, in each environment:
30
+ - `seedance-2.0`, `seedance-2.0-fast`, `seedance-2.5`: `constraints.prompt` → `{ "referenceSyntax": "numbered", "maxChars": 30000 }` (assumes English prompts).
31
+ - `gpt-image-2`, `gpt-image-2.5-flare`, `gpt-image-2.5-sunburst`: `constraints.prompt` → `{ "referenceSyntax": "numbered", "maxChars": 32000 }`.
32
+ - `flux-2-pro`: `constraints.prompt` → `{ "referenceSyntax": "numbered", "maxChars": 32768 }`.
33
+ - `minimax-h3`, `minimax-h3-max`, `minimax-h3-reference`, `minimax-h3-max-reference`: `constraints.prompt` → `{ "referenceSyntax": "numbered", "maxChars": 50000 }`.
34
+ - `gemini-3-pro-image-preview`, `gemini-3.1-flash-image-preview`, `gemini-3.1-flash-lite-image`, `gemini-omni-flash`, `gemini-omni-1.1-flash`: `constraints.prompt` → `{ "referenceSyntax": "caption", "maxChars": 50000 }`.
35
+
12
36
  ## [0.2.21] - Unreleased
13
37
 
14
38
  ### Added
package/dist/catalog.cjs CHANGED
@@ -36,6 +36,7 @@ __export(catalog_entry_exports, {
36
36
  SurfaceSchema: () => SurfaceSchema,
37
37
  TEXT_MODELS: () => TEXT_MODELS,
38
38
  VIDEO_MODELS: () => VIDEO_MODELS,
39
+ billedAudio: () => billedAudio,
39
40
  compareCatalogOrder: () => compareCatalogOrder,
40
41
  isListed: () => isListed,
41
42
  isListedOn: () => isListedOn,
@@ -217,13 +218,16 @@ var GEMINI_RATIOS = [
217
218
  "5:4",
218
219
  "adaptive"
219
220
  ];
220
- function geminiImage(id, label, aliases, sizes, display, exposure, references) {
221
+ var GEMINI_PROMPT_MAX_CHARS = 5e4;
222
+ var GPT_IMAGE_PROMPT = { referenceSyntax: "numbered", maxChars: 32e3 };
223
+ function geminiImage(id, label, aliases, sizes, display, exposure, references, promptMaxChars) {
224
+ const prompt = { referenceSyntax: "caption" };
225
+ if (promptMaxChars !== void 0) prompt.maxChars = promptMaxChars;
221
226
  const constraints = {
222
227
  aspectRatios: [...GEMINI_RATIOS],
223
228
  sizes,
224
229
  supports: ["safetySettings", "temperature"],
225
- // google-image sends MediaRef.label as a text part beside each reference.
226
- prompt: { referenceSyntax: "caption" }
230
+ prompt
227
231
  };
228
232
  if (references !== void 0) constraints.references = references;
229
233
  const model = {
@@ -255,7 +259,8 @@ var IMAGE_MODELS = [
255
259
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
256
260
  },
257
261
  ["cowork", "space_builder"],
258
- { images: 14 }
262
+ { images: 14 },
263
+ GEMINI_PROMPT_MAX_CHARS
259
264
  ),
260
265
  geminiImage(
261
266
  "gemini-3.1-flash-image-preview",
@@ -269,7 +274,8 @@ var IMAGE_MODELS = [
269
274
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
270
275
  },
271
276
  ["cowork", "space_builder"],
272
- { images: 14 }
277
+ { images: 14 },
278
+ GEMINI_PROMPT_MAX_CHARS
273
279
  ),
274
280
  geminiImage(
275
281
  "gemini-3.1-flash-lite-image",
@@ -282,7 +288,8 @@ var IMAGE_MODELS = [
282
288
  logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
283
289
  },
284
290
  ["cowork", "space_builder"],
285
- { images: 14 }
291
+ { images: 14 },
292
+ GEMINI_PROMPT_MAX_CHARS
286
293
  ),
287
294
  // trigger-workflows validates 1K only; pricing seeds 2K/4K rows so allow all three.
288
295
  geminiImage(
@@ -320,7 +327,8 @@ var IMAGE_MODELS = [
320
327
  sizes: ["1K", "2K", "4K"],
321
328
  qualityOptions: ["auto", "low", "medium", "high"],
322
329
  references: { images: 16 },
323
- supports: ["quality", "count", "outputFormat"]
330
+ supports: ["quality", "count", "outputFormat"],
331
+ prompt: GPT_IMAGE_PROMPT
324
332
  },
325
333
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
326
334
  usage: { ...IMAGE_USAGE, slug: "gpt" },
@@ -355,7 +363,8 @@ var IMAGE_MODELS = [
355
363
  sizes: ["1K", "2K", "4K"],
356
364
  qualityOptions: ["auto", "low", "medium", "high", "xhigh", "max"],
357
365
  references: { images: 16 },
358
- supports: ["quality", "count", "outputFormat"]
366
+ supports: ["quality", "count", "outputFormat"],
367
+ prompt: GPT_IMAGE_PROMPT
359
368
  },
360
369
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
361
370
  usage: { ...IMAGE_USAGE },
@@ -389,7 +398,8 @@ var IMAGE_MODELS = [
389
398
  sizes: ["1K", "2K", "4K"],
390
399
  qualityOptions: ["auto", "low", "medium", "high", "xhigh", "max"],
391
400
  references: { images: 16 },
392
- supports: ["quality", "count", "outputFormat"]
401
+ supports: ["quality", "count", "outputFormat"],
402
+ prompt: GPT_IMAGE_PROMPT
393
403
  },
394
404
  defaults: { size: "1K", aspectRatio: "adaptive", quality: "auto" },
395
405
  usage: { ...IMAGE_USAGE },
@@ -512,7 +522,9 @@ var IMAGE_MODELS = [
512
522
  sizes: ["1K"],
513
523
  references: { images: 8 },
514
524
  // flux-2-pro's job type always returns image/png; only the seed is forwarded.
515
- supports: ["seed"]
525
+ supports: ["seed"],
526
+ // Prodia's flux-2-pro schema gives the prompt a maxLength of 32,768.
527
+ prompt: { referenceSyntax: "numbered", maxChars: 32768 }
516
528
  },
517
529
  defaults: { size: "1K", aspectRatio: "1:1" },
518
530
  usage: { ...IMAGE_USAGE },
@@ -1314,6 +1326,9 @@ var H3_REFERENCE_RATIOS = ["adaptive", ...H3_RATIOS];
1314
1326
  var NEGATIVE_PROMPT = "blur, distort, and low quality";
1315
1327
  var FRAMES_EXCLUDE_REFERENCES = { framesExcludeReferences: true };
1316
1328
  var KLING_PROMPT = { referenceSyntax: "numbered", maxChars: 2500 };
1329
+ var SEEDANCE_PROMPT = { referenceSyntax: "numbered", maxChars: 3e4 };
1330
+ var H3_PROMPT = { referenceSyntax: "numbered", maxChars: 5e4 };
1331
+ var OMNI_PROMPT = { referenceSyntax: "caption", maxChars: 5e4 };
1317
1332
  var BYTEDANCE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/3bba5d81-4e57-4e71-911b-cdfa05acca2c_compressed.png";
1318
1333
  var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
1319
1334
  var VIDEO_MODELS = [
@@ -1437,8 +1452,7 @@ var VIDEO_MODELS = [
1437
1452
  references: { images: 6, videos: 1, videoSeconds: { max: 10 } },
1438
1453
  sourceVideoSeconds: { max: 10 },
1439
1454
  supports: [],
1440
- // generateOmniVideo sends MediaRef.label as a text part beside each image.
1441
- prompt: { referenceSyntax: "caption" },
1455
+ prompt: OMNI_PROMPT,
1442
1456
  audio: "always"
1443
1457
  },
1444
1458
  defaults: {},
@@ -1475,8 +1489,7 @@ var VIDEO_MODELS = [
1475
1489
  // First-to-last-frame interpolation: `<LAST_FRAME>` goes with `<FIRST_FRAME>`.
1476
1490
  supports: ["videoExtension", "lastFrame"],
1477
1491
  extension: { segmentSeconds: 10, maxTotalSeconds: 40 },
1478
- // generateOmniVideo sends MediaRef.label as a text part beside each image.
1479
- prompt: { referenceSyntax: "caption" },
1492
+ prompt: OMNI_PROMPT,
1480
1493
  audio: "always"
1481
1494
  },
1482
1495
  defaults: {},
@@ -1515,6 +1528,7 @@ var VIDEO_MODELS = [
1515
1528
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1516
1529
  // No seed: 2.x echoes it but does not honour it (two seeded runs differed, 2026-10-01).
1517
1530
  supports: ["generateAudio", "lastFrame", "watermark"],
1531
+ prompt: SEEDANCE_PROMPT,
1518
1532
  audio: "optional"
1519
1533
  },
1520
1534
  defaults: {
@@ -1556,6 +1570,7 @@ var VIDEO_MODELS = [
1556
1570
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1557
1571
  // No seed: 2.x echoes it but does not honour it (two seeded runs differed, 2026-10-01).
1558
1572
  supports: ["generateAudio", "lastFrame", "watermark"],
1573
+ prompt: SEEDANCE_PROMPT,
1559
1574
  audio: "optional"
1560
1575
  },
1561
1576
  defaults: {
@@ -1597,6 +1612,7 @@ var VIDEO_MODELS = [
1597
1612
  ratioIgnoredWith: ["firstFrame", "sourceVideo"],
1598
1613
  // No seed: 2.x echoes it but does not honour it (two seeded runs differed, 2026-10-01).
1599
1614
  supports: ["generateAudio", "lastFrame", "watermark", "taskType"],
1615
+ prompt: SEEDANCE_PROMPT,
1600
1616
  audio: "optional"
1601
1617
  },
1602
1618
  defaults: {
@@ -1758,6 +1774,7 @@ var VIDEO_MODELS = [
1758
1774
  // fal's image-to-video endpoint has no aspect_ratio; the frame sets it.
1759
1775
  ratioIgnoredWith: ["firstFrame"],
1760
1776
  supports: ["seed", "promptExpansion", "lastFrame", "safetyChecker"],
1777
+ prompt: H3_PROMPT,
1761
1778
  audio: "always"
1762
1779
  },
1763
1780
  defaults: {
@@ -1791,6 +1808,7 @@ var VIDEO_MODELS = [
1791
1808
  // fal's image-to-video endpoint has no aspect_ratio; the frame sets it.
1792
1809
  ratioIgnoredWith: ["firstFrame"],
1793
1810
  supports: ["seed", "promptExpansion", "lastFrame", "safetyChecker"],
1811
+ prompt: H3_PROMPT,
1794
1812
  audio: "always"
1795
1813
  },
1796
1814
  defaults: {
@@ -1832,6 +1850,7 @@ var VIDEO_MODELS = [
1832
1850
  videoSeconds: { min: 2, max: 15, total: 15 }
1833
1851
  },
1834
1852
  supports: ["seed", "promptExpansion", "safetyChecker"],
1853
+ prompt: H3_PROMPT,
1835
1854
  audio: "always"
1836
1855
  },
1837
1856
  defaults: {
@@ -1875,6 +1894,7 @@ var VIDEO_MODELS = [
1875
1894
  videoSeconds: { min: 2, max: 15, total: 15 }
1876
1895
  },
1877
1896
  supports: ["seed", "promptExpansion", "safetyChecker"],
1897
+ prompt: H3_PROMPT,
1878
1898
  audio: "always"
1879
1899
  },
1880
1900
  defaults: {
@@ -2051,6 +2071,17 @@ function outputAudio(row) {
2051
2071
  const view = ConstraintsReadView.safeParse(row.constraints);
2052
2072
  return view.success ? view.data.audio : void 0;
2053
2073
  }
2074
+ var DefaultsReadView = import_zod.z.looseObject({
2075
+ generateAudio: import_zod.z.boolean().optional().catch(void 0)
2076
+ });
2077
+ function billedAudio(row, requested) {
2078
+ const audio = outputAudio(row);
2079
+ if (audio === "never") return false;
2080
+ if (audio !== "optional") return true;
2081
+ if (requested !== void 0) return requested;
2082
+ const defaults = DefaultsReadView.safeParse(row.defaults);
2083
+ return (defaults.success ? defaults.data.generateAudio : void 0) ?? true;
2084
+ }
2054
2085
  function promptConventions(row) {
2055
2086
  const view = ConstraintsReadView.safeParse(row.constraints);
2056
2087
  const prompt = view.success ? view.data.prompt : void 0;