@shop-os/modelkit 0.7.2 → 0.7.4
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 +23 -0
- package/dist/catalog.cjs +155 -150
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.js +155 -150
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +294 -211
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +294 -211
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,29 @@ header in the release PR.
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [0.7.4] - Unreleased
|
|
13
|
+
|
|
14
|
+
ENG-3321: one source of truth for each 3D family's options.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- The 3D family rules (`MODEL3D_FAMILY_RULES`, `model3dSpecIssues`) move from the catalog schema to `catalog/model3d-spec.ts`. Each family's texture and resolution options are now a map to the value the fal request sends (Hi3D `quality`/`master` to `2048quality`/`2048master`; Tripo `texture_quality`; Hunyuan `generate_type`; Meshy's text `mode`; Hi3D `enable_texture`). The catalog check allows only the map's keys and `model3dCall` sends its values, so an option cannot be offered without a value to send. An option missing from the map (only possible on an unvalidated `catalogOverride` row) now fails with `unsupported_option` instead of being sent as the family's default. Every request the current rows can make sends the same body as before.
|
|
18
|
+
|
|
19
|
+
## [0.7.3] - Unreleased
|
|
20
|
+
|
|
21
|
+
ENG-3272 Luma code review follow-ups.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- `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.
|
|
25
|
+
- A URL source for edit or reframe sends `media_type` from its extension (`.mov` is `video/quicktime`, `.webm` is `video/webm`), else `video/mp4`.
|
|
26
|
+
- Luma receives the `providerModelId` lowercased, the same spelling the row checks accept.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- 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.
|
|
30
|
+
- 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.
|
|
31
|
+
- A completed video takes only an output typed `video` (or untyped); an output of another type is no longer downloaded as the video.
|
|
32
|
+
- `result({ signal })` also cancels the poll requests and the download, not only the wait between polls.
|
|
33
|
+
- A 200 response that is not JSON is a `ModelKitError`: on submit `provider_rejected`, on a poll a transient `network` error that keeps polling.
|
|
34
|
+
|
|
12
35
|
## [0.7.2] - Unreleased
|
|
13
36
|
|
|
14
37
|
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.
|
package/dist/catalog.cjs
CHANGED
|
@@ -6633,6 +6633,161 @@ var MODEL3D_IMAGE_SLOTS = {
|
|
|
6633
6633
|
ordered: ["image", "left", "back", "right"],
|
|
6634
6634
|
unordered: ["image", "back", "left", "right", "top"]
|
|
6635
6635
|
};
|
|
6636
|
+
var MODEL3D_FAMILY_RULES = {
|
|
6637
|
+
trellis: {
|
|
6638
|
+
textPath: false,
|
|
6639
|
+
views: ["none"],
|
|
6640
|
+
multiImage: false,
|
|
6641
|
+
texture: null,
|
|
6642
|
+
pbr: false,
|
|
6643
|
+
seed: true,
|
|
6644
|
+
textureRef: false,
|
|
6645
|
+
resolutions: "integer"
|
|
6646
|
+
},
|
|
6647
|
+
hunyuan: {
|
|
6648
|
+
textPath: true,
|
|
6649
|
+
views: ["none", "named"],
|
|
6650
|
+
multiImage: false,
|
|
6651
|
+
// generate_type
|
|
6652
|
+
texture: { none: "Geometry", standard: "Normal" },
|
|
6653
|
+
pbr: true,
|
|
6654
|
+
seed: false,
|
|
6655
|
+
textureRef: false,
|
|
6656
|
+
resolutions: null
|
|
6657
|
+
},
|
|
6658
|
+
tripo: {
|
|
6659
|
+
textPath: true,
|
|
6660
|
+
views: ["none", "ordered"],
|
|
6661
|
+
multiImage: true,
|
|
6662
|
+
// texture_quality; null sends an untextured model.
|
|
6663
|
+
texture: { none: null, standard: "standard", detailed: "detailed" },
|
|
6664
|
+
pbr: true,
|
|
6665
|
+
seed: true,
|
|
6666
|
+
textureRef: false,
|
|
6667
|
+
resolutions: null
|
|
6668
|
+
},
|
|
6669
|
+
rodin: {
|
|
6670
|
+
textPath: true,
|
|
6671
|
+
views: ["none", "unordered"],
|
|
6672
|
+
multiImage: false,
|
|
6673
|
+
texture: null,
|
|
6674
|
+
pbr: false,
|
|
6675
|
+
seed: true,
|
|
6676
|
+
textureRef: false,
|
|
6677
|
+
resolutions: null
|
|
6678
|
+
},
|
|
6679
|
+
meshy: {
|
|
6680
|
+
textPath: true,
|
|
6681
|
+
views: ["none", "unordered"],
|
|
6682
|
+
multiImage: true,
|
|
6683
|
+
// The text endpoint's mode; the image endpoints take should_texture.
|
|
6684
|
+
texture: { none: "preview", standard: "full" },
|
|
6685
|
+
pbr: true,
|
|
6686
|
+
seed: true,
|
|
6687
|
+
textureRef: true,
|
|
6688
|
+
resolutions: null
|
|
6689
|
+
},
|
|
6690
|
+
hi3d: {
|
|
6691
|
+
textPath: false,
|
|
6692
|
+
views: ["none", "named"],
|
|
6693
|
+
multiImage: true,
|
|
6694
|
+
// enable_texture
|
|
6695
|
+
texture: { none: false, standard: true },
|
|
6696
|
+
pbr: true,
|
|
6697
|
+
seed: false,
|
|
6698
|
+
textureRef: false,
|
|
6699
|
+
resolutions: { quality: "2048quality", master: "2048master" }
|
|
6700
|
+
},
|
|
6701
|
+
sam: {
|
|
6702
|
+
textPath: false,
|
|
6703
|
+
views: ["none"],
|
|
6704
|
+
multiImage: false,
|
|
6705
|
+
texture: null,
|
|
6706
|
+
pbr: false,
|
|
6707
|
+
seed: true,
|
|
6708
|
+
textureRef: false,
|
|
6709
|
+
resolutions: null
|
|
6710
|
+
}
|
|
6711
|
+
};
|
|
6712
|
+
function model3dSpecIssues(spec) {
|
|
6713
|
+
const issues = [];
|
|
6714
|
+
const add = (path, message) => issues.push({ path, message });
|
|
6715
|
+
const rules = MODEL3D_FAMILY_RULES[spec.family];
|
|
6716
|
+
const promptOnly = spec.text && !spec.imageRequired;
|
|
6717
|
+
if (spec.endpoints.image === void 0)
|
|
6718
|
+
add(["endpoints", "image"], "every row needs an image endpoint");
|
|
6719
|
+
if (promptOnly && !rules.textPath) {
|
|
6720
|
+
add(
|
|
6721
|
+
["imageRequired"],
|
|
6722
|
+
`${spec.family} has no text-to-3D endpoint; a text row needs an image`
|
|
6723
|
+
);
|
|
6724
|
+
}
|
|
6725
|
+
if (promptOnly && spec.endpoints.text === void 0) {
|
|
6726
|
+
add(["endpoints", "text"], "a text row needs a text endpoint");
|
|
6727
|
+
}
|
|
6728
|
+
if (!rules.views.includes(spec.views)) {
|
|
6729
|
+
add(["views"], `${spec.family} takes views ${rules.views.join(" or ")}`);
|
|
6730
|
+
}
|
|
6731
|
+
if (spec.views === "none" && spec.maxImages !== 1) {
|
|
6732
|
+
add(["maxImages"], "a row without views takes 1 image");
|
|
6733
|
+
}
|
|
6734
|
+
if (spec.views === "unordered" && spec.maxImages < 2) {
|
|
6735
|
+
add(["maxImages"], "a row with views takes at least 2 images");
|
|
6736
|
+
}
|
|
6737
|
+
const slots = MODEL3D_IMAGE_SLOTS[spec.views].length;
|
|
6738
|
+
if (spec.views !== "none" && spec.maxImages > slots) {
|
|
6739
|
+
add(["maxImages"], `a row with ${spec.views} views sends at most ${slots} images`);
|
|
6740
|
+
}
|
|
6741
|
+
if ((spec.views === "named" || spec.views === "ordered") && spec.maxImages < slots) {
|
|
6742
|
+
add(
|
|
6743
|
+
["maxImages"],
|
|
6744
|
+
`a row with ${spec.views} views takes ${slots} images (front and three sides)`
|
|
6745
|
+
);
|
|
6746
|
+
}
|
|
6747
|
+
if (spec.views !== "none" && rules.multiImage && spec.endpoints.multiImage === void 0) {
|
|
6748
|
+
add(["endpoints", "multiImage"], `${spec.family} sends views to a multi-image endpoint`);
|
|
6749
|
+
}
|
|
6750
|
+
if (rules.texture === null) {
|
|
6751
|
+
if (spec.texture.length > 0) add(["texture"], `${spec.family} has no texture switch`);
|
|
6752
|
+
} else {
|
|
6753
|
+
const allowed = rules.texture;
|
|
6754
|
+
if (spec.texture.length === 0) add(["texture"], `${spec.family} needs its texture options`);
|
|
6755
|
+
if (new Set(spec.texture).size !== spec.texture.length)
|
|
6756
|
+
add(["texture"], "texture options repeat");
|
|
6757
|
+
for (const t of spec.texture) {
|
|
6758
|
+
if (!Object.hasOwn(allowed, t))
|
|
6759
|
+
add(["texture"], `${spec.family} has no "${t}" texture`);
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
if (spec.pbr && !rules.pbr) add(["pbr"], `${spec.family} has no PBR switch`);
|
|
6763
|
+
if (spec.pbr && !spec.texture.some((t) => t !== "none")) {
|
|
6764
|
+
add(["pbr"], "PBR needs a textured option");
|
|
6765
|
+
}
|
|
6766
|
+
if (spec.seed && !rules.seed) add(["seed"], `${spec.family} takes no seed`);
|
|
6767
|
+
if (spec.seedMax !== void 0 && !spec.seed) add(["seedMax"], "seedMax needs seed");
|
|
6768
|
+
if (spec.textureRef && !rules.textureRef)
|
|
6769
|
+
add(["textureRef"], `${spec.family} takes no texture reference`);
|
|
6770
|
+
const res = spec.resolutions;
|
|
6771
|
+
if (rules.resolutions === null) {
|
|
6772
|
+
if (res !== void 0) add(["resolutions"], `${spec.family} has no resolution option`);
|
|
6773
|
+
} else if (res === void 0) {
|
|
6774
|
+
add(["resolutions"], `${spec.family} needs its resolution options`);
|
|
6775
|
+
} else {
|
|
6776
|
+
if (!res.options.includes(res.default)) {
|
|
6777
|
+
add(["resolutions", "default"], "default must be an option");
|
|
6778
|
+
}
|
|
6779
|
+
if (new Set(res.options).size !== res.options.length) {
|
|
6780
|
+
add(["resolutions", "options"], "resolution options repeat");
|
|
6781
|
+
}
|
|
6782
|
+
const allowed = rules.resolutions;
|
|
6783
|
+
for (const option of res.options) {
|
|
6784
|
+
const ok = allowed === "integer" ? /^[1-9][0-9]*$/.test(option) : Object.hasOwn(allowed, option);
|
|
6785
|
+
if (!ok)
|
|
6786
|
+
add(["resolutions", "options"], `${spec.family} has no "${option}" resolution`);
|
|
6787
|
+
}
|
|
6788
|
+
}
|
|
6789
|
+
return issues;
|
|
6790
|
+
}
|
|
6636
6791
|
function model3dInputRefusal(spec, wired) {
|
|
6637
6792
|
const top = spec.views === "unordered" && wired.top === true;
|
|
6638
6793
|
const anyView = spec.views !== "none" && (wired.back || wired.left || wired.right || top);
|
|
@@ -7214,156 +7369,6 @@ var LanguageOptionSchema = import_zod3.z.looseObject({
|
|
|
7214
7369
|
code: import_zod3.z.string().min(1),
|
|
7215
7370
|
name: import_zod3.z.string().min(1)
|
|
7216
7371
|
});
|
|
7217
|
-
var MODEL3D_FAMILY_RULES = {
|
|
7218
|
-
trellis: {
|
|
7219
|
-
textPath: false,
|
|
7220
|
-
views: ["none"],
|
|
7221
|
-
multiImage: false,
|
|
7222
|
-
texture: null,
|
|
7223
|
-
pbr: false,
|
|
7224
|
-
seed: true,
|
|
7225
|
-
textureRef: false,
|
|
7226
|
-
resolutions: "integer"
|
|
7227
|
-
},
|
|
7228
|
-
hunyuan: {
|
|
7229
|
-
textPath: true,
|
|
7230
|
-
views: ["none", "named"],
|
|
7231
|
-
multiImage: false,
|
|
7232
|
-
texture: ["none", "standard"],
|
|
7233
|
-
pbr: true,
|
|
7234
|
-
seed: false,
|
|
7235
|
-
textureRef: false,
|
|
7236
|
-
resolutions: null
|
|
7237
|
-
},
|
|
7238
|
-
tripo: {
|
|
7239
|
-
textPath: true,
|
|
7240
|
-
views: ["none", "ordered"],
|
|
7241
|
-
multiImage: true,
|
|
7242
|
-
texture: ["none", "standard", "detailed"],
|
|
7243
|
-
pbr: true,
|
|
7244
|
-
seed: true,
|
|
7245
|
-
textureRef: false,
|
|
7246
|
-
resolutions: null
|
|
7247
|
-
},
|
|
7248
|
-
rodin: {
|
|
7249
|
-
textPath: true,
|
|
7250
|
-
views: ["none", "unordered"],
|
|
7251
|
-
multiImage: false,
|
|
7252
|
-
texture: null,
|
|
7253
|
-
pbr: false,
|
|
7254
|
-
seed: true,
|
|
7255
|
-
textureRef: false,
|
|
7256
|
-
resolutions: null
|
|
7257
|
-
},
|
|
7258
|
-
meshy: {
|
|
7259
|
-
textPath: true,
|
|
7260
|
-
views: ["none", "unordered"],
|
|
7261
|
-
multiImage: true,
|
|
7262
|
-
texture: ["none", "standard"],
|
|
7263
|
-
pbr: true,
|
|
7264
|
-
seed: true,
|
|
7265
|
-
textureRef: true,
|
|
7266
|
-
resolutions: null
|
|
7267
|
-
},
|
|
7268
|
-
hi3d: {
|
|
7269
|
-
textPath: false,
|
|
7270
|
-
views: ["none", "named"],
|
|
7271
|
-
multiImage: true,
|
|
7272
|
-
texture: ["none", "standard"],
|
|
7273
|
-
pbr: true,
|
|
7274
|
-
seed: false,
|
|
7275
|
-
textureRef: false,
|
|
7276
|
-
resolutions: ["quality", "master"]
|
|
7277
|
-
},
|
|
7278
|
-
sam: {
|
|
7279
|
-
textPath: false,
|
|
7280
|
-
views: ["none"],
|
|
7281
|
-
multiImage: false,
|
|
7282
|
-
texture: null,
|
|
7283
|
-
pbr: false,
|
|
7284
|
-
seed: true,
|
|
7285
|
-
textureRef: false,
|
|
7286
|
-
resolutions: null
|
|
7287
|
-
}
|
|
7288
|
-
};
|
|
7289
|
-
function model3dSpecIssues(spec) {
|
|
7290
|
-
const issues = [];
|
|
7291
|
-
const add = (path, message) => issues.push({ path, message });
|
|
7292
|
-
const rules = MODEL3D_FAMILY_RULES[spec.family];
|
|
7293
|
-
const promptOnly = spec.text && !spec.imageRequired;
|
|
7294
|
-
if (spec.endpoints.image === void 0)
|
|
7295
|
-
add(["endpoints", "image"], "every row needs an image endpoint");
|
|
7296
|
-
if (promptOnly && !rules.textPath) {
|
|
7297
|
-
add(
|
|
7298
|
-
["imageRequired"],
|
|
7299
|
-
`${spec.family} has no text-to-3D endpoint; a text row needs an image`
|
|
7300
|
-
);
|
|
7301
|
-
}
|
|
7302
|
-
if (promptOnly && spec.endpoints.text === void 0) {
|
|
7303
|
-
add(["endpoints", "text"], "a text row needs a text endpoint");
|
|
7304
|
-
}
|
|
7305
|
-
if (!rules.views.includes(spec.views)) {
|
|
7306
|
-
add(["views"], `${spec.family} takes views ${rules.views.join(" or ")}`);
|
|
7307
|
-
}
|
|
7308
|
-
if (spec.views === "none" && spec.maxImages !== 1) {
|
|
7309
|
-
add(["maxImages"], "a row without views takes 1 image");
|
|
7310
|
-
}
|
|
7311
|
-
if (spec.views === "unordered" && spec.maxImages < 2) {
|
|
7312
|
-
add(["maxImages"], "a row with views takes at least 2 images");
|
|
7313
|
-
}
|
|
7314
|
-
const slots = MODEL3D_IMAGE_SLOTS[spec.views].length;
|
|
7315
|
-
if (spec.views !== "none" && spec.maxImages > slots) {
|
|
7316
|
-
add(["maxImages"], `a row with ${spec.views} views sends at most ${slots} images`);
|
|
7317
|
-
}
|
|
7318
|
-
if ((spec.views === "named" || spec.views === "ordered") && spec.maxImages < slots) {
|
|
7319
|
-
add(
|
|
7320
|
-
["maxImages"],
|
|
7321
|
-
`a row with ${spec.views} views takes ${slots} images (front and three sides)`
|
|
7322
|
-
);
|
|
7323
|
-
}
|
|
7324
|
-
if (spec.views !== "none" && rules.multiImage && spec.endpoints.multiImage === void 0) {
|
|
7325
|
-
add(["endpoints", "multiImage"], `${spec.family} sends views to a multi-image endpoint`);
|
|
7326
|
-
}
|
|
7327
|
-
if (rules.texture === null) {
|
|
7328
|
-
if (spec.texture.length > 0) add(["texture"], `${spec.family} has no texture switch`);
|
|
7329
|
-
} else {
|
|
7330
|
-
const allowed = rules.texture;
|
|
7331
|
-
if (spec.texture.length === 0) add(["texture"], `${spec.family} needs its texture options`);
|
|
7332
|
-
if (new Set(spec.texture).size !== spec.texture.length)
|
|
7333
|
-
add(["texture"], "texture options repeat");
|
|
7334
|
-
for (const t of spec.texture) {
|
|
7335
|
-
if (!allowed.includes(t)) add(["texture"], `${spec.family} has no "${t}" texture`);
|
|
7336
|
-
}
|
|
7337
|
-
}
|
|
7338
|
-
if (spec.pbr && !rules.pbr) add(["pbr"], `${spec.family} has no PBR switch`);
|
|
7339
|
-
if (spec.pbr && !spec.texture.some((t) => t !== "none")) {
|
|
7340
|
-
add(["pbr"], "PBR needs a textured option");
|
|
7341
|
-
}
|
|
7342
|
-
if (spec.seed && !rules.seed) add(["seed"], `${spec.family} takes no seed`);
|
|
7343
|
-
if (spec.seedMax !== void 0 && !spec.seed) add(["seedMax"], "seedMax needs seed");
|
|
7344
|
-
if (spec.textureRef && !rules.textureRef)
|
|
7345
|
-
add(["textureRef"], `${spec.family} takes no texture reference`);
|
|
7346
|
-
const res = spec.resolutions;
|
|
7347
|
-
if (rules.resolutions === null) {
|
|
7348
|
-
if (res !== void 0) add(["resolutions"], `${spec.family} has no resolution option`);
|
|
7349
|
-
} else if (res === void 0) {
|
|
7350
|
-
add(["resolutions"], `${spec.family} needs its resolution options`);
|
|
7351
|
-
} else {
|
|
7352
|
-
if (!res.options.includes(res.default)) {
|
|
7353
|
-
add(["resolutions", "default"], "default must be an option");
|
|
7354
|
-
}
|
|
7355
|
-
if (new Set(res.options).size !== res.options.length) {
|
|
7356
|
-
add(["resolutions", "options"], "resolution options repeat");
|
|
7357
|
-
}
|
|
7358
|
-
const allowed = rules.resolutions;
|
|
7359
|
-
for (const option of res.options) {
|
|
7360
|
-
const ok = allowed === "integer" ? /^[1-9][0-9]*$/.test(option) : allowed.includes(option);
|
|
7361
|
-
if (!ok)
|
|
7362
|
-
add(["resolutions", "options"], `${spec.family} has no "${option}" resolution`);
|
|
7363
|
-
}
|
|
7364
|
-
}
|
|
7365
|
-
return issues;
|
|
7366
|
-
}
|
|
7367
7372
|
var VideoToolConstraintsSchema = import_zod3.z.looseObject({
|
|
7368
7373
|
kind: import_zod3.z.enum(["upscale", "interpolate", "hdr", "bg-remove", "subtitles"]),
|
|
7369
7374
|
upscaleFactor: RangeSchema.optional(),
|