@shop-os/modelkit 0.7.1 → 0.7.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.
package/CHANGELOG.md CHANGED
@@ -9,6 +9,33 @@ header in the release PR.
9
9
 
10
10
  ## [Unreleased]
11
11
 
12
+ ## [0.7.3] - Unreleased
13
+
14
+ ENG-3272 Luma code review follow-ups.
15
+
16
+ ### Changed
17
+ - `ray-3.2` (generate) returns the output as `{ url, expiresAt }` instead of downloading it: its 5 s bill needs no bytes. Luma's URL lasts 1 hour; `expiresAt` is 55 minutes after the result. Edit and reframe still download the MP4 to read its length, and that download is now retried.
18
+ - A URL source for edit or reframe sends `media_type` from its extension (`.mov` is `video/quicktime`, `.webm` is `video/webm`), else `video/mp4`.
19
+ - Luma receives the `providerModelId` lowercased, the same spelling the row checks accept.
20
+
21
+ ### Fixed
22
+ - An edit or reframe whose MP4 length cannot be read bills the caller's measured `durationSeconds` for an inline (`bytes`) source too, not only for a URL source. Before, it billed 5 s.
23
+ - The MP4 length reader reads boxes with a 64-bit size or a size of 0 (box to end of file), so a `moov` after a large `mdat` is found.
24
+ - A completed video takes only an output typed `video` (or untyped); an output of another type is no longer downloaded as the video.
25
+ - `result({ signal })` also cancels the poll requests and the download, not only the wait between polls.
26
+ - A 200 response that is not JSON is a `ModelKitError`: on submit `provider_rejected`, on a poll a transient `network` error that keeps polling.
27
+
28
+ ## [0.7.2] - Unreleased
29
+
30
+ 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.
31
+
32
+ ### Added
33
+ - `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).
34
+ - `lumaReframeTooTall(req)`: a 9:16 or 3:4 target at 1080p, which Luma renders at 720p.
35
+
36
+ ### Changed
37
+ - `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.
38
+
12
39
  ## [0.7.1] - Unreleased
13
40
 
14
41
  ### Changed
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
  });
@@ -6420,6 +6422,57 @@ function applyXaiVideoRules(model, req, onUnsupported, warnings) {
6420
6422
  });
6421
6423
  req.resolution = XAI_REFERENCE_MAX_RESOLUTION;
6422
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
+ }
6423
6476
  var MINIMAX_H3_INSERT = "minimax/h3-max/insert-video";
6424
6477
  var INSERT_MIN = 1.625;
6425
6478
  var INSERT_MAX = 60;
@@ -9133,6 +9186,7 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
9133
9186
  delete merged.previousInteractionId;
9134
9187
  }
9135
9188
  applyXaiVideoRules(model, merged, onUnsupported, warnings);
9189
+ applyLumaVideoRules(model, merged, onUnsupported, warnings);
9136
9190
  checkVideoRequired(model, merged);
9137
9191
  applyFalVideoRules(model, merged, request.aspectRatio, warnings);
9138
9192
  return { request: merged, warnings };