@shop-os/modelkit 0.5.0 → 0.6.1
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 +19 -0
- package/README.md +26 -1
- package/dist/catalog.cjs +607 -83
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +224 -3
- package/dist/catalog.d.ts +224 -3
- package/dist/catalog.js +607 -83
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +1349 -473
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +254 -3
- package/dist/index.d.ts +254 -3
- package/dist/index.js +1339 -473
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/catalog.cjs
CHANGED
|
@@ -30,6 +30,8 @@ __export(catalog_entry_exports, {
|
|
|
30
30
|
IMAGE_MODELS: () => IMAGE_MODELS,
|
|
31
31
|
MEDIA_METHODS: () => MEDIA_METHODS,
|
|
32
32
|
MEDIA_NODE_MODELS: () => MEDIA_NODE_MODELS,
|
|
33
|
+
MODEL3D_IMAGE_SLOTS: () => MODEL3D_IMAGE_SLOTS,
|
|
34
|
+
MODEL3D_MODELS: () => MODEL3D_MODELS,
|
|
33
35
|
MODELS: () => MODELS,
|
|
34
36
|
ModelKitError: () => ModelKitError,
|
|
35
37
|
OTHER_MODELS: () => OTHER_MODELS,
|
|
@@ -47,6 +49,13 @@ __export(catalog_entry_exports, {
|
|
|
47
49
|
isModelKitError: () => isModelKitError,
|
|
48
50
|
liveCatalog: () => liveCatalog,
|
|
49
51
|
liveState: () => liveState,
|
|
52
|
+
model3dConstraints: () => model3dConstraints,
|
|
53
|
+
model3dInputRefusal: () => model3dInputRefusal,
|
|
54
|
+
model3dPricingSku: () => model3dPricingSku,
|
|
55
|
+
model3dResolution: () => model3dResolution,
|
|
56
|
+
model3dSeedFits: () => model3dSeedFits,
|
|
57
|
+
model3dSkus: () => model3dSkus,
|
|
58
|
+
model3dTexture: () => model3dTexture,
|
|
50
59
|
nearestAspectRatio: () => nearestAspectRatio,
|
|
51
60
|
normalizeExposure: () => normalizeExposure,
|
|
52
61
|
outputAudio: () => outputAudio,
|
|
@@ -208,11 +217,11 @@ function normalizeExposure(value) {
|
|
|
208
217
|
}
|
|
209
218
|
return value;
|
|
210
219
|
}
|
|
211
|
-
function isListedOn(
|
|
212
|
-
return
|
|
220
|
+
function isListedOn(row2, surface) {
|
|
221
|
+
return row2.lifecycle === "active" && row2.exposure.includes(surface);
|
|
213
222
|
}
|
|
214
|
-
function isListed(
|
|
215
|
-
return
|
|
223
|
+
function isListed(row2) {
|
|
224
|
+
return row2.lifecycle === "active" && row2.exposure.length > 0;
|
|
216
225
|
}
|
|
217
226
|
|
|
218
227
|
// src/catalog/image-fal.ts
|
|
@@ -3614,6 +3623,197 @@ var MEDIA_NODE_MODELS = [
|
|
|
3614
3623
|
SAM_3_IMAGE
|
|
3615
3624
|
];
|
|
3616
3625
|
|
|
3626
|
+
// src/catalog/model3d.ts
|
|
3627
|
+
var REQUEST_USAGE = { unit: "requests" };
|
|
3628
|
+
function row(id, label, spec, display) {
|
|
3629
|
+
return {
|
|
3630
|
+
id,
|
|
3631
|
+
aliases: [],
|
|
3632
|
+
label,
|
|
3633
|
+
type: "model3d",
|
|
3634
|
+
adapter: "fal",
|
|
3635
|
+
// The single-image endpoint; the adapter picks the endpoint a request needs.
|
|
3636
|
+
providerModelId: spec.endpoints.image ?? id,
|
|
3637
|
+
lifecycle: "active",
|
|
3638
|
+
exposure: ["space_builder"],
|
|
3639
|
+
constraints: { supports: [], model3d: spec },
|
|
3640
|
+
defaults: {},
|
|
3641
|
+
usage: REQUEST_USAGE,
|
|
3642
|
+
pricingKind: "flat",
|
|
3643
|
+
display
|
|
3644
|
+
};
|
|
3645
|
+
}
|
|
3646
|
+
var MODEL3D_MODELS = [
|
|
3647
|
+
row(
|
|
3648
|
+
"trellis-2",
|
|
3649
|
+
"Trellis 2",
|
|
3650
|
+
{
|
|
3651
|
+
family: "trellis",
|
|
3652
|
+
endpoints: { image: "fal-ai/trellis-2" },
|
|
3653
|
+
text: false,
|
|
3654
|
+
imageRequired: true,
|
|
3655
|
+
views: "none",
|
|
3656
|
+
maxImages: 1,
|
|
3657
|
+
texture: [],
|
|
3658
|
+
pbr: false,
|
|
3659
|
+
textureRef: false,
|
|
3660
|
+
seed: true,
|
|
3661
|
+
resolutions: { label: "Resolution", options: ["512", "1024", "1536"], default: "1024" }
|
|
3662
|
+
},
|
|
3663
|
+
{
|
|
3664
|
+
provider: "microsoft",
|
|
3665
|
+
description: "One photo to a detailed textured model. Fast and the best value.",
|
|
3666
|
+
sortOrder: 70
|
|
3667
|
+
}
|
|
3668
|
+
),
|
|
3669
|
+
row(
|
|
3670
|
+
"hunyuan3d-3.1-pro",
|
|
3671
|
+
"Hunyuan3D 3.1 Pro",
|
|
3672
|
+
{
|
|
3673
|
+
family: "hunyuan",
|
|
3674
|
+
endpoints: {
|
|
3675
|
+
text: "fal-ai/hunyuan-3d/v3.1/pro/text-to-3d",
|
|
3676
|
+
image: "fal-ai/hunyuan-3d/v3.1/pro/image-to-3d"
|
|
3677
|
+
},
|
|
3678
|
+
text: true,
|
|
3679
|
+
imageRequired: false,
|
|
3680
|
+
views: "named",
|
|
3681
|
+
maxImages: 4,
|
|
3682
|
+
texture: ["none", "standard"],
|
|
3683
|
+
pbr: true,
|
|
3684
|
+
textureRef: false,
|
|
3685
|
+
seed: false
|
|
3686
|
+
},
|
|
3687
|
+
{
|
|
3688
|
+
provider: "tencent",
|
|
3689
|
+
description: "Photo-faithful models from a prompt, a photo, or a photo with back and side views.",
|
|
3690
|
+
sortOrder: 60
|
|
3691
|
+
}
|
|
3692
|
+
),
|
|
3693
|
+
row(
|
|
3694
|
+
"tripo-h3.1",
|
|
3695
|
+
"Tripo H3.1",
|
|
3696
|
+
{
|
|
3697
|
+
family: "tripo",
|
|
3698
|
+
endpoints: {
|
|
3699
|
+
text: "tripo3d/h3.1/text-to-3d",
|
|
3700
|
+
image: "tripo3d/h3.1/image-to-3d",
|
|
3701
|
+
multiImage: "tripo3d/h3.1/multiview-to-3d"
|
|
3702
|
+
},
|
|
3703
|
+
text: true,
|
|
3704
|
+
imageRequired: false,
|
|
3705
|
+
views: "ordered",
|
|
3706
|
+
maxImages: 4,
|
|
3707
|
+
texture: ["none", "standard", "detailed"],
|
|
3708
|
+
pbr: true,
|
|
3709
|
+
textureRef: false,
|
|
3710
|
+
seed: true
|
|
3711
|
+
},
|
|
3712
|
+
{
|
|
3713
|
+
provider: "tripo",
|
|
3714
|
+
description: "Clean, game-ready models from a prompt, a photo or four views.",
|
|
3715
|
+
sortOrder: 50
|
|
3716
|
+
}
|
|
3717
|
+
),
|
|
3718
|
+
row(
|
|
3719
|
+
"rodin-gen-2.5",
|
|
3720
|
+
"Rodin Gen-2.5",
|
|
3721
|
+
{
|
|
3722
|
+
family: "rodin",
|
|
3723
|
+
endpoints: {
|
|
3724
|
+
text: "fal-ai/hyper3d/rodin/v2.5/text-to-3d",
|
|
3725
|
+
image: "fal-ai/hyper3d/rodin/v2.5"
|
|
3726
|
+
},
|
|
3727
|
+
text: true,
|
|
3728
|
+
imageRequired: false,
|
|
3729
|
+
views: "unordered",
|
|
3730
|
+
maxImages: 5,
|
|
3731
|
+
texture: [],
|
|
3732
|
+
pbr: false,
|
|
3733
|
+
textureRef: false,
|
|
3734
|
+
seed: true,
|
|
3735
|
+
seedMax: 65535
|
|
3736
|
+
},
|
|
3737
|
+
{
|
|
3738
|
+
provider: "hyper3d",
|
|
3739
|
+
description: "Detailed PBR models from a prompt or up to five photos.",
|
|
3740
|
+
sortOrder: 40
|
|
3741
|
+
}
|
|
3742
|
+
),
|
|
3743
|
+
row(
|
|
3744
|
+
"meshy-7.1",
|
|
3745
|
+
"Meshy 7.1",
|
|
3746
|
+
{
|
|
3747
|
+
family: "meshy",
|
|
3748
|
+
endpoints: {
|
|
3749
|
+
text: "meshy/v7.1/text-to-3d",
|
|
3750
|
+
image: "meshy/v7.1/image-to-3d",
|
|
3751
|
+
multiImage: "meshy/v7.1/multi-image-to-3d"
|
|
3752
|
+
},
|
|
3753
|
+
text: true,
|
|
3754
|
+
imageRequired: false,
|
|
3755
|
+
views: "unordered",
|
|
3756
|
+
maxImages: 4,
|
|
3757
|
+
texture: ["none", "standard"],
|
|
3758
|
+
pbr: true,
|
|
3759
|
+
textureRef: true,
|
|
3760
|
+
seed: true
|
|
3761
|
+
},
|
|
3762
|
+
{
|
|
3763
|
+
provider: "meshy",
|
|
3764
|
+
description: "Models from a prompt or photos, with a texture prompt or texture image to restyle.",
|
|
3765
|
+
sortOrder: 30
|
|
3766
|
+
}
|
|
3767
|
+
),
|
|
3768
|
+
row(
|
|
3769
|
+
"hi3d-3.0",
|
|
3770
|
+
"Hi3D 3.0",
|
|
3771
|
+
{
|
|
3772
|
+
family: "hi3d",
|
|
3773
|
+
endpoints: {
|
|
3774
|
+
image: "hitem3d/hi3d/v3.0/image-to-3d",
|
|
3775
|
+
multiImage: "hitem3d/hi3d/v3.0/multi-view-to-3d"
|
|
3776
|
+
},
|
|
3777
|
+
text: false,
|
|
3778
|
+
imageRequired: true,
|
|
3779
|
+
views: "named",
|
|
3780
|
+
maxImages: 4,
|
|
3781
|
+
texture: ["none", "standard"],
|
|
3782
|
+
pbr: true,
|
|
3783
|
+
textureRef: false,
|
|
3784
|
+
seed: false,
|
|
3785
|
+
resolutions: { label: "Quality", options: ["quality", "master"], default: "quality" }
|
|
3786
|
+
},
|
|
3787
|
+
{
|
|
3788
|
+
provider: "hitem3d",
|
|
3789
|
+
description: "Highest-fidelity product models from a photo or four views. Slowest.",
|
|
3790
|
+
sortOrder: 20
|
|
3791
|
+
}
|
|
3792
|
+
),
|
|
3793
|
+
row(
|
|
3794
|
+
"sam-3d-objects",
|
|
3795
|
+
"SAM 3D Objects",
|
|
3796
|
+
{
|
|
3797
|
+
family: "sam",
|
|
3798
|
+
endpoints: { image: "fal-ai/sam-3/3d-objects" },
|
|
3799
|
+
text: true,
|
|
3800
|
+
imageRequired: true,
|
|
3801
|
+
promptRequired: true,
|
|
3802
|
+
views: "none",
|
|
3803
|
+
maxImages: 1,
|
|
3804
|
+
texture: [],
|
|
3805
|
+
pbr: false,
|
|
3806
|
+
textureRef: false,
|
|
3807
|
+
seed: true
|
|
3808
|
+
},
|
|
3809
|
+
{
|
|
3810
|
+
provider: "meta",
|
|
3811
|
+
description: "Lifts one named object out of a real photo into a 3D model.",
|
|
3812
|
+
sortOrder: 10
|
|
3813
|
+
}
|
|
3814
|
+
)
|
|
3815
|
+
];
|
|
3816
|
+
|
|
3617
3817
|
// src/catalog/other.ts
|
|
3618
3818
|
var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
|
|
3619
3819
|
var ELEVENLABS_LOGO2 = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/elevenlabs.png";
|
|
@@ -5932,6 +6132,7 @@ var MODELS = [
|
|
|
5932
6132
|
...IMAGE_MODELS,
|
|
5933
6133
|
...VIDEO_MODELS,
|
|
5934
6134
|
...VIDEO_TOOL_MODELS,
|
|
6135
|
+
...MODEL3D_MODELS,
|
|
5935
6136
|
...OTHER_MODELS,
|
|
5936
6137
|
...MEDIA_NODE_MODELS
|
|
5937
6138
|
];
|
|
@@ -5940,11 +6141,11 @@ var MODELS = [
|
|
|
5940
6141
|
var import_zod3 = require("zod");
|
|
5941
6142
|
|
|
5942
6143
|
// src/resolve-provider-rules.ts
|
|
5943
|
-
function ruleRefusal(
|
|
6144
|
+
function ruleRefusal(row2, message, code) {
|
|
5944
6145
|
return new ModelKitError({
|
|
5945
6146
|
code,
|
|
5946
|
-
message: `${
|
|
5947
|
-
model:
|
|
6147
|
+
message: `${row2.label}: ${message}`,
|
|
6148
|
+
model: row2.id,
|
|
5948
6149
|
retryable: false
|
|
5949
6150
|
});
|
|
5950
6151
|
}
|
|
@@ -6103,27 +6304,27 @@ function collisionIssues(rows) {
|
|
|
6103
6304
|
const issues = [];
|
|
6104
6305
|
const seenIds = /* @__PURE__ */ new Map();
|
|
6105
6306
|
const seenAliases = /* @__PURE__ */ new Map();
|
|
6106
|
-
rows.forEach((
|
|
6107
|
-
if (seenIds.has(
|
|
6307
|
+
rows.forEach((row2, index) => {
|
|
6308
|
+
if (seenIds.has(row2.id)) {
|
|
6108
6309
|
issues.push({
|
|
6109
6310
|
index,
|
|
6110
6311
|
path: ["id"],
|
|
6111
|
-
message: `Duplicate model id "${
|
|
6312
|
+
message: `Duplicate model id "${row2.id}"`
|
|
6112
6313
|
});
|
|
6113
6314
|
} else {
|
|
6114
|
-
const aliasOwner = seenAliases.get(
|
|
6315
|
+
const aliasOwner = seenAliases.get(row2.id);
|
|
6115
6316
|
if (aliasOwner !== void 0) {
|
|
6116
6317
|
issues.push({
|
|
6117
6318
|
index: aliasOwner.index,
|
|
6118
6319
|
path: ["aliases", aliasOwner.aliasIndex],
|
|
6119
|
-
message: `Alias "${
|
|
6320
|
+
message: `Alias "${row2.id}" collides with a model id`
|
|
6120
6321
|
});
|
|
6121
6322
|
}
|
|
6122
|
-
seenIds.set(
|
|
6323
|
+
seenIds.set(row2.id, index);
|
|
6123
6324
|
}
|
|
6124
6325
|
const local = /* @__PURE__ */ new Set();
|
|
6125
|
-
for (const [aliasIndex, alias] of
|
|
6126
|
-
if (alias ===
|
|
6326
|
+
for (const [aliasIndex, alias] of row2.aliases.entries()) {
|
|
6327
|
+
if (alias === row2.id || seenIds.has(alias)) {
|
|
6127
6328
|
issues.push({
|
|
6128
6329
|
index,
|
|
6129
6330
|
path: ["aliases", aliasIndex],
|
|
@@ -6162,23 +6363,23 @@ var ConstraintsReadView = import_zod.z.looseObject({
|
|
|
6162
6363
|
}).optional().catch(void 0)
|
|
6163
6364
|
});
|
|
6164
6365
|
var DEFAULT_CONVENTIONS = { referenceSyntax: "numbered" };
|
|
6165
|
-
function outputAudio(
|
|
6166
|
-
const view = ConstraintsReadView.safeParse(
|
|
6366
|
+
function outputAudio(row2) {
|
|
6367
|
+
const view = ConstraintsReadView.safeParse(row2.constraints);
|
|
6167
6368
|
return view.success ? view.data.audio : void 0;
|
|
6168
6369
|
}
|
|
6169
6370
|
var DefaultsReadView = import_zod.z.looseObject({
|
|
6170
6371
|
generateAudio: import_zod.z.boolean().optional().catch(void 0)
|
|
6171
6372
|
});
|
|
6172
|
-
function billedAudio(
|
|
6173
|
-
const audio = outputAudio(
|
|
6373
|
+
function billedAudio(row2, requested) {
|
|
6374
|
+
const audio = outputAudio(row2);
|
|
6174
6375
|
if (audio === "never") return false;
|
|
6175
6376
|
if (audio !== "optional") return true;
|
|
6176
6377
|
if (requested !== void 0) return requested;
|
|
6177
|
-
const defaults = DefaultsReadView.safeParse(
|
|
6378
|
+
const defaults = DefaultsReadView.safeParse(row2.defaults);
|
|
6178
6379
|
return (defaults.success ? defaults.data.generateAudio : void 0) ?? true;
|
|
6179
6380
|
}
|
|
6180
|
-
function promptConventions(
|
|
6181
|
-
const view = ConstraintsReadView.safeParse(
|
|
6381
|
+
function promptConventions(row2) {
|
|
6382
|
+
const view = ConstraintsReadView.safeParse(row2.constraints);
|
|
6182
6383
|
const prompt = view.success ? view.data.prompt : void 0;
|
|
6183
6384
|
if (prompt === void 0) return { ...DEFAULT_CONVENTIONS };
|
|
6184
6385
|
const result = { referenceSyntax: prompt.referenceSyntax };
|
|
@@ -6189,22 +6390,111 @@ var RawConventionsView = import_zod.z.looseObject({
|
|
|
6189
6390
|
audio: import_zod.z.unknown().optional(),
|
|
6190
6391
|
prompt: import_zod.z.unknown().optional()
|
|
6191
6392
|
});
|
|
6192
|
-
function normaliseConventions(
|
|
6193
|
-
const view = RawConventionsView.safeParse(
|
|
6194
|
-
if (!view.success) return { row, invalidKeys: [] };
|
|
6393
|
+
function normaliseConventions(row2) {
|
|
6394
|
+
const view = RawConventionsView.safeParse(row2.constraints);
|
|
6395
|
+
if (!view.success) return { row: row2, invalidKeys: [] };
|
|
6195
6396
|
const { audio, prompt } = view.data;
|
|
6196
6397
|
const badAudio = audio !== void 0 && !AudioOutputSchema.safeParse(audio).success;
|
|
6197
6398
|
const badPrompt = prompt !== void 0 && !PromptConventionsSchema.safeParse(prompt).success;
|
|
6198
|
-
if (!badAudio && !badPrompt) return { row, invalidKeys: [] };
|
|
6399
|
+
if (!badAudio && !badPrompt) return { row: row2, invalidKeys: [] };
|
|
6199
6400
|
const invalidKeys = [];
|
|
6200
6401
|
if (badAudio) invalidKeys.push("constraints.audio");
|
|
6201
6402
|
if (badPrompt) invalidKeys.push("constraints.prompt");
|
|
6202
|
-
const entries = Object.entries(
|
|
6403
|
+
const entries = Object.entries(row2.constraints).flatMap(([key, value]) => {
|
|
6203
6404
|
if (key === "audio" && badAudio) return [];
|
|
6204
|
-
if (key === "prompt" && badPrompt) return [[key, promptConventions(
|
|
6405
|
+
if (key === "prompt" && badPrompt) return [[key, promptConventions(row2)]];
|
|
6205
6406
|
return [[key, value]];
|
|
6206
6407
|
});
|
|
6207
|
-
return { row: { ...
|
|
6408
|
+
return { row: { ...row2, constraints: Object.fromEntries(entries) }, invalidKeys };
|
|
6409
|
+
}
|
|
6410
|
+
|
|
6411
|
+
// src/catalog/model3d-spec.ts
|
|
6412
|
+
function model3dConstraints(row2) {
|
|
6413
|
+
if (row2.type !== "model3d") return void 0;
|
|
6414
|
+
return row2.constraints.model3d;
|
|
6415
|
+
}
|
|
6416
|
+
var MODEL3D_IMAGE_SLOTS = {
|
|
6417
|
+
none: ["image"],
|
|
6418
|
+
named: ["image", "back", "left", "right"],
|
|
6419
|
+
ordered: ["image", "left", "back", "right"],
|
|
6420
|
+
unordered: ["image", "back", "left", "right", "top"]
|
|
6421
|
+
};
|
|
6422
|
+
function model3dInputRefusal(spec, wired) {
|
|
6423
|
+
const top = spec.views === "unordered" && wired.top === true;
|
|
6424
|
+
const anyView = spec.views !== "none" && (wired.back || wired.left || wired.right || top);
|
|
6425
|
+
if (anyView && !wired.image) return "model3d_views_need_image";
|
|
6426
|
+
if (spec.imageRequired && !wired.image) return "model3d_needs_image";
|
|
6427
|
+
if (spec.promptRequired && !wired.prompt) return "model3d_needs_prompt";
|
|
6428
|
+
if (!wired.image && !(spec.text && wired.prompt)) return "model3d_needs_input";
|
|
6429
|
+
if (spec.views === "ordered") {
|
|
6430
|
+
if ((wired.back || wired.right) && !wired.left) return "model3d_views_out_of_order";
|
|
6431
|
+
if (wired.right && !wired.back) return "model3d_views_out_of_order";
|
|
6432
|
+
}
|
|
6433
|
+
return null;
|
|
6434
|
+
}
|
|
6435
|
+
function model3dSeedFits(spec, seed) {
|
|
6436
|
+
return Number.isSafeInteger(seed) && seed >= 0 && seed <= (spec.seedMax ?? Number.MAX_SAFE_INTEGER);
|
|
6437
|
+
}
|
|
6438
|
+
function model3dTexture(spec, requested) {
|
|
6439
|
+
if (requested !== void 0 && spec.texture.includes(requested)) return requested;
|
|
6440
|
+
return spec.texture.includes("standard") ? "standard" : spec.texture[0] ?? "standard";
|
|
6441
|
+
}
|
|
6442
|
+
function model3dResolution(spec, requested) {
|
|
6443
|
+
const res = spec.resolutions;
|
|
6444
|
+
if (res === void 0) return void 0;
|
|
6445
|
+
return requested !== void 0 && res.options.includes(requested) ? requested : res.default;
|
|
6446
|
+
}
|
|
6447
|
+
function model3dPricingSku(row2, options, inputs) {
|
|
6448
|
+
const spec = model3dConstraints(row2);
|
|
6449
|
+
if (spec === void 0) throw new Error(`${row2.id} is not a 3D model`);
|
|
6450
|
+
const texture = model3dTexture(spec, options.texture);
|
|
6451
|
+
const textured = spec.texture.length > 0 && texture !== "none";
|
|
6452
|
+
const pbr = spec.pbr && textured && options.pbr === true;
|
|
6453
|
+
const resolution = model3dResolution(spec, options.resolution);
|
|
6454
|
+
switch (spec.family) {
|
|
6455
|
+
case "meshy":
|
|
6456
|
+
return `${row2.id}__${textured ? "textured" : "untextured"}`;
|
|
6457
|
+
case "tripo":
|
|
6458
|
+
return `${row2.id}__${inputs.image ? "image" : "text"}__${texture}`;
|
|
6459
|
+
case "hunyuan":
|
|
6460
|
+
return `${row2.id}${pbr ? "__pbr" : ""}${inputs.views ? "__views" : ""}`;
|
|
6461
|
+
case "trellis":
|
|
6462
|
+
return `${row2.id}__${resolution}`;
|
|
6463
|
+
case "hi3d":
|
|
6464
|
+
return `${row2.id}__${resolution}__${textured ? pbr ? "texture-pbr" : "texture" : "geometry"}`;
|
|
6465
|
+
case "rodin":
|
|
6466
|
+
case "sam":
|
|
6467
|
+
return row2.id;
|
|
6468
|
+
}
|
|
6469
|
+
}
|
|
6470
|
+
function model3dSkus(row2) {
|
|
6471
|
+
const spec = model3dConstraints(row2);
|
|
6472
|
+
if (spec === void 0) return [];
|
|
6473
|
+
const textures = spec.texture.length > 0 ? spec.texture : [void 0];
|
|
6474
|
+
const pbrs = spec.pbr ? [false, true] : [false];
|
|
6475
|
+
const resolutions = spec.resolutions?.options ?? [void 0];
|
|
6476
|
+
const images = spec.text && !spec.imageRequired ? [true, false] : [true];
|
|
6477
|
+
const views = spec.views === "none" ? [false] : [false, true];
|
|
6478
|
+
const skus = /* @__PURE__ */ new Set();
|
|
6479
|
+
for (const texture of textures)
|
|
6480
|
+
for (const pbr of pbrs)
|
|
6481
|
+
for (const resolution of resolutions)
|
|
6482
|
+
for (const image of images)
|
|
6483
|
+
for (const view of views) {
|
|
6484
|
+
if (view && !image) continue;
|
|
6485
|
+
skus.add(
|
|
6486
|
+
model3dPricingSku(
|
|
6487
|
+
row2,
|
|
6488
|
+
{
|
|
6489
|
+
...texture !== void 0 && { texture },
|
|
6490
|
+
pbr,
|
|
6491
|
+
...resolution !== void 0 && { resolution }
|
|
6492
|
+
},
|
|
6493
|
+
{ image, views: view }
|
|
6494
|
+
)
|
|
6495
|
+
);
|
|
6496
|
+
}
|
|
6497
|
+
return [...skus].sort();
|
|
6208
6498
|
}
|
|
6209
6499
|
|
|
6210
6500
|
// src/catalog/input-spec.ts
|
|
@@ -6349,7 +6639,7 @@ var InputSpecSchema = import_zod2.z.strictObject({
|
|
|
6349
6639
|
}
|
|
6350
6640
|
}
|
|
6351
6641
|
});
|
|
6352
|
-
function validateInputSpec(raw,
|
|
6642
|
+
function validateInputSpec(raw, row2) {
|
|
6353
6643
|
const parsed = InputSpecSchema.safeParse(raw);
|
|
6354
6644
|
if (!parsed.success) {
|
|
6355
6645
|
return {
|
|
@@ -6361,7 +6651,7 @@ function validateInputSpec(raw, row) {
|
|
|
6361
6651
|
};
|
|
6362
6652
|
}
|
|
6363
6653
|
const spec = parsed.data;
|
|
6364
|
-
const supportedTypes = TYPES_BY_ADAPTER.get(
|
|
6654
|
+
const supportedTypes = TYPES_BY_ADAPTER.get(row2.adapter);
|
|
6365
6655
|
if (supportedTypes === void 0) {
|
|
6366
6656
|
return {
|
|
6367
6657
|
ok: false,
|
|
@@ -6374,18 +6664,18 @@ function validateInputSpec(raw, row) {
|
|
|
6374
6664
|
};
|
|
6375
6665
|
}
|
|
6376
6666
|
const issues = [];
|
|
6377
|
-
const allowed = ALLOWED_KEYS_BY_TYPE.get(
|
|
6378
|
-
if (allowed === void 0 || !supportedTypes.includes(
|
|
6667
|
+
const allowed = ALLOWED_KEYS_BY_TYPE.get(row2.type);
|
|
6668
|
+
if (allowed === void 0 || !supportedTypes.includes(row2.type)) {
|
|
6379
6669
|
issues.push({
|
|
6380
6670
|
path: [],
|
|
6381
|
-
message:
|
|
6671
|
+
message: row2.adapter === "fal" ? `inputSpec on fal rows is only supported for image rows, not "${row2.type}"` : `inputSpec is not supported for "${row2.type}" rows`
|
|
6382
6672
|
});
|
|
6383
6673
|
} else {
|
|
6384
6674
|
for (const key of Object.keys(spec.fields)) {
|
|
6385
6675
|
if (!allowed.has(key)) {
|
|
6386
6676
|
issues.push({
|
|
6387
6677
|
path: ["fields", key],
|
|
6388
|
-
message: `inputSpec.fields "${key}" is not supported for ${
|
|
6678
|
+
message: `inputSpec.fields "${key}" is not supported for ${row2.type} rows`
|
|
6389
6679
|
});
|
|
6390
6680
|
}
|
|
6391
6681
|
}
|
|
@@ -6393,13 +6683,13 @@ function validateInputSpec(raw, row) {
|
|
|
6393
6683
|
if (!allowed.has(key)) {
|
|
6394
6684
|
issues.push({
|
|
6395
6685
|
path: ["values", key],
|
|
6396
|
-
message: `inputSpec.values "${key}" is not supported for ${
|
|
6686
|
+
message: `inputSpec.values "${key}" is not supported for ${row2.type} rows`
|
|
6397
6687
|
});
|
|
6398
6688
|
}
|
|
6399
6689
|
}
|
|
6400
6690
|
}
|
|
6401
6691
|
if (spec.editEndpoint !== void 0) {
|
|
6402
|
-
if (
|
|
6692
|
+
if (row2.adapter !== "fal") {
|
|
6403
6693
|
issues.push({
|
|
6404
6694
|
path: ["editEndpoint"],
|
|
6405
6695
|
message: "inputSpec.editEndpoint is only supported on fal rows"
|
|
@@ -6443,7 +6733,7 @@ function validateInputSpec(raw, row) {
|
|
|
6443
6733
|
if (allowed !== void 0 && !allowed.has(key)) {
|
|
6444
6734
|
issues.push({
|
|
6445
6735
|
path: ["arrays", name],
|
|
6446
|
-
message: `inputSpec.arrays "${key}" is not supported for ${
|
|
6736
|
+
message: `inputSpec.arrays "${key}" is not supported for ${row2.type} rows`
|
|
6447
6737
|
});
|
|
6448
6738
|
}
|
|
6449
6739
|
if (key in spec.fields) {
|
|
@@ -6463,7 +6753,7 @@ function validateInputSpec(raw, row) {
|
|
|
6463
6753
|
}
|
|
6464
6754
|
}
|
|
6465
6755
|
if (spec.dimensions !== void 0) {
|
|
6466
|
-
if (
|
|
6756
|
+
if (row2.type !== "image") {
|
|
6467
6757
|
issues.push({
|
|
6468
6758
|
path: ["dimensions"],
|
|
6469
6759
|
message: "inputSpec.dimensions is only supported on image rows"
|
|
@@ -6485,7 +6775,7 @@ function validateInputSpec(raw, row) {
|
|
|
6485
6775
|
});
|
|
6486
6776
|
}
|
|
6487
6777
|
}
|
|
6488
|
-
const supports =
|
|
6778
|
+
const supports = row2.constraints.supports ?? [];
|
|
6489
6779
|
for (const key of INPUT_SPEC_SUPPORTS_KEYS) {
|
|
6490
6780
|
if (supports.includes(key)) continue;
|
|
6491
6781
|
if (key in spec.fields) {
|
|
@@ -6530,8 +6820,8 @@ function listIssues(name, values, fallback, defaultKey) {
|
|
|
6530
6820
|
}
|
|
6531
6821
|
return issues;
|
|
6532
6822
|
}
|
|
6533
|
-
function optionListIssues(
|
|
6534
|
-
const { constraints, defaults } =
|
|
6823
|
+
function optionListIssues(row2) {
|
|
6824
|
+
const { constraints, defaults } = row2;
|
|
6535
6825
|
const issues = [
|
|
6536
6826
|
...listIssues(
|
|
6537
6827
|
"voices",
|
|
@@ -6589,7 +6879,8 @@ var ModelTypeSchema = import_zod3.z.enum([
|
|
|
6589
6879
|
"voice-change",
|
|
6590
6880
|
"dubbing",
|
|
6591
6881
|
"lipsync",
|
|
6592
|
-
"transcription"
|
|
6882
|
+
"transcription",
|
|
6883
|
+
"model3d"
|
|
6593
6884
|
]);
|
|
6594
6885
|
var LifecycleSchema = import_zod3.z.enum(["active", "deprecated", "retired"]);
|
|
6595
6886
|
var SurfaceSchema = import_zod3.z.enum(["cowork", "space_builder"]);
|
|
@@ -6653,7 +6944,8 @@ var UsageUnitSchema = import_zod3.z.enum([
|
|
|
6653
6944
|
"images",
|
|
6654
6945
|
"seconds",
|
|
6655
6946
|
"reported_cost_usd",
|
|
6656
|
-
"compute_seconds"
|
|
6947
|
+
"compute_seconds",
|
|
6948
|
+
"requests"
|
|
6657
6949
|
]);
|
|
6658
6950
|
var PricingKindSchema = import_zod3.z.enum(["token", "image_size", "video_per_second", "flat"]);
|
|
6659
6951
|
var ProviderOptionValueSchema = import_zod3.z.lazy(
|
|
@@ -6707,6 +6999,156 @@ var LanguageOptionSchema = import_zod3.z.looseObject({
|
|
|
6707
6999
|
code: import_zod3.z.string().min(1),
|
|
6708
7000
|
name: import_zod3.z.string().min(1)
|
|
6709
7001
|
});
|
|
7002
|
+
var MODEL3D_FAMILY_RULES = {
|
|
7003
|
+
trellis: {
|
|
7004
|
+
textPath: false,
|
|
7005
|
+
views: ["none"],
|
|
7006
|
+
multiImage: false,
|
|
7007
|
+
texture: null,
|
|
7008
|
+
pbr: false,
|
|
7009
|
+
seed: true,
|
|
7010
|
+
textureRef: false,
|
|
7011
|
+
resolutions: "integer"
|
|
7012
|
+
},
|
|
7013
|
+
hunyuan: {
|
|
7014
|
+
textPath: true,
|
|
7015
|
+
views: ["none", "named"],
|
|
7016
|
+
multiImage: false,
|
|
7017
|
+
texture: ["none", "standard"],
|
|
7018
|
+
pbr: true,
|
|
7019
|
+
seed: false,
|
|
7020
|
+
textureRef: false,
|
|
7021
|
+
resolutions: null
|
|
7022
|
+
},
|
|
7023
|
+
tripo: {
|
|
7024
|
+
textPath: true,
|
|
7025
|
+
views: ["none", "ordered"],
|
|
7026
|
+
multiImage: true,
|
|
7027
|
+
texture: ["none", "standard", "detailed"],
|
|
7028
|
+
pbr: true,
|
|
7029
|
+
seed: true,
|
|
7030
|
+
textureRef: false,
|
|
7031
|
+
resolutions: null
|
|
7032
|
+
},
|
|
7033
|
+
rodin: {
|
|
7034
|
+
textPath: true,
|
|
7035
|
+
views: ["none", "unordered"],
|
|
7036
|
+
multiImage: false,
|
|
7037
|
+
texture: null,
|
|
7038
|
+
pbr: false,
|
|
7039
|
+
seed: true,
|
|
7040
|
+
textureRef: false,
|
|
7041
|
+
resolutions: null
|
|
7042
|
+
},
|
|
7043
|
+
meshy: {
|
|
7044
|
+
textPath: true,
|
|
7045
|
+
views: ["none", "unordered"],
|
|
7046
|
+
multiImage: true,
|
|
7047
|
+
texture: ["none", "standard"],
|
|
7048
|
+
pbr: true,
|
|
7049
|
+
seed: true,
|
|
7050
|
+
textureRef: true,
|
|
7051
|
+
resolutions: null
|
|
7052
|
+
},
|
|
7053
|
+
hi3d: {
|
|
7054
|
+
textPath: false,
|
|
7055
|
+
views: ["none", "named"],
|
|
7056
|
+
multiImage: true,
|
|
7057
|
+
texture: ["none", "standard"],
|
|
7058
|
+
pbr: true,
|
|
7059
|
+
seed: false,
|
|
7060
|
+
textureRef: false,
|
|
7061
|
+
resolutions: ["quality", "master"]
|
|
7062
|
+
},
|
|
7063
|
+
sam: {
|
|
7064
|
+
textPath: false,
|
|
7065
|
+
views: ["none"],
|
|
7066
|
+
multiImage: false,
|
|
7067
|
+
texture: null,
|
|
7068
|
+
pbr: false,
|
|
7069
|
+
seed: true,
|
|
7070
|
+
textureRef: false,
|
|
7071
|
+
resolutions: null
|
|
7072
|
+
}
|
|
7073
|
+
};
|
|
7074
|
+
function model3dSpecIssues(spec) {
|
|
7075
|
+
const issues = [];
|
|
7076
|
+
const add = (path, message) => issues.push({ path, message });
|
|
7077
|
+
const rules = MODEL3D_FAMILY_RULES[spec.family];
|
|
7078
|
+
const promptOnly = spec.text && !spec.imageRequired;
|
|
7079
|
+
if (spec.endpoints.image === void 0)
|
|
7080
|
+
add(["endpoints", "image"], "every row needs an image endpoint");
|
|
7081
|
+
if (promptOnly && !rules.textPath) {
|
|
7082
|
+
add(
|
|
7083
|
+
["imageRequired"],
|
|
7084
|
+
`${spec.family} has no text-to-3D endpoint; a text row needs an image`
|
|
7085
|
+
);
|
|
7086
|
+
}
|
|
7087
|
+
if (promptOnly && spec.endpoints.text === void 0) {
|
|
7088
|
+
add(["endpoints", "text"], "a text row needs a text endpoint");
|
|
7089
|
+
}
|
|
7090
|
+
if (!rules.views.includes(spec.views)) {
|
|
7091
|
+
add(["views"], `${spec.family} takes views ${rules.views.join(" or ")}`);
|
|
7092
|
+
}
|
|
7093
|
+
if (spec.views === "none" && spec.maxImages !== 1) {
|
|
7094
|
+
add(["maxImages"], "a row without views takes 1 image");
|
|
7095
|
+
}
|
|
7096
|
+
if (spec.views === "unordered" && spec.maxImages < 2) {
|
|
7097
|
+
add(["maxImages"], "a row with views takes at least 2 images");
|
|
7098
|
+
}
|
|
7099
|
+
const slots = MODEL3D_IMAGE_SLOTS[spec.views].length;
|
|
7100
|
+
if (spec.views !== "none" && spec.maxImages > slots) {
|
|
7101
|
+
add(["maxImages"], `a row with ${spec.views} views sends at most ${slots} images`);
|
|
7102
|
+
}
|
|
7103
|
+
if ((spec.views === "named" || spec.views === "ordered") && spec.maxImages < slots) {
|
|
7104
|
+
add(
|
|
7105
|
+
["maxImages"],
|
|
7106
|
+
`a row with ${spec.views} views takes ${slots} images (front and three sides)`
|
|
7107
|
+
);
|
|
7108
|
+
}
|
|
7109
|
+
if (spec.views !== "none" && rules.multiImage && spec.endpoints.multiImage === void 0) {
|
|
7110
|
+
add(["endpoints", "multiImage"], `${spec.family} sends views to a multi-image endpoint`);
|
|
7111
|
+
}
|
|
7112
|
+
if (rules.texture === null) {
|
|
7113
|
+
if (spec.texture.length > 0) add(["texture"], `${spec.family} has no texture switch`);
|
|
7114
|
+
} else {
|
|
7115
|
+
const allowed = rules.texture;
|
|
7116
|
+
if (spec.texture.length === 0) add(["texture"], `${spec.family} needs its texture options`);
|
|
7117
|
+
if (new Set(spec.texture).size !== spec.texture.length)
|
|
7118
|
+
add(["texture"], "texture options repeat");
|
|
7119
|
+
for (const t of spec.texture) {
|
|
7120
|
+
if (!allowed.includes(t)) add(["texture"], `${spec.family} has no "${t}" texture`);
|
|
7121
|
+
}
|
|
7122
|
+
}
|
|
7123
|
+
if (spec.pbr && !rules.pbr) add(["pbr"], `${spec.family} has no PBR switch`);
|
|
7124
|
+
if (spec.pbr && !spec.texture.some((t) => t !== "none")) {
|
|
7125
|
+
add(["pbr"], "PBR needs a textured option");
|
|
7126
|
+
}
|
|
7127
|
+
if (spec.seed && !rules.seed) add(["seed"], `${spec.family} takes no seed`);
|
|
7128
|
+
if (spec.seedMax !== void 0 && !spec.seed) add(["seedMax"], "seedMax needs seed");
|
|
7129
|
+
if (spec.textureRef && !rules.textureRef)
|
|
7130
|
+
add(["textureRef"], `${spec.family} takes no texture reference`);
|
|
7131
|
+
const res = spec.resolutions;
|
|
7132
|
+
if (rules.resolutions === null) {
|
|
7133
|
+
if (res !== void 0) add(["resolutions"], `${spec.family} has no resolution option`);
|
|
7134
|
+
} else if (res === void 0) {
|
|
7135
|
+
add(["resolutions"], `${spec.family} needs its resolution options`);
|
|
7136
|
+
} else {
|
|
7137
|
+
if (!res.options.includes(res.default)) {
|
|
7138
|
+
add(["resolutions", "default"], "default must be an option");
|
|
7139
|
+
}
|
|
7140
|
+
if (new Set(res.options).size !== res.options.length) {
|
|
7141
|
+
add(["resolutions", "options"], "resolution options repeat");
|
|
7142
|
+
}
|
|
7143
|
+
const allowed = rules.resolutions;
|
|
7144
|
+
for (const option of res.options) {
|
|
7145
|
+
const ok = allowed === "integer" ? /^[1-9][0-9]*$/.test(option) : allowed.includes(option);
|
|
7146
|
+
if (!ok)
|
|
7147
|
+
add(["resolutions", "options"], `${spec.family} has no "${option}" resolution`);
|
|
7148
|
+
}
|
|
7149
|
+
}
|
|
7150
|
+
return issues;
|
|
7151
|
+
}
|
|
6710
7152
|
var VideoToolConstraintsSchema = import_zod3.z.looseObject({
|
|
6711
7153
|
kind: import_zod3.z.enum(["upscale", "interpolate", "hdr", "bg-remove", "subtitles"]),
|
|
6712
7154
|
upscaleFactor: RangeSchema.optional(),
|
|
@@ -6723,6 +7165,30 @@ var VideoToolConstraintsSchema = import_zod3.z.looseObject({
|
|
|
6723
7165
|
translationLanguages: import_zod3.z.array(import_zod3.z.string().min(1)).min(1).optional(),
|
|
6724
7166
|
maxSecondsAbove1080p: import_zod3.z.number().positive().optional()
|
|
6725
7167
|
});
|
|
7168
|
+
var Model3dTextureSchema = import_zod3.z.enum(["none", "standard", "detailed"]);
|
|
7169
|
+
var Model3dConstraintsSchema = import_zod3.z.looseObject({
|
|
7170
|
+
family: import_zod3.z.enum(["trellis", "hunyuan", "tripo", "rodin", "meshy", "hi3d", "sam"]),
|
|
7171
|
+
endpoints: import_zod3.z.looseObject({
|
|
7172
|
+
text: import_zod3.z.string().min(1).optional(),
|
|
7173
|
+
image: import_zod3.z.string().min(1).optional(),
|
|
7174
|
+
multiImage: import_zod3.z.string().min(1).optional()
|
|
7175
|
+
}),
|
|
7176
|
+
text: import_zod3.z.boolean(),
|
|
7177
|
+
imageRequired: import_zod3.z.boolean(),
|
|
7178
|
+
promptRequired: import_zod3.z.boolean().optional(),
|
|
7179
|
+
views: import_zod3.z.enum(["none", "unordered", "ordered", "named"]),
|
|
7180
|
+
maxImages: import_zod3.z.number().int().positive(),
|
|
7181
|
+
texture: import_zod3.z.array(Model3dTextureSchema),
|
|
7182
|
+
pbr: import_zod3.z.boolean(),
|
|
7183
|
+
textureRef: import_zod3.z.boolean(),
|
|
7184
|
+
seed: import_zod3.z.boolean(),
|
|
7185
|
+
seedMax: import_zod3.z.number().int().positive().optional(),
|
|
7186
|
+
resolutions: import_zod3.z.looseObject({
|
|
7187
|
+
label: import_zod3.z.string().min(1),
|
|
7188
|
+
options: import_zod3.z.array(import_zod3.z.string().min(1)).min(1),
|
|
7189
|
+
default: import_zod3.z.string().min(1)
|
|
7190
|
+
}).optional()
|
|
7191
|
+
});
|
|
6726
7192
|
var ModelConstraintsSchema = import_zod3.z.looseObject({
|
|
6727
7193
|
aspectRatios: import_zod3.z.array(AspectRatioSchema).optional(),
|
|
6728
7194
|
sizes: import_zod3.z.array(ImageSizeSchema).optional(),
|
|
@@ -6750,6 +7216,7 @@ var ModelConstraintsSchema = import_zod3.z.looseObject({
|
|
|
6750
7216
|
returns: import_zod3.z.enum(["new", "joined"]).optional()
|
|
6751
7217
|
}).optional(),
|
|
6752
7218
|
tool: VideoToolConstraintsSchema.optional(),
|
|
7219
|
+
model3d: Model3dConstraintsSchema.optional(),
|
|
6753
7220
|
// Loose on purpose: the read path keeps a row whose value is invalid (the accessors in
|
|
6754
7221
|
// conventions.ts read it as "not set"); CatalogModelSchema below rejects it on write.
|
|
6755
7222
|
audio: import_zod3.z.unknown().optional(),
|
|
@@ -6865,29 +7332,47 @@ var CatalogModelSchemaBase = import_zod3.z.looseObject({
|
|
|
6865
7332
|
pricingKind: PricingKindSchema,
|
|
6866
7333
|
display: CatalogDisplaySchema.optional(),
|
|
6867
7334
|
capabilities: CatalogCapabilitiesSchema.optional()
|
|
6868
|
-
}).superRefine((
|
|
6869
|
-
if (
|
|
7335
|
+
}).superRefine((row2, ctx) => {
|
|
7336
|
+
if (row2.lifecycle === "active" && !row2.display) {
|
|
6870
7337
|
ctx.addIssue({
|
|
6871
7338
|
code: "custom",
|
|
6872
7339
|
path: ["display"],
|
|
6873
7340
|
message: "active rows need display"
|
|
6874
7341
|
});
|
|
6875
7342
|
}
|
|
6876
|
-
if (
|
|
7343
|
+
if (row2.lifecycle === "active" && row2.type === "text" && !row2.capabilities?.contextWindow) {
|
|
6877
7344
|
ctx.addIssue({
|
|
6878
7345
|
code: "custom",
|
|
6879
7346
|
path: ["capabilities", "contextWindow"],
|
|
6880
7347
|
message: "active text rows need contextWindow"
|
|
6881
7348
|
});
|
|
6882
7349
|
}
|
|
6883
|
-
if (
|
|
7350
|
+
if (row2.type === "video-tool" && row2.constraints.tool === void 0) {
|
|
6884
7351
|
ctx.addIssue({
|
|
6885
7352
|
code: "custom",
|
|
6886
7353
|
path: ["constraints", "tool"],
|
|
6887
7354
|
message: "video-tool rows need constraints.tool"
|
|
6888
7355
|
});
|
|
6889
7356
|
}
|
|
6890
|
-
if (
|
|
7357
|
+
if (row2.type === "model3d") {
|
|
7358
|
+
const spec = row2.constraints.model3d;
|
|
7359
|
+
if (spec === void 0) {
|
|
7360
|
+
ctx.addIssue({
|
|
7361
|
+
code: "custom",
|
|
7362
|
+
path: ["constraints", "model3d"],
|
|
7363
|
+
message: "model3d rows need constraints.model3d"
|
|
7364
|
+
});
|
|
7365
|
+
} else {
|
|
7366
|
+
for (const issue of model3dSpecIssues(spec)) {
|
|
7367
|
+
ctx.addIssue({
|
|
7368
|
+
code: "custom",
|
|
7369
|
+
path: ["constraints", "model3d", ...issue.path],
|
|
7370
|
+
message: issue.message
|
|
7371
|
+
});
|
|
7372
|
+
}
|
|
7373
|
+
}
|
|
7374
|
+
}
|
|
7375
|
+
if (row2.replacedBy !== void 0 && row2.replacedBy === row2.id) {
|
|
6891
7376
|
ctx.addIssue({
|
|
6892
7377
|
code: "custom",
|
|
6893
7378
|
path: ["replacedBy"],
|
|
@@ -6896,8 +7381,8 @@ var CatalogModelSchemaBase = import_zod3.z.looseObject({
|
|
|
6896
7381
|
}
|
|
6897
7382
|
});
|
|
6898
7383
|
var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
6899
|
-
(
|
|
6900
|
-
const transport =
|
|
7384
|
+
(row2, ctx) => {
|
|
7385
|
+
const transport = row2.providerOptions?.["modelkit"]?.["transport"];
|
|
6901
7386
|
if (transport !== void 0 && transport !== "direct" && transport !== "bedrock") {
|
|
6902
7387
|
ctx.addIssue({
|
|
6903
7388
|
code: "custom",
|
|
@@ -6905,9 +7390,9 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
|
6905
7390
|
message: 'transport must be "direct" or "bedrock"'
|
|
6906
7391
|
});
|
|
6907
7392
|
}
|
|
6908
|
-
const inputSpecRaw =
|
|
7393
|
+
const inputSpecRaw = row2.providerOptions?.["modelkit"]?.["inputSpec"];
|
|
6909
7394
|
if (inputSpecRaw !== void 0) {
|
|
6910
|
-
const result = validateInputSpec(inputSpecRaw,
|
|
7395
|
+
const result = validateInputSpec(inputSpecRaw, row2);
|
|
6911
7396
|
if (!result.ok) {
|
|
6912
7397
|
for (const issue of result.issues) {
|
|
6913
7398
|
ctx.addIssue({
|
|
@@ -6918,7 +7403,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
|
6918
7403
|
}
|
|
6919
7404
|
}
|
|
6920
7405
|
}
|
|
6921
|
-
const audio =
|
|
7406
|
+
const audio = row2.constraints.audio;
|
|
6922
7407
|
if (audio !== void 0 && !AudioOutputSchema.safeParse(audio).success) {
|
|
6923
7408
|
ctx.addIssue({
|
|
6924
7409
|
code: "custom",
|
|
@@ -6926,7 +7411,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
|
6926
7411
|
message: 'audio must be "always", "optional" or "never"'
|
|
6927
7412
|
});
|
|
6928
7413
|
}
|
|
6929
|
-
const refs =
|
|
7414
|
+
const refs = row2.constraints.references;
|
|
6930
7415
|
for (const kind of ["images", "videos", "audios"]) {
|
|
6931
7416
|
const least = refs?.min?.[kind];
|
|
6932
7417
|
const most = refs?.[kind];
|
|
@@ -6938,10 +7423,10 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
|
6938
7423
|
});
|
|
6939
7424
|
}
|
|
6940
7425
|
}
|
|
6941
|
-
for (const issue of optionListIssues(
|
|
7426
|
+
for (const issue of optionListIssues(row2)) {
|
|
6942
7427
|
ctx.addIssue({ code: "custom", path: issue.path, message: issue.message });
|
|
6943
7428
|
}
|
|
6944
|
-
const prompt =
|
|
7429
|
+
const prompt = row2.constraints.prompt;
|
|
6945
7430
|
if (prompt !== void 0) {
|
|
6946
7431
|
const parsed = PromptConventionsSchema.safeParse(prompt);
|
|
6947
7432
|
if (!parsed.success) {
|
|
@@ -6956,7 +7441,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
|
6956
7441
|
}
|
|
6957
7442
|
}
|
|
6958
7443
|
);
|
|
6959
|
-
var CatalogSchema = import_zod3.z.array(CatalogModelSchemaBase.transform((
|
|
7444
|
+
var CatalogSchema = import_zod3.z.array(CatalogModelSchemaBase.transform((row2) => normaliseConventions(row2).row)).superRefine((rows, ctx) => {
|
|
6960
7445
|
for (const issue of collisionIssues(rows)) {
|
|
6961
7446
|
ctx.addIssue({
|
|
6962
7447
|
code: "custom",
|
|
@@ -7030,22 +7515,22 @@ function quarantine(rawRows, logger) {
|
|
|
7030
7515
|
dropped += 1;
|
|
7031
7516
|
continue;
|
|
7032
7517
|
}
|
|
7033
|
-
const
|
|
7034
|
-
const inputSpecRaw =
|
|
7518
|
+
const row2 = parsed.data;
|
|
7519
|
+
const inputSpecRaw = row2.providerOptions?.["modelkit"]?.["inputSpec"];
|
|
7035
7520
|
if (inputSpecRaw !== void 0) {
|
|
7036
|
-
const result = validateInputSpec(inputSpecRaw,
|
|
7521
|
+
const result = validateInputSpec(inputSpecRaw, row2);
|
|
7037
7522
|
if (!result.ok) {
|
|
7038
7523
|
const first = result.issues[0];
|
|
7039
7524
|
const detail = first ? dropReason(first.path, first.message) : "invalid inputSpec";
|
|
7040
7525
|
logger.warn(
|
|
7041
|
-
`[modelkit] catalog row ${
|
|
7526
|
+
`[modelkit] catalog row ${row2.id} has an invalid providerOptions.modelkit.inputSpec: ${detail}; calls fail until it is fixed`
|
|
7042
7527
|
);
|
|
7043
7528
|
}
|
|
7044
7529
|
}
|
|
7045
|
-
const normalised = normaliseConventions(
|
|
7530
|
+
const normalised = normaliseConventions(row2);
|
|
7046
7531
|
if (normalised.invalidKeys.length > 0) {
|
|
7047
7532
|
logger.warn(
|
|
7048
|
-
`[modelkit] catalog row ${
|
|
7533
|
+
`[modelkit] catalog row ${row2.id} has an invalid ${normalised.invalidKeys.join(", ")}; read as not set`
|
|
7049
7534
|
);
|
|
7050
7535
|
}
|
|
7051
7536
|
valid.push(normalised.row);
|
|
@@ -7059,10 +7544,10 @@ function quarantine(rawRows, logger) {
|
|
|
7059
7544
|
if (!firstByIndex.has(issue.index)) firstByIndex.set(issue.index, issue);
|
|
7060
7545
|
}
|
|
7061
7546
|
for (const [index, issue] of [...firstByIndex.entries()].sort((a, b) => a[0] - b[0])) {
|
|
7062
|
-
const
|
|
7063
|
-
if (!
|
|
7547
|
+
const row2 = kept[index];
|
|
7548
|
+
if (!row2) continue;
|
|
7064
7549
|
logger.warn(
|
|
7065
|
-
`[modelkit] catalog row dropped id=${
|
|
7550
|
+
`[modelkit] catalog row dropped id=${row2.id} reason=${String(issue.path[0] ?? "")} ${issue.message}`
|
|
7066
7551
|
);
|
|
7067
7552
|
}
|
|
7068
7553
|
const dropSet = new Set(firstByIndex.keys());
|
|
@@ -7281,9 +7766,9 @@ var ToolSchema = import_zod6.z.object({
|
|
|
7281
7766
|
translationLanguages: import_zod6.z.array(import_zod6.z.string().min(1)).min(1).optional(),
|
|
7282
7767
|
maxSecondsAbove1080p: import_zod6.z.number().positive().optional()
|
|
7283
7768
|
});
|
|
7284
|
-
function videoToolConstraints(
|
|
7285
|
-
if (
|
|
7286
|
-
const parsed = ToolSchema.safeParse(
|
|
7769
|
+
function videoToolConstraints(row2) {
|
|
7770
|
+
if (row2.type !== "video-tool") return void 0;
|
|
7771
|
+
const parsed = ToolSchema.safeParse(row2.constraints.tool);
|
|
7287
7772
|
if (!parsed.success) return void 0;
|
|
7288
7773
|
const {
|
|
7289
7774
|
kind,
|
|
@@ -7330,16 +7815,16 @@ function resolutionTier(width, height) {
|
|
|
7330
7815
|
function fail(error) {
|
|
7331
7816
|
return { ok: false, error };
|
|
7332
7817
|
}
|
|
7333
|
-
function planVideoTool(
|
|
7334
|
-
const tool = videoToolConstraints(
|
|
7335
|
-
if (!tool) return fail(`${
|
|
7818
|
+
function planVideoTool(row2, req) {
|
|
7819
|
+
const tool = videoToolConstraints(row2);
|
|
7820
|
+
if (!tool) return fail(`${row2.id} is not a video tool`);
|
|
7336
7821
|
const { width, height, durationSeconds, fps } = req.source;
|
|
7337
7822
|
if (!(width > 0 && height > 0 && durationSeconds > 0)) {
|
|
7338
7823
|
return fail("The source video's width, height and duration are required");
|
|
7339
7824
|
}
|
|
7340
|
-
const maxSeconds =
|
|
7825
|
+
const maxSeconds = row2.constraints.sourceVideoSeconds?.max;
|
|
7341
7826
|
if (maxSeconds !== void 0 && overMax(durationSeconds, maxSeconds)) {
|
|
7342
|
-
return fail(`${
|
|
7827
|
+
return fail(`${row2.label} takes source videos up to ${maxSeconds} seconds.`);
|
|
7343
7828
|
}
|
|
7344
7829
|
const base = {
|
|
7345
7830
|
durationSeconds,
|
|
@@ -7350,7 +7835,7 @@ function planVideoTool(row, req) {
|
|
|
7350
7835
|
if (factor === void 0) return fail("An upscale factor is required");
|
|
7351
7836
|
const range2 = tool.upscaleFactor;
|
|
7352
7837
|
if (range2 && (factor < range2.min || factor > range2.max)) {
|
|
7353
|
-
return fail(`${
|
|
7838
|
+
return fail(`${row2.label} upscales by ${range2.min}x to ${range2.max}x.`);
|
|
7354
7839
|
}
|
|
7355
7840
|
const outWidth = Math.round(width * factor);
|
|
7356
7841
|
const outHeight = Math.round(height * factor);
|
|
@@ -7378,7 +7863,7 @@ function planVideoTool(row, req) {
|
|
|
7378
7863
|
}
|
|
7379
7864
|
const range2 = tool.fps;
|
|
7380
7865
|
if (range2 && (target < range2.min || target > range2.max)) {
|
|
7381
|
-
return fail(`${
|
|
7866
|
+
return fail(`${row2.label} outputs ${range2.min} to ${range2.max} fps.`);
|
|
7382
7867
|
}
|
|
7383
7868
|
return {
|
|
7384
7869
|
ok: true,
|
|
@@ -7407,7 +7892,7 @@ function planVideoTool(row, req) {
|
|
|
7407
7892
|
if (tool.kind === "subtitles") {
|
|
7408
7893
|
const resolution = resolutionTier(width, height);
|
|
7409
7894
|
const problem = subtitleProblem(
|
|
7410
|
-
|
|
7895
|
+
row2.label,
|
|
7411
7896
|
tool,
|
|
7412
7897
|
req.subtitles,
|
|
7413
7898
|
resolution,
|
|
@@ -7419,9 +7904,9 @@ function planVideoTool(row, req) {
|
|
|
7419
7904
|
const formats = tool.outputFormats ?? ["h265"];
|
|
7420
7905
|
const format = req.outputFormat ?? formats[0] ?? "h265";
|
|
7421
7906
|
if (!formats.includes(format)) {
|
|
7422
|
-
return fail(`${
|
|
7907
|
+
return fail(`${row2.label} writes ${formats.join(" or ")}.`);
|
|
7423
7908
|
}
|
|
7424
|
-
const timing = renderedTiming(
|
|
7909
|
+
const timing = renderedTiming(row2, tool, durationSeconds, fps);
|
|
7425
7910
|
if (!timing.ok) return fail(timing.error);
|
|
7426
7911
|
const out = shrinkToShortEdge(width, height, tool.maxOutputShortEdge);
|
|
7427
7912
|
return {
|
|
@@ -7437,7 +7922,7 @@ function planVideoTool(row, req) {
|
|
|
7437
7922
|
};
|
|
7438
7923
|
}
|
|
7439
7924
|
var DEFAULT_FPS = 24;
|
|
7440
|
-
function renderedTiming(
|
|
7925
|
+
function renderedTiming(row2, tool, durationSeconds, fps) {
|
|
7441
7926
|
const { maxOutputFps, minOutputFrames, maxOutputFrames } = tool;
|
|
7442
7927
|
if (maxOutputFps === void 0 && minOutputFrames === void 0 && maxOutputFrames === void 0) {
|
|
7443
7928
|
return fps !== void 0 ? { ok: true, fps } : { ok: true };
|
|
@@ -7446,7 +7931,7 @@ function renderedTiming(row, tool, durationSeconds, fps) {
|
|
|
7446
7931
|
const frames = Math.max(minOutputFrames ?? 1, Math.round(durationSeconds * rate));
|
|
7447
7932
|
if (maxOutputFrames !== void 0 && frames > maxOutputFrames) {
|
|
7448
7933
|
const limit = `${maxOutputFrames} frames (${seconds(maxOutputFrames, rate)})`;
|
|
7449
|
-
return { ok: false, error: `${
|
|
7934
|
+
return { ok: false, error: `${row2.label} renders up to ${limit}.` };
|
|
7450
7935
|
}
|
|
7451
7936
|
return { ok: true, fps: rate, frames, durationSeconds: frames / rate };
|
|
7452
7937
|
}
|
|
@@ -7790,6 +8275,30 @@ function applyFalImageRules(model, req, callerSize, warnings) {
|
|
|
7790
8275
|
req.size = exact.tier;
|
|
7791
8276
|
}
|
|
7792
8277
|
|
|
8278
|
+
// src/replicate-video-kinds.ts
|
|
8279
|
+
function replicateBaseModelId(providerModelId) {
|
|
8280
|
+
const colon = providerModelId.indexOf(":");
|
|
8281
|
+
return colon === -1 ? providerModelId : providerModelId.slice(0, colon);
|
|
8282
|
+
}
|
|
8283
|
+
var REPLICATE_VIDEO_KINDS = /* @__PURE__ */ new Map([
|
|
8284
|
+
["kling-video/v2.5-turbo/pro/image-to-video", "kling"],
|
|
8285
|
+
["kling-video/v3.0/pro/image-to-video", "kling"],
|
|
8286
|
+
["kwaivgi/kling-v3-video", "kling"],
|
|
8287
|
+
["kwaivgi/kling-v3-omni-video", "kling-omni"],
|
|
8288
|
+
["minimax/hailuo-02", "hailuo"]
|
|
8289
|
+
]);
|
|
8290
|
+
function videoKind(providerModelId) {
|
|
8291
|
+
return REPLICATE_VIDEO_KINDS.get(replicateBaseModelId(providerModelId));
|
|
8292
|
+
}
|
|
8293
|
+
var KLING_TIERS = [
|
|
8294
|
+
{ mode: "standard", resolution: "720p" },
|
|
8295
|
+
{ mode: "pro", resolution: "1080p" },
|
|
8296
|
+
{ mode: "4k", resolution: "4k" }
|
|
8297
|
+
];
|
|
8298
|
+
function klingTier(req) {
|
|
8299
|
+
return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
|
|
8300
|
+
}
|
|
8301
|
+
|
|
7793
8302
|
// src/resolve-video-rules.ts
|
|
7794
8303
|
var MOTION_PRO = "fal-ai/kling-video/v3/pro/motion-control";
|
|
7795
8304
|
var MOTION_STANDARD = "fal-ai/kling-video/v3/standard/motion-control";
|
|
@@ -7963,6 +8472,16 @@ function h3EndFrameRatioWarning(model, ratio) {
|
|
|
7963
8472
|
message: `${model.id} follows the end frame's aspect ratio`
|
|
7964
8473
|
};
|
|
7965
8474
|
}
|
|
8475
|
+
function isReplicateKling(model) {
|
|
8476
|
+
if (model.adapter !== "replicate") return false;
|
|
8477
|
+
const kind = videoKind(model.providerModelId);
|
|
8478
|
+
return kind === "kling" || kind === "kling-omni";
|
|
8479
|
+
}
|
|
8480
|
+
function fillReplicateKlingResolution(model, req) {
|
|
8481
|
+
if (isReplicateKling(model) && req.resolution === void 0) {
|
|
8482
|
+
req.resolution = klingTier(req).resolution;
|
|
8483
|
+
}
|
|
8484
|
+
}
|
|
7966
8485
|
function applyFalVideoRules(model, req, callerRatio, warnings) {
|
|
7967
8486
|
if (model.adapter !== "fal") return;
|
|
7968
8487
|
const problem = falVideoProblem(model.providerModelId, withPromptForResolve(req));
|
|
@@ -8352,8 +8871,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
8352
8871
|
warnings
|
|
8353
8872
|
);
|
|
8354
8873
|
if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
|
|
8874
|
+
fillReplicateKlingResolution(model, merged);
|
|
8355
8875
|
const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
|
|
8356
8876
|
if (resolution !== void 0) merged.resolution = resolution;
|
|
8877
|
+
if (isReplicateKling(model)) delete merged.mode;
|
|
8357
8878
|
const duration = resolveDuration(
|
|
8358
8879
|
merged.durationSeconds,
|
|
8359
8880
|
c.durations,
|
|
@@ -8759,7 +9280,10 @@ var MEDIA_METHODS = {
|
|
|
8759
9280
|
lipsync: ["lipsync"],
|
|
8760
9281
|
dubbing: ["dub"],
|
|
8761
9282
|
transcription: ["transcribe"],
|
|
8762
|
-
"video-tool": ["submitVideoTool"]
|
|
9283
|
+
"video-tool": ["submitVideoTool"],
|
|
9284
|
+
// 3D jobs run through submitModel3d, which checks the row type itself; their preflight
|
|
9285
|
+
// is model3dInputRefusal, not resolveOptions.
|
|
9286
|
+
model3d: []
|
|
8763
9287
|
};
|
|
8764
9288
|
var METHOD_NOUN = {
|
|
8765
9289
|
generateImage: "an image model",
|