@shop-os/modelkit 0.7.0 → 0.7.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/CHANGELOG.md CHANGED
@@ -9,6 +9,22 @@ header in the release PR.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.7.2] - Unreleased
13
+
14
+ ENG-3272 review fixes. Merged as a second 0.7.1 after FlashVSR's 0.7.1 had published, so npm never got it; released as 0.7.2.
15
+
16
+ ### Added
17
+ - `takesTargetAspectRatio(row)` (both entries): a row that requires a source video and lists ratios without `"adaptive"` renders the source into the ratio it is given (Ray 3.2 Reframe). Consumers send a ratio to an edit only for these rows; every other edit keeps the source's framing (H3 Max Relight lists `"adaptive"`, so it stays out).
18
+ - `lumaReframeTooTall(req)`: a 9:16 or 3:4 target at 1080p, which Luma renders at 720p.
19
+
20
+ ### Changed
21
+ - `resolveVideoOptions` on a luma reframe row refuses (`error`) or replaces with the row default (`coerce`) an `"adaptive"` or missing target ratio, and refuses or lowers a vertical 1080p target to 720p. The rule runs where quotes read the request, so a hold is never taken at a rate the render will not use; the adapter keeps the same check as a backstop.
22
+
23
+ ## [0.7.1] - Unreleased
24
+
25
+ ### Changed
26
+ - FlashVSR (`flashvsr`) is retired (`replacedBy: "flux-video-upscale-precise"`). fal bills it per output megapixel-frame, but its price rows tier by the output's short edge, so square, wide and above-4k outputs were billed below cost (ENG-3314). The dev, stg and prod catalog rows were retired on 2026-10-21; this keeps a fresh seed the same.
27
+
12
28
  ## [0.7.0] - Unreleased
13
29
 
14
30
  ENG-3272: Luma (Agents API, direct) image and video models.
package/dist/catalog.cjs CHANGED
@@ -49,6 +49,7 @@ __export(catalog_entry_exports, {
49
49
  isModelKitError: () => isModelKitError,
50
50
  liveCatalog: () => liveCatalog,
51
51
  liveState: () => liveState,
52
+ lumaReframeTooTall: () => lumaReframeTooTall,
52
53
  model3dConstraints: () => model3dConstraints,
53
54
  model3dInputRefusal: () => model3dInputRefusal,
54
55
  model3dPricingSku: () => model3dPricingSku,
@@ -74,6 +75,7 @@ __export(catalog_entry_exports, {
74
75
  resolveVideoOptions: () => resolveVideoOptions,
75
76
  resolveVoiceChangeOptions: () => resolveVoiceChangeOptions,
76
77
  sortCatalogRows: () => sortCatalogRows,
78
+ takesTargetAspectRatio: () => takesTargetAspectRatio,
77
79
  videoLengthViolation: () => videoLengthViolation,
78
80
  videoToolConstraints: () => videoToolConstraints
79
81
  });
@@ -6207,14 +6209,17 @@ var VIDEO_TOOL_MODELS = [
6207
6209
  {
6208
6210
  // https://fal.ai/models/fal-ai/flashvsr/upscale/video/api: upscale_factor 1-4, X264 MP4
6209
6211
  // by default; fal bills $0.0005 per output megapixel-frame (width x height x frames).
6212
+ // Retired (ENG-3314): the price rows tier by short edge, which under-prices square, wide
6213
+ // and above-4k outputs.
6210
6214
  id: "flashvsr",
6211
6215
  aliases: ["flashvsr-upscale"],
6212
6216
  label: "FlashVSR",
6213
6217
  type: "video-tool",
6214
6218
  adapter: "fal",
6215
6219
  providerModelId: "fal-ai/flashvsr/upscale/video",
6216
- lifecycle: "active",
6217
- exposure: ["cowork", "space_builder"],
6220
+ lifecycle: "retired",
6221
+ replacedBy: "flux-video-upscale-precise",
6222
+ exposure: [],
6218
6223
  constraints: {
6219
6224
  supports: [],
6220
6225
  tool: { kind: "upscale", upscaleFactor: { min: 1, max: 4 } }
@@ -6417,6 +6422,57 @@ function applyXaiVideoRules(model, req, onUnsupported, warnings) {
6417
6422
  });
6418
6423
  req.resolution = XAI_REFERENCE_MAX_RESOLUTION;
6419
6424
  }
6425
+ function takesTargetAspectRatio(model) {
6426
+ const ratios = model.constraints.aspectRatios ?? [];
6427
+ return (model.constraints.requires ?? []).includes("sourceVideo") && ratios.length > 0 && !ratios.includes("adaptive");
6428
+ }
6429
+ var LUMA_REFRAME_VERTICAL_MAX_RESOLUTION = "720p";
6430
+ function lumaReframeTooTall(req) {
6431
+ const vertical = req.aspectRatio === "9:16" || req.aspectRatio === "3:4";
6432
+ return vertical && req.resolution === "1080p";
6433
+ }
6434
+ function applyLumaVideoRules(model, req, onUnsupported, warnings) {
6435
+ if (model.adapter !== "luma" || !takesTargetAspectRatio(model)) return;
6436
+ if (req.aspectRatio === void 0 || req.aspectRatio === "adaptive") {
6437
+ const listed2 = model.constraints.aspectRatios ?? [];
6438
+ const fallback = model.defaults.aspectRatio !== void 0 && model.defaults.aspectRatio !== "adaptive" ? model.defaults.aspectRatio : listed2[0];
6439
+ const message2 = `${model.id} needs a target aspect ratio: ${listed2.join(", ")}`;
6440
+ if (onUnsupported === "error" || fallback === void 0) {
6441
+ throw new ModelKitError({
6442
+ code: "unsupported_option",
6443
+ message: message2,
6444
+ model: model.id,
6445
+ retryable: false
6446
+ });
6447
+ }
6448
+ warnings.push({
6449
+ code: "ratio_coerced",
6450
+ field: "aspectRatio",
6451
+ from: req.aspectRatio ?? "adaptive",
6452
+ to: fallback,
6453
+ message: message2
6454
+ });
6455
+ req.aspectRatio = fallback;
6456
+ }
6457
+ if (!lumaReframeTooTall(req)) return;
6458
+ const message = `${model.id} renders 9:16 and 3:4 reframes at up to ${LUMA_REFRAME_VERTICAL_MAX_RESOLUTION}`;
6459
+ if (onUnsupported === "error") {
6460
+ throw new ModelKitError({
6461
+ code: "unsupported_option",
6462
+ message,
6463
+ model: model.id,
6464
+ retryable: false
6465
+ });
6466
+ }
6467
+ warnings.push({
6468
+ code: "resolution_coerced",
6469
+ field: "resolution",
6470
+ from: req.resolution,
6471
+ to: LUMA_REFRAME_VERTICAL_MAX_RESOLUTION,
6472
+ message
6473
+ });
6474
+ req.resolution = LUMA_REFRAME_VERTICAL_MAX_RESOLUTION;
6475
+ }
6420
6476
  var MINIMAX_H3_INSERT = "minimax/h3-max/insert-video";
6421
6477
  var INSERT_MIN = 1.625;
6422
6478
  var INSERT_MAX = 60;
@@ -9130,6 +9186,7 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
9130
9186
  delete merged.previousInteractionId;
9131
9187
  }
9132
9188
  applyXaiVideoRules(model, merged, onUnsupported, warnings);
9189
+ applyLumaVideoRules(model, merged, onUnsupported, warnings);
9133
9190
  checkVideoRequired(model, merged);
9134
9191
  applyFalVideoRules(model, merged, request.aspectRatio, warnings);
9135
9192
  return { request: merged, warnings };