@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.js
CHANGED
|
@@ -136,11 +136,11 @@ function normalizeExposure(value) {
|
|
|
136
136
|
}
|
|
137
137
|
return value;
|
|
138
138
|
}
|
|
139
|
-
function isListedOn(
|
|
140
|
-
return
|
|
139
|
+
function isListedOn(row2, surface) {
|
|
140
|
+
return row2.lifecycle === "active" && row2.exposure.includes(surface);
|
|
141
141
|
}
|
|
142
|
-
function isListed(
|
|
143
|
-
return
|
|
142
|
+
function isListed(row2) {
|
|
143
|
+
return row2.lifecycle === "active" && row2.exposure.length > 0;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
// src/catalog/image-fal.ts
|
|
@@ -3542,6 +3542,197 @@ var MEDIA_NODE_MODELS = [
|
|
|
3542
3542
|
SAM_3_IMAGE
|
|
3543
3543
|
];
|
|
3544
3544
|
|
|
3545
|
+
// src/catalog/model3d.ts
|
|
3546
|
+
var REQUEST_USAGE = { unit: "requests" };
|
|
3547
|
+
function row(id, label, spec, display) {
|
|
3548
|
+
return {
|
|
3549
|
+
id,
|
|
3550
|
+
aliases: [],
|
|
3551
|
+
label,
|
|
3552
|
+
type: "model3d",
|
|
3553
|
+
adapter: "fal",
|
|
3554
|
+
// The single-image endpoint; the adapter picks the endpoint a request needs.
|
|
3555
|
+
providerModelId: spec.endpoints.image ?? id,
|
|
3556
|
+
lifecycle: "active",
|
|
3557
|
+
exposure: ["space_builder"],
|
|
3558
|
+
constraints: { supports: [], model3d: spec },
|
|
3559
|
+
defaults: {},
|
|
3560
|
+
usage: REQUEST_USAGE,
|
|
3561
|
+
pricingKind: "flat",
|
|
3562
|
+
display
|
|
3563
|
+
};
|
|
3564
|
+
}
|
|
3565
|
+
var MODEL3D_MODELS = [
|
|
3566
|
+
row(
|
|
3567
|
+
"trellis-2",
|
|
3568
|
+
"Trellis 2",
|
|
3569
|
+
{
|
|
3570
|
+
family: "trellis",
|
|
3571
|
+
endpoints: { image: "fal-ai/trellis-2" },
|
|
3572
|
+
text: false,
|
|
3573
|
+
imageRequired: true,
|
|
3574
|
+
views: "none",
|
|
3575
|
+
maxImages: 1,
|
|
3576
|
+
texture: [],
|
|
3577
|
+
pbr: false,
|
|
3578
|
+
textureRef: false,
|
|
3579
|
+
seed: true,
|
|
3580
|
+
resolutions: { label: "Resolution", options: ["512", "1024", "1536"], default: "1024" }
|
|
3581
|
+
},
|
|
3582
|
+
{
|
|
3583
|
+
provider: "microsoft",
|
|
3584
|
+
description: "One photo to a detailed textured model. Fast and the best value.",
|
|
3585
|
+
sortOrder: 70
|
|
3586
|
+
}
|
|
3587
|
+
),
|
|
3588
|
+
row(
|
|
3589
|
+
"hunyuan3d-3.1-pro",
|
|
3590
|
+
"Hunyuan3D 3.1 Pro",
|
|
3591
|
+
{
|
|
3592
|
+
family: "hunyuan",
|
|
3593
|
+
endpoints: {
|
|
3594
|
+
text: "fal-ai/hunyuan-3d/v3.1/pro/text-to-3d",
|
|
3595
|
+
image: "fal-ai/hunyuan-3d/v3.1/pro/image-to-3d"
|
|
3596
|
+
},
|
|
3597
|
+
text: true,
|
|
3598
|
+
imageRequired: false,
|
|
3599
|
+
views: "named",
|
|
3600
|
+
maxImages: 4,
|
|
3601
|
+
texture: ["none", "standard"],
|
|
3602
|
+
pbr: true,
|
|
3603
|
+
textureRef: false,
|
|
3604
|
+
seed: false
|
|
3605
|
+
},
|
|
3606
|
+
{
|
|
3607
|
+
provider: "tencent",
|
|
3608
|
+
description: "Photo-faithful models from a prompt, a photo, or a photo with back and side views.",
|
|
3609
|
+
sortOrder: 60
|
|
3610
|
+
}
|
|
3611
|
+
),
|
|
3612
|
+
row(
|
|
3613
|
+
"tripo-h3.1",
|
|
3614
|
+
"Tripo H3.1",
|
|
3615
|
+
{
|
|
3616
|
+
family: "tripo",
|
|
3617
|
+
endpoints: {
|
|
3618
|
+
text: "tripo3d/h3.1/text-to-3d",
|
|
3619
|
+
image: "tripo3d/h3.1/image-to-3d",
|
|
3620
|
+
multiImage: "tripo3d/h3.1/multiview-to-3d"
|
|
3621
|
+
},
|
|
3622
|
+
text: true,
|
|
3623
|
+
imageRequired: false,
|
|
3624
|
+
views: "ordered",
|
|
3625
|
+
maxImages: 4,
|
|
3626
|
+
texture: ["none", "standard", "detailed"],
|
|
3627
|
+
pbr: true,
|
|
3628
|
+
textureRef: false,
|
|
3629
|
+
seed: true
|
|
3630
|
+
},
|
|
3631
|
+
{
|
|
3632
|
+
provider: "tripo",
|
|
3633
|
+
description: "Clean, game-ready models from a prompt, a photo or four views.",
|
|
3634
|
+
sortOrder: 50
|
|
3635
|
+
}
|
|
3636
|
+
),
|
|
3637
|
+
row(
|
|
3638
|
+
"rodin-gen-2.5",
|
|
3639
|
+
"Rodin Gen-2.5",
|
|
3640
|
+
{
|
|
3641
|
+
family: "rodin",
|
|
3642
|
+
endpoints: {
|
|
3643
|
+
text: "fal-ai/hyper3d/rodin/v2.5/text-to-3d",
|
|
3644
|
+
image: "fal-ai/hyper3d/rodin/v2.5"
|
|
3645
|
+
},
|
|
3646
|
+
text: true,
|
|
3647
|
+
imageRequired: false,
|
|
3648
|
+
views: "unordered",
|
|
3649
|
+
maxImages: 5,
|
|
3650
|
+
texture: [],
|
|
3651
|
+
pbr: false,
|
|
3652
|
+
textureRef: false,
|
|
3653
|
+
seed: true,
|
|
3654
|
+
seedMax: 65535
|
|
3655
|
+
},
|
|
3656
|
+
{
|
|
3657
|
+
provider: "hyper3d",
|
|
3658
|
+
description: "Detailed PBR models from a prompt or up to five photos.",
|
|
3659
|
+
sortOrder: 40
|
|
3660
|
+
}
|
|
3661
|
+
),
|
|
3662
|
+
row(
|
|
3663
|
+
"meshy-7.1",
|
|
3664
|
+
"Meshy 7.1",
|
|
3665
|
+
{
|
|
3666
|
+
family: "meshy",
|
|
3667
|
+
endpoints: {
|
|
3668
|
+
text: "meshy/v7.1/text-to-3d",
|
|
3669
|
+
image: "meshy/v7.1/image-to-3d",
|
|
3670
|
+
multiImage: "meshy/v7.1/multi-image-to-3d"
|
|
3671
|
+
},
|
|
3672
|
+
text: true,
|
|
3673
|
+
imageRequired: false,
|
|
3674
|
+
views: "unordered",
|
|
3675
|
+
maxImages: 4,
|
|
3676
|
+
texture: ["none", "standard"],
|
|
3677
|
+
pbr: true,
|
|
3678
|
+
textureRef: true,
|
|
3679
|
+
seed: true
|
|
3680
|
+
},
|
|
3681
|
+
{
|
|
3682
|
+
provider: "meshy",
|
|
3683
|
+
description: "Models from a prompt or photos, with a texture prompt or texture image to restyle.",
|
|
3684
|
+
sortOrder: 30
|
|
3685
|
+
}
|
|
3686
|
+
),
|
|
3687
|
+
row(
|
|
3688
|
+
"hi3d-3.0",
|
|
3689
|
+
"Hi3D 3.0",
|
|
3690
|
+
{
|
|
3691
|
+
family: "hi3d",
|
|
3692
|
+
endpoints: {
|
|
3693
|
+
image: "hitem3d/hi3d/v3.0/image-to-3d",
|
|
3694
|
+
multiImage: "hitem3d/hi3d/v3.0/multi-view-to-3d"
|
|
3695
|
+
},
|
|
3696
|
+
text: false,
|
|
3697
|
+
imageRequired: true,
|
|
3698
|
+
views: "named",
|
|
3699
|
+
maxImages: 4,
|
|
3700
|
+
texture: ["none", "standard"],
|
|
3701
|
+
pbr: true,
|
|
3702
|
+
textureRef: false,
|
|
3703
|
+
seed: false,
|
|
3704
|
+
resolutions: { label: "Quality", options: ["quality", "master"], default: "quality" }
|
|
3705
|
+
},
|
|
3706
|
+
{
|
|
3707
|
+
provider: "hitem3d",
|
|
3708
|
+
description: "Highest-fidelity product models from a photo or four views. Slowest.",
|
|
3709
|
+
sortOrder: 20
|
|
3710
|
+
}
|
|
3711
|
+
),
|
|
3712
|
+
row(
|
|
3713
|
+
"sam-3d-objects",
|
|
3714
|
+
"SAM 3D Objects",
|
|
3715
|
+
{
|
|
3716
|
+
family: "sam",
|
|
3717
|
+
endpoints: { image: "fal-ai/sam-3/3d-objects" },
|
|
3718
|
+
text: true,
|
|
3719
|
+
imageRequired: true,
|
|
3720
|
+
promptRequired: true,
|
|
3721
|
+
views: "none",
|
|
3722
|
+
maxImages: 1,
|
|
3723
|
+
texture: [],
|
|
3724
|
+
pbr: false,
|
|
3725
|
+
textureRef: false,
|
|
3726
|
+
seed: true
|
|
3727
|
+
},
|
|
3728
|
+
{
|
|
3729
|
+
provider: "meta",
|
|
3730
|
+
description: "Lifts one named object out of a real photo into a 3D model.",
|
|
3731
|
+
sortOrder: 10
|
|
3732
|
+
}
|
|
3733
|
+
)
|
|
3734
|
+
];
|
|
3735
|
+
|
|
3545
3736
|
// src/catalog/other.ts
|
|
3546
3737
|
var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
|
|
3547
3738
|
var ELEVENLABS_LOGO2 = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/elevenlabs.png";
|
|
@@ -5860,6 +6051,7 @@ var MODELS = [
|
|
|
5860
6051
|
...IMAGE_MODELS,
|
|
5861
6052
|
...VIDEO_MODELS,
|
|
5862
6053
|
...VIDEO_TOOL_MODELS,
|
|
6054
|
+
...MODEL3D_MODELS,
|
|
5863
6055
|
...OTHER_MODELS,
|
|
5864
6056
|
...MEDIA_NODE_MODELS
|
|
5865
6057
|
];
|
|
@@ -5868,11 +6060,11 @@ var MODELS = [
|
|
|
5868
6060
|
import { z as z3 } from "zod";
|
|
5869
6061
|
|
|
5870
6062
|
// src/resolve-provider-rules.ts
|
|
5871
|
-
function ruleRefusal(
|
|
6063
|
+
function ruleRefusal(row2, message, code) {
|
|
5872
6064
|
return new ModelKitError({
|
|
5873
6065
|
code,
|
|
5874
|
-
message: `${
|
|
5875
|
-
model:
|
|
6066
|
+
message: `${row2.label}: ${message}`,
|
|
6067
|
+
model: row2.id,
|
|
5876
6068
|
retryable: false
|
|
5877
6069
|
});
|
|
5878
6070
|
}
|
|
@@ -6031,27 +6223,27 @@ function collisionIssues(rows) {
|
|
|
6031
6223
|
const issues = [];
|
|
6032
6224
|
const seenIds = /* @__PURE__ */ new Map();
|
|
6033
6225
|
const seenAliases = /* @__PURE__ */ new Map();
|
|
6034
|
-
rows.forEach((
|
|
6035
|
-
if (seenIds.has(
|
|
6226
|
+
rows.forEach((row2, index) => {
|
|
6227
|
+
if (seenIds.has(row2.id)) {
|
|
6036
6228
|
issues.push({
|
|
6037
6229
|
index,
|
|
6038
6230
|
path: ["id"],
|
|
6039
|
-
message: `Duplicate model id "${
|
|
6231
|
+
message: `Duplicate model id "${row2.id}"`
|
|
6040
6232
|
});
|
|
6041
6233
|
} else {
|
|
6042
|
-
const aliasOwner = seenAliases.get(
|
|
6234
|
+
const aliasOwner = seenAliases.get(row2.id);
|
|
6043
6235
|
if (aliasOwner !== void 0) {
|
|
6044
6236
|
issues.push({
|
|
6045
6237
|
index: aliasOwner.index,
|
|
6046
6238
|
path: ["aliases", aliasOwner.aliasIndex],
|
|
6047
|
-
message: `Alias "${
|
|
6239
|
+
message: `Alias "${row2.id}" collides with a model id`
|
|
6048
6240
|
});
|
|
6049
6241
|
}
|
|
6050
|
-
seenIds.set(
|
|
6242
|
+
seenIds.set(row2.id, index);
|
|
6051
6243
|
}
|
|
6052
6244
|
const local = /* @__PURE__ */ new Set();
|
|
6053
|
-
for (const [aliasIndex, alias] of
|
|
6054
|
-
if (alias ===
|
|
6245
|
+
for (const [aliasIndex, alias] of row2.aliases.entries()) {
|
|
6246
|
+
if (alias === row2.id || seenIds.has(alias)) {
|
|
6055
6247
|
issues.push({
|
|
6056
6248
|
index,
|
|
6057
6249
|
path: ["aliases", aliasIndex],
|
|
@@ -6090,23 +6282,23 @@ var ConstraintsReadView = z.looseObject({
|
|
|
6090
6282
|
}).optional().catch(void 0)
|
|
6091
6283
|
});
|
|
6092
6284
|
var DEFAULT_CONVENTIONS = { referenceSyntax: "numbered" };
|
|
6093
|
-
function outputAudio(
|
|
6094
|
-
const view = ConstraintsReadView.safeParse(
|
|
6285
|
+
function outputAudio(row2) {
|
|
6286
|
+
const view = ConstraintsReadView.safeParse(row2.constraints);
|
|
6095
6287
|
return view.success ? view.data.audio : void 0;
|
|
6096
6288
|
}
|
|
6097
6289
|
var DefaultsReadView = z.looseObject({
|
|
6098
6290
|
generateAudio: z.boolean().optional().catch(void 0)
|
|
6099
6291
|
});
|
|
6100
|
-
function billedAudio(
|
|
6101
|
-
const audio = outputAudio(
|
|
6292
|
+
function billedAudio(row2, requested) {
|
|
6293
|
+
const audio = outputAudio(row2);
|
|
6102
6294
|
if (audio === "never") return false;
|
|
6103
6295
|
if (audio !== "optional") return true;
|
|
6104
6296
|
if (requested !== void 0) return requested;
|
|
6105
|
-
const defaults = DefaultsReadView.safeParse(
|
|
6297
|
+
const defaults = DefaultsReadView.safeParse(row2.defaults);
|
|
6106
6298
|
return (defaults.success ? defaults.data.generateAudio : void 0) ?? true;
|
|
6107
6299
|
}
|
|
6108
|
-
function promptConventions(
|
|
6109
|
-
const view = ConstraintsReadView.safeParse(
|
|
6300
|
+
function promptConventions(row2) {
|
|
6301
|
+
const view = ConstraintsReadView.safeParse(row2.constraints);
|
|
6110
6302
|
const prompt = view.success ? view.data.prompt : void 0;
|
|
6111
6303
|
if (prompt === void 0) return { ...DEFAULT_CONVENTIONS };
|
|
6112
6304
|
const result = { referenceSyntax: prompt.referenceSyntax };
|
|
@@ -6117,22 +6309,111 @@ var RawConventionsView = z.looseObject({
|
|
|
6117
6309
|
audio: z.unknown().optional(),
|
|
6118
6310
|
prompt: z.unknown().optional()
|
|
6119
6311
|
});
|
|
6120
|
-
function normaliseConventions(
|
|
6121
|
-
const view = RawConventionsView.safeParse(
|
|
6122
|
-
if (!view.success) return { row, invalidKeys: [] };
|
|
6312
|
+
function normaliseConventions(row2) {
|
|
6313
|
+
const view = RawConventionsView.safeParse(row2.constraints);
|
|
6314
|
+
if (!view.success) return { row: row2, invalidKeys: [] };
|
|
6123
6315
|
const { audio, prompt } = view.data;
|
|
6124
6316
|
const badAudio = audio !== void 0 && !AudioOutputSchema.safeParse(audio).success;
|
|
6125
6317
|
const badPrompt = prompt !== void 0 && !PromptConventionsSchema.safeParse(prompt).success;
|
|
6126
|
-
if (!badAudio && !badPrompt) return { row, invalidKeys: [] };
|
|
6318
|
+
if (!badAudio && !badPrompt) return { row: row2, invalidKeys: [] };
|
|
6127
6319
|
const invalidKeys = [];
|
|
6128
6320
|
if (badAudio) invalidKeys.push("constraints.audio");
|
|
6129
6321
|
if (badPrompt) invalidKeys.push("constraints.prompt");
|
|
6130
|
-
const entries = Object.entries(
|
|
6322
|
+
const entries = Object.entries(row2.constraints).flatMap(([key, value]) => {
|
|
6131
6323
|
if (key === "audio" && badAudio) return [];
|
|
6132
|
-
if (key === "prompt" && badPrompt) return [[key, promptConventions(
|
|
6324
|
+
if (key === "prompt" && badPrompt) return [[key, promptConventions(row2)]];
|
|
6133
6325
|
return [[key, value]];
|
|
6134
6326
|
});
|
|
6135
|
-
return { row: { ...
|
|
6327
|
+
return { row: { ...row2, constraints: Object.fromEntries(entries) }, invalidKeys };
|
|
6328
|
+
}
|
|
6329
|
+
|
|
6330
|
+
// src/catalog/model3d-spec.ts
|
|
6331
|
+
function model3dConstraints(row2) {
|
|
6332
|
+
if (row2.type !== "model3d") return void 0;
|
|
6333
|
+
return row2.constraints.model3d;
|
|
6334
|
+
}
|
|
6335
|
+
var MODEL3D_IMAGE_SLOTS = {
|
|
6336
|
+
none: ["image"],
|
|
6337
|
+
named: ["image", "back", "left", "right"],
|
|
6338
|
+
ordered: ["image", "left", "back", "right"],
|
|
6339
|
+
unordered: ["image", "back", "left", "right", "top"]
|
|
6340
|
+
};
|
|
6341
|
+
function model3dInputRefusal(spec, wired) {
|
|
6342
|
+
const top = spec.views === "unordered" && wired.top === true;
|
|
6343
|
+
const anyView = spec.views !== "none" && (wired.back || wired.left || wired.right || top);
|
|
6344
|
+
if (anyView && !wired.image) return "model3d_views_need_image";
|
|
6345
|
+
if (spec.imageRequired && !wired.image) return "model3d_needs_image";
|
|
6346
|
+
if (spec.promptRequired && !wired.prompt) return "model3d_needs_prompt";
|
|
6347
|
+
if (!wired.image && !(spec.text && wired.prompt)) return "model3d_needs_input";
|
|
6348
|
+
if (spec.views === "ordered") {
|
|
6349
|
+
if ((wired.back || wired.right) && !wired.left) return "model3d_views_out_of_order";
|
|
6350
|
+
if (wired.right && !wired.back) return "model3d_views_out_of_order";
|
|
6351
|
+
}
|
|
6352
|
+
return null;
|
|
6353
|
+
}
|
|
6354
|
+
function model3dSeedFits(spec, seed) {
|
|
6355
|
+
return Number.isSafeInteger(seed) && seed >= 0 && seed <= (spec.seedMax ?? Number.MAX_SAFE_INTEGER);
|
|
6356
|
+
}
|
|
6357
|
+
function model3dTexture(spec, requested) {
|
|
6358
|
+
if (requested !== void 0 && spec.texture.includes(requested)) return requested;
|
|
6359
|
+
return spec.texture.includes("standard") ? "standard" : spec.texture[0] ?? "standard";
|
|
6360
|
+
}
|
|
6361
|
+
function model3dResolution(spec, requested) {
|
|
6362
|
+
const res = spec.resolutions;
|
|
6363
|
+
if (res === void 0) return void 0;
|
|
6364
|
+
return requested !== void 0 && res.options.includes(requested) ? requested : res.default;
|
|
6365
|
+
}
|
|
6366
|
+
function model3dPricingSku(row2, options, inputs) {
|
|
6367
|
+
const spec = model3dConstraints(row2);
|
|
6368
|
+
if (spec === void 0) throw new Error(`${row2.id} is not a 3D model`);
|
|
6369
|
+
const texture = model3dTexture(spec, options.texture);
|
|
6370
|
+
const textured = spec.texture.length > 0 && texture !== "none";
|
|
6371
|
+
const pbr = spec.pbr && textured && options.pbr === true;
|
|
6372
|
+
const resolution = model3dResolution(spec, options.resolution);
|
|
6373
|
+
switch (spec.family) {
|
|
6374
|
+
case "meshy":
|
|
6375
|
+
return `${row2.id}__${textured ? "textured" : "untextured"}`;
|
|
6376
|
+
case "tripo":
|
|
6377
|
+
return `${row2.id}__${inputs.image ? "image" : "text"}__${texture}`;
|
|
6378
|
+
case "hunyuan":
|
|
6379
|
+
return `${row2.id}${pbr ? "__pbr" : ""}${inputs.views ? "__views" : ""}`;
|
|
6380
|
+
case "trellis":
|
|
6381
|
+
return `${row2.id}__${resolution}`;
|
|
6382
|
+
case "hi3d":
|
|
6383
|
+
return `${row2.id}__${resolution}__${textured ? pbr ? "texture-pbr" : "texture" : "geometry"}`;
|
|
6384
|
+
case "rodin":
|
|
6385
|
+
case "sam":
|
|
6386
|
+
return row2.id;
|
|
6387
|
+
}
|
|
6388
|
+
}
|
|
6389
|
+
function model3dSkus(row2) {
|
|
6390
|
+
const spec = model3dConstraints(row2);
|
|
6391
|
+
if (spec === void 0) return [];
|
|
6392
|
+
const textures = spec.texture.length > 0 ? spec.texture : [void 0];
|
|
6393
|
+
const pbrs = spec.pbr ? [false, true] : [false];
|
|
6394
|
+
const resolutions = spec.resolutions?.options ?? [void 0];
|
|
6395
|
+
const images = spec.text && !spec.imageRequired ? [true, false] : [true];
|
|
6396
|
+
const views = spec.views === "none" ? [false] : [false, true];
|
|
6397
|
+
const skus = /* @__PURE__ */ new Set();
|
|
6398
|
+
for (const texture of textures)
|
|
6399
|
+
for (const pbr of pbrs)
|
|
6400
|
+
for (const resolution of resolutions)
|
|
6401
|
+
for (const image of images)
|
|
6402
|
+
for (const view of views) {
|
|
6403
|
+
if (view && !image) continue;
|
|
6404
|
+
skus.add(
|
|
6405
|
+
model3dPricingSku(
|
|
6406
|
+
row2,
|
|
6407
|
+
{
|
|
6408
|
+
...texture !== void 0 && { texture },
|
|
6409
|
+
pbr,
|
|
6410
|
+
...resolution !== void 0 && { resolution }
|
|
6411
|
+
},
|
|
6412
|
+
{ image, views: view }
|
|
6413
|
+
)
|
|
6414
|
+
);
|
|
6415
|
+
}
|
|
6416
|
+
return [...skus].sort();
|
|
6136
6417
|
}
|
|
6137
6418
|
|
|
6138
6419
|
// src/catalog/input-spec.ts
|
|
@@ -6277,7 +6558,7 @@ var InputSpecSchema = z2.strictObject({
|
|
|
6277
6558
|
}
|
|
6278
6559
|
}
|
|
6279
6560
|
});
|
|
6280
|
-
function validateInputSpec(raw,
|
|
6561
|
+
function validateInputSpec(raw, row2) {
|
|
6281
6562
|
const parsed = InputSpecSchema.safeParse(raw);
|
|
6282
6563
|
if (!parsed.success) {
|
|
6283
6564
|
return {
|
|
@@ -6289,7 +6570,7 @@ function validateInputSpec(raw, row) {
|
|
|
6289
6570
|
};
|
|
6290
6571
|
}
|
|
6291
6572
|
const spec = parsed.data;
|
|
6292
|
-
const supportedTypes = TYPES_BY_ADAPTER.get(
|
|
6573
|
+
const supportedTypes = TYPES_BY_ADAPTER.get(row2.adapter);
|
|
6293
6574
|
if (supportedTypes === void 0) {
|
|
6294
6575
|
return {
|
|
6295
6576
|
ok: false,
|
|
@@ -6302,18 +6583,18 @@ function validateInputSpec(raw, row) {
|
|
|
6302
6583
|
};
|
|
6303
6584
|
}
|
|
6304
6585
|
const issues = [];
|
|
6305
|
-
const allowed = ALLOWED_KEYS_BY_TYPE.get(
|
|
6306
|
-
if (allowed === void 0 || !supportedTypes.includes(
|
|
6586
|
+
const allowed = ALLOWED_KEYS_BY_TYPE.get(row2.type);
|
|
6587
|
+
if (allowed === void 0 || !supportedTypes.includes(row2.type)) {
|
|
6307
6588
|
issues.push({
|
|
6308
6589
|
path: [],
|
|
6309
|
-
message:
|
|
6590
|
+
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`
|
|
6310
6591
|
});
|
|
6311
6592
|
} else {
|
|
6312
6593
|
for (const key of Object.keys(spec.fields)) {
|
|
6313
6594
|
if (!allowed.has(key)) {
|
|
6314
6595
|
issues.push({
|
|
6315
6596
|
path: ["fields", key],
|
|
6316
|
-
message: `inputSpec.fields "${key}" is not supported for ${
|
|
6597
|
+
message: `inputSpec.fields "${key}" is not supported for ${row2.type} rows`
|
|
6317
6598
|
});
|
|
6318
6599
|
}
|
|
6319
6600
|
}
|
|
@@ -6321,13 +6602,13 @@ function validateInputSpec(raw, row) {
|
|
|
6321
6602
|
if (!allowed.has(key)) {
|
|
6322
6603
|
issues.push({
|
|
6323
6604
|
path: ["values", key],
|
|
6324
|
-
message: `inputSpec.values "${key}" is not supported for ${
|
|
6605
|
+
message: `inputSpec.values "${key}" is not supported for ${row2.type} rows`
|
|
6325
6606
|
});
|
|
6326
6607
|
}
|
|
6327
6608
|
}
|
|
6328
6609
|
}
|
|
6329
6610
|
if (spec.editEndpoint !== void 0) {
|
|
6330
|
-
if (
|
|
6611
|
+
if (row2.adapter !== "fal") {
|
|
6331
6612
|
issues.push({
|
|
6332
6613
|
path: ["editEndpoint"],
|
|
6333
6614
|
message: "inputSpec.editEndpoint is only supported on fal rows"
|
|
@@ -6371,7 +6652,7 @@ function validateInputSpec(raw, row) {
|
|
|
6371
6652
|
if (allowed !== void 0 && !allowed.has(key)) {
|
|
6372
6653
|
issues.push({
|
|
6373
6654
|
path: ["arrays", name],
|
|
6374
|
-
message: `inputSpec.arrays "${key}" is not supported for ${
|
|
6655
|
+
message: `inputSpec.arrays "${key}" is not supported for ${row2.type} rows`
|
|
6375
6656
|
});
|
|
6376
6657
|
}
|
|
6377
6658
|
if (key in spec.fields) {
|
|
@@ -6391,7 +6672,7 @@ function validateInputSpec(raw, row) {
|
|
|
6391
6672
|
}
|
|
6392
6673
|
}
|
|
6393
6674
|
if (spec.dimensions !== void 0) {
|
|
6394
|
-
if (
|
|
6675
|
+
if (row2.type !== "image") {
|
|
6395
6676
|
issues.push({
|
|
6396
6677
|
path: ["dimensions"],
|
|
6397
6678
|
message: "inputSpec.dimensions is only supported on image rows"
|
|
@@ -6413,7 +6694,7 @@ function validateInputSpec(raw, row) {
|
|
|
6413
6694
|
});
|
|
6414
6695
|
}
|
|
6415
6696
|
}
|
|
6416
|
-
const supports =
|
|
6697
|
+
const supports = row2.constraints.supports ?? [];
|
|
6417
6698
|
for (const key of INPUT_SPEC_SUPPORTS_KEYS) {
|
|
6418
6699
|
if (supports.includes(key)) continue;
|
|
6419
6700
|
if (key in spec.fields) {
|
|
@@ -6458,8 +6739,8 @@ function listIssues(name, values, fallback, defaultKey) {
|
|
|
6458
6739
|
}
|
|
6459
6740
|
return issues;
|
|
6460
6741
|
}
|
|
6461
|
-
function optionListIssues(
|
|
6462
|
-
const { constraints, defaults } =
|
|
6742
|
+
function optionListIssues(row2) {
|
|
6743
|
+
const { constraints, defaults } = row2;
|
|
6463
6744
|
const issues = [
|
|
6464
6745
|
...listIssues(
|
|
6465
6746
|
"voices",
|
|
@@ -6517,7 +6798,8 @@ var ModelTypeSchema = z3.enum([
|
|
|
6517
6798
|
"voice-change",
|
|
6518
6799
|
"dubbing",
|
|
6519
6800
|
"lipsync",
|
|
6520
|
-
"transcription"
|
|
6801
|
+
"transcription",
|
|
6802
|
+
"model3d"
|
|
6521
6803
|
]);
|
|
6522
6804
|
var LifecycleSchema = z3.enum(["active", "deprecated", "retired"]);
|
|
6523
6805
|
var SurfaceSchema = z3.enum(["cowork", "space_builder"]);
|
|
@@ -6581,7 +6863,8 @@ var UsageUnitSchema = z3.enum([
|
|
|
6581
6863
|
"images",
|
|
6582
6864
|
"seconds",
|
|
6583
6865
|
"reported_cost_usd",
|
|
6584
|
-
"compute_seconds"
|
|
6866
|
+
"compute_seconds",
|
|
6867
|
+
"requests"
|
|
6585
6868
|
]);
|
|
6586
6869
|
var PricingKindSchema = z3.enum(["token", "image_size", "video_per_second", "flat"]);
|
|
6587
6870
|
var ProviderOptionValueSchema = z3.lazy(
|
|
@@ -6635,6 +6918,156 @@ var LanguageOptionSchema = z3.looseObject({
|
|
|
6635
6918
|
code: z3.string().min(1),
|
|
6636
6919
|
name: z3.string().min(1)
|
|
6637
6920
|
});
|
|
6921
|
+
var MODEL3D_FAMILY_RULES = {
|
|
6922
|
+
trellis: {
|
|
6923
|
+
textPath: false,
|
|
6924
|
+
views: ["none"],
|
|
6925
|
+
multiImage: false,
|
|
6926
|
+
texture: null,
|
|
6927
|
+
pbr: false,
|
|
6928
|
+
seed: true,
|
|
6929
|
+
textureRef: false,
|
|
6930
|
+
resolutions: "integer"
|
|
6931
|
+
},
|
|
6932
|
+
hunyuan: {
|
|
6933
|
+
textPath: true,
|
|
6934
|
+
views: ["none", "named"],
|
|
6935
|
+
multiImage: false,
|
|
6936
|
+
texture: ["none", "standard"],
|
|
6937
|
+
pbr: true,
|
|
6938
|
+
seed: false,
|
|
6939
|
+
textureRef: false,
|
|
6940
|
+
resolutions: null
|
|
6941
|
+
},
|
|
6942
|
+
tripo: {
|
|
6943
|
+
textPath: true,
|
|
6944
|
+
views: ["none", "ordered"],
|
|
6945
|
+
multiImage: true,
|
|
6946
|
+
texture: ["none", "standard", "detailed"],
|
|
6947
|
+
pbr: true,
|
|
6948
|
+
seed: true,
|
|
6949
|
+
textureRef: false,
|
|
6950
|
+
resolutions: null
|
|
6951
|
+
},
|
|
6952
|
+
rodin: {
|
|
6953
|
+
textPath: true,
|
|
6954
|
+
views: ["none", "unordered"],
|
|
6955
|
+
multiImage: false,
|
|
6956
|
+
texture: null,
|
|
6957
|
+
pbr: false,
|
|
6958
|
+
seed: true,
|
|
6959
|
+
textureRef: false,
|
|
6960
|
+
resolutions: null
|
|
6961
|
+
},
|
|
6962
|
+
meshy: {
|
|
6963
|
+
textPath: true,
|
|
6964
|
+
views: ["none", "unordered"],
|
|
6965
|
+
multiImage: true,
|
|
6966
|
+
texture: ["none", "standard"],
|
|
6967
|
+
pbr: true,
|
|
6968
|
+
seed: true,
|
|
6969
|
+
textureRef: true,
|
|
6970
|
+
resolutions: null
|
|
6971
|
+
},
|
|
6972
|
+
hi3d: {
|
|
6973
|
+
textPath: false,
|
|
6974
|
+
views: ["none", "named"],
|
|
6975
|
+
multiImage: true,
|
|
6976
|
+
texture: ["none", "standard"],
|
|
6977
|
+
pbr: true,
|
|
6978
|
+
seed: false,
|
|
6979
|
+
textureRef: false,
|
|
6980
|
+
resolutions: ["quality", "master"]
|
|
6981
|
+
},
|
|
6982
|
+
sam: {
|
|
6983
|
+
textPath: false,
|
|
6984
|
+
views: ["none"],
|
|
6985
|
+
multiImage: false,
|
|
6986
|
+
texture: null,
|
|
6987
|
+
pbr: false,
|
|
6988
|
+
seed: true,
|
|
6989
|
+
textureRef: false,
|
|
6990
|
+
resolutions: null
|
|
6991
|
+
}
|
|
6992
|
+
};
|
|
6993
|
+
function model3dSpecIssues(spec) {
|
|
6994
|
+
const issues = [];
|
|
6995
|
+
const add = (path, message) => issues.push({ path, message });
|
|
6996
|
+
const rules = MODEL3D_FAMILY_RULES[spec.family];
|
|
6997
|
+
const promptOnly = spec.text && !spec.imageRequired;
|
|
6998
|
+
if (spec.endpoints.image === void 0)
|
|
6999
|
+
add(["endpoints", "image"], "every row needs an image endpoint");
|
|
7000
|
+
if (promptOnly && !rules.textPath) {
|
|
7001
|
+
add(
|
|
7002
|
+
["imageRequired"],
|
|
7003
|
+
`${spec.family} has no text-to-3D endpoint; a text row needs an image`
|
|
7004
|
+
);
|
|
7005
|
+
}
|
|
7006
|
+
if (promptOnly && spec.endpoints.text === void 0) {
|
|
7007
|
+
add(["endpoints", "text"], "a text row needs a text endpoint");
|
|
7008
|
+
}
|
|
7009
|
+
if (!rules.views.includes(spec.views)) {
|
|
7010
|
+
add(["views"], `${spec.family} takes views ${rules.views.join(" or ")}`);
|
|
7011
|
+
}
|
|
7012
|
+
if (spec.views === "none" && spec.maxImages !== 1) {
|
|
7013
|
+
add(["maxImages"], "a row without views takes 1 image");
|
|
7014
|
+
}
|
|
7015
|
+
if (spec.views === "unordered" && spec.maxImages < 2) {
|
|
7016
|
+
add(["maxImages"], "a row with views takes at least 2 images");
|
|
7017
|
+
}
|
|
7018
|
+
const slots = MODEL3D_IMAGE_SLOTS[spec.views].length;
|
|
7019
|
+
if (spec.views !== "none" && spec.maxImages > slots) {
|
|
7020
|
+
add(["maxImages"], `a row with ${spec.views} views sends at most ${slots} images`);
|
|
7021
|
+
}
|
|
7022
|
+
if ((spec.views === "named" || spec.views === "ordered") && spec.maxImages < slots) {
|
|
7023
|
+
add(
|
|
7024
|
+
["maxImages"],
|
|
7025
|
+
`a row with ${spec.views} views takes ${slots} images (front and three sides)`
|
|
7026
|
+
);
|
|
7027
|
+
}
|
|
7028
|
+
if (spec.views !== "none" && rules.multiImage && spec.endpoints.multiImage === void 0) {
|
|
7029
|
+
add(["endpoints", "multiImage"], `${spec.family} sends views to a multi-image endpoint`);
|
|
7030
|
+
}
|
|
7031
|
+
if (rules.texture === null) {
|
|
7032
|
+
if (spec.texture.length > 0) add(["texture"], `${spec.family} has no texture switch`);
|
|
7033
|
+
} else {
|
|
7034
|
+
const allowed = rules.texture;
|
|
7035
|
+
if (spec.texture.length === 0) add(["texture"], `${spec.family} needs its texture options`);
|
|
7036
|
+
if (new Set(spec.texture).size !== spec.texture.length)
|
|
7037
|
+
add(["texture"], "texture options repeat");
|
|
7038
|
+
for (const t of spec.texture) {
|
|
7039
|
+
if (!allowed.includes(t)) add(["texture"], `${spec.family} has no "${t}" texture`);
|
|
7040
|
+
}
|
|
7041
|
+
}
|
|
7042
|
+
if (spec.pbr && !rules.pbr) add(["pbr"], `${spec.family} has no PBR switch`);
|
|
7043
|
+
if (spec.pbr && !spec.texture.some((t) => t !== "none")) {
|
|
7044
|
+
add(["pbr"], "PBR needs a textured option");
|
|
7045
|
+
}
|
|
7046
|
+
if (spec.seed && !rules.seed) add(["seed"], `${spec.family} takes no seed`);
|
|
7047
|
+
if (spec.seedMax !== void 0 && !spec.seed) add(["seedMax"], "seedMax needs seed");
|
|
7048
|
+
if (spec.textureRef && !rules.textureRef)
|
|
7049
|
+
add(["textureRef"], `${spec.family} takes no texture reference`);
|
|
7050
|
+
const res = spec.resolutions;
|
|
7051
|
+
if (rules.resolutions === null) {
|
|
7052
|
+
if (res !== void 0) add(["resolutions"], `${spec.family} has no resolution option`);
|
|
7053
|
+
} else if (res === void 0) {
|
|
7054
|
+
add(["resolutions"], `${spec.family} needs its resolution options`);
|
|
7055
|
+
} else {
|
|
7056
|
+
if (!res.options.includes(res.default)) {
|
|
7057
|
+
add(["resolutions", "default"], "default must be an option");
|
|
7058
|
+
}
|
|
7059
|
+
if (new Set(res.options).size !== res.options.length) {
|
|
7060
|
+
add(["resolutions", "options"], "resolution options repeat");
|
|
7061
|
+
}
|
|
7062
|
+
const allowed = rules.resolutions;
|
|
7063
|
+
for (const option of res.options) {
|
|
7064
|
+
const ok = allowed === "integer" ? /^[1-9][0-9]*$/.test(option) : allowed.includes(option);
|
|
7065
|
+
if (!ok)
|
|
7066
|
+
add(["resolutions", "options"], `${spec.family} has no "${option}" resolution`);
|
|
7067
|
+
}
|
|
7068
|
+
}
|
|
7069
|
+
return issues;
|
|
7070
|
+
}
|
|
6638
7071
|
var VideoToolConstraintsSchema = z3.looseObject({
|
|
6639
7072
|
kind: z3.enum(["upscale", "interpolate", "hdr", "bg-remove", "subtitles"]),
|
|
6640
7073
|
upscaleFactor: RangeSchema.optional(),
|
|
@@ -6651,6 +7084,30 @@ var VideoToolConstraintsSchema = z3.looseObject({
|
|
|
6651
7084
|
translationLanguages: z3.array(z3.string().min(1)).min(1).optional(),
|
|
6652
7085
|
maxSecondsAbove1080p: z3.number().positive().optional()
|
|
6653
7086
|
});
|
|
7087
|
+
var Model3dTextureSchema = z3.enum(["none", "standard", "detailed"]);
|
|
7088
|
+
var Model3dConstraintsSchema = z3.looseObject({
|
|
7089
|
+
family: z3.enum(["trellis", "hunyuan", "tripo", "rodin", "meshy", "hi3d", "sam"]),
|
|
7090
|
+
endpoints: z3.looseObject({
|
|
7091
|
+
text: z3.string().min(1).optional(),
|
|
7092
|
+
image: z3.string().min(1).optional(),
|
|
7093
|
+
multiImage: z3.string().min(1).optional()
|
|
7094
|
+
}),
|
|
7095
|
+
text: z3.boolean(),
|
|
7096
|
+
imageRequired: z3.boolean(),
|
|
7097
|
+
promptRequired: z3.boolean().optional(),
|
|
7098
|
+
views: z3.enum(["none", "unordered", "ordered", "named"]),
|
|
7099
|
+
maxImages: z3.number().int().positive(),
|
|
7100
|
+
texture: z3.array(Model3dTextureSchema),
|
|
7101
|
+
pbr: z3.boolean(),
|
|
7102
|
+
textureRef: z3.boolean(),
|
|
7103
|
+
seed: z3.boolean(),
|
|
7104
|
+
seedMax: z3.number().int().positive().optional(),
|
|
7105
|
+
resolutions: z3.looseObject({
|
|
7106
|
+
label: z3.string().min(1),
|
|
7107
|
+
options: z3.array(z3.string().min(1)).min(1),
|
|
7108
|
+
default: z3.string().min(1)
|
|
7109
|
+
}).optional()
|
|
7110
|
+
});
|
|
6654
7111
|
var ModelConstraintsSchema = z3.looseObject({
|
|
6655
7112
|
aspectRatios: z3.array(AspectRatioSchema).optional(),
|
|
6656
7113
|
sizes: z3.array(ImageSizeSchema).optional(),
|
|
@@ -6678,6 +7135,7 @@ var ModelConstraintsSchema = z3.looseObject({
|
|
|
6678
7135
|
returns: z3.enum(["new", "joined"]).optional()
|
|
6679
7136
|
}).optional(),
|
|
6680
7137
|
tool: VideoToolConstraintsSchema.optional(),
|
|
7138
|
+
model3d: Model3dConstraintsSchema.optional(),
|
|
6681
7139
|
// Loose on purpose: the read path keeps a row whose value is invalid (the accessors in
|
|
6682
7140
|
// conventions.ts read it as "not set"); CatalogModelSchema below rejects it on write.
|
|
6683
7141
|
audio: z3.unknown().optional(),
|
|
@@ -6793,29 +7251,47 @@ var CatalogModelSchemaBase = z3.looseObject({
|
|
|
6793
7251
|
pricingKind: PricingKindSchema,
|
|
6794
7252
|
display: CatalogDisplaySchema.optional(),
|
|
6795
7253
|
capabilities: CatalogCapabilitiesSchema.optional()
|
|
6796
|
-
}).superRefine((
|
|
6797
|
-
if (
|
|
7254
|
+
}).superRefine((row2, ctx) => {
|
|
7255
|
+
if (row2.lifecycle === "active" && !row2.display) {
|
|
6798
7256
|
ctx.addIssue({
|
|
6799
7257
|
code: "custom",
|
|
6800
7258
|
path: ["display"],
|
|
6801
7259
|
message: "active rows need display"
|
|
6802
7260
|
});
|
|
6803
7261
|
}
|
|
6804
|
-
if (
|
|
7262
|
+
if (row2.lifecycle === "active" && row2.type === "text" && !row2.capabilities?.contextWindow) {
|
|
6805
7263
|
ctx.addIssue({
|
|
6806
7264
|
code: "custom",
|
|
6807
7265
|
path: ["capabilities", "contextWindow"],
|
|
6808
7266
|
message: "active text rows need contextWindow"
|
|
6809
7267
|
});
|
|
6810
7268
|
}
|
|
6811
|
-
if (
|
|
7269
|
+
if (row2.type === "video-tool" && row2.constraints.tool === void 0) {
|
|
6812
7270
|
ctx.addIssue({
|
|
6813
7271
|
code: "custom",
|
|
6814
7272
|
path: ["constraints", "tool"],
|
|
6815
7273
|
message: "video-tool rows need constraints.tool"
|
|
6816
7274
|
});
|
|
6817
7275
|
}
|
|
6818
|
-
if (
|
|
7276
|
+
if (row2.type === "model3d") {
|
|
7277
|
+
const spec = row2.constraints.model3d;
|
|
7278
|
+
if (spec === void 0) {
|
|
7279
|
+
ctx.addIssue({
|
|
7280
|
+
code: "custom",
|
|
7281
|
+
path: ["constraints", "model3d"],
|
|
7282
|
+
message: "model3d rows need constraints.model3d"
|
|
7283
|
+
});
|
|
7284
|
+
} else {
|
|
7285
|
+
for (const issue of model3dSpecIssues(spec)) {
|
|
7286
|
+
ctx.addIssue({
|
|
7287
|
+
code: "custom",
|
|
7288
|
+
path: ["constraints", "model3d", ...issue.path],
|
|
7289
|
+
message: issue.message
|
|
7290
|
+
});
|
|
7291
|
+
}
|
|
7292
|
+
}
|
|
7293
|
+
}
|
|
7294
|
+
if (row2.replacedBy !== void 0 && row2.replacedBy === row2.id) {
|
|
6819
7295
|
ctx.addIssue({
|
|
6820
7296
|
code: "custom",
|
|
6821
7297
|
path: ["replacedBy"],
|
|
@@ -6824,8 +7300,8 @@ var CatalogModelSchemaBase = z3.looseObject({
|
|
|
6824
7300
|
}
|
|
6825
7301
|
});
|
|
6826
7302
|
var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
6827
|
-
(
|
|
6828
|
-
const transport =
|
|
7303
|
+
(row2, ctx) => {
|
|
7304
|
+
const transport = row2.providerOptions?.["modelkit"]?.["transport"];
|
|
6829
7305
|
if (transport !== void 0 && transport !== "direct" && transport !== "bedrock") {
|
|
6830
7306
|
ctx.addIssue({
|
|
6831
7307
|
code: "custom",
|
|
@@ -6833,9 +7309,9 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
|
6833
7309
|
message: 'transport must be "direct" or "bedrock"'
|
|
6834
7310
|
});
|
|
6835
7311
|
}
|
|
6836
|
-
const inputSpecRaw =
|
|
7312
|
+
const inputSpecRaw = row2.providerOptions?.["modelkit"]?.["inputSpec"];
|
|
6837
7313
|
if (inputSpecRaw !== void 0) {
|
|
6838
|
-
const result = validateInputSpec(inputSpecRaw,
|
|
7314
|
+
const result = validateInputSpec(inputSpecRaw, row2);
|
|
6839
7315
|
if (!result.ok) {
|
|
6840
7316
|
for (const issue of result.issues) {
|
|
6841
7317
|
ctx.addIssue({
|
|
@@ -6846,7 +7322,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
|
6846
7322
|
}
|
|
6847
7323
|
}
|
|
6848
7324
|
}
|
|
6849
|
-
const audio =
|
|
7325
|
+
const audio = row2.constraints.audio;
|
|
6850
7326
|
if (audio !== void 0 && !AudioOutputSchema.safeParse(audio).success) {
|
|
6851
7327
|
ctx.addIssue({
|
|
6852
7328
|
code: "custom",
|
|
@@ -6854,7 +7330,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
|
6854
7330
|
message: 'audio must be "always", "optional" or "never"'
|
|
6855
7331
|
});
|
|
6856
7332
|
}
|
|
6857
|
-
const refs =
|
|
7333
|
+
const refs = row2.constraints.references;
|
|
6858
7334
|
for (const kind of ["images", "videos", "audios"]) {
|
|
6859
7335
|
const least = refs?.min?.[kind];
|
|
6860
7336
|
const most = refs?.[kind];
|
|
@@ -6866,10 +7342,10 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
|
6866
7342
|
});
|
|
6867
7343
|
}
|
|
6868
7344
|
}
|
|
6869
|
-
for (const issue of optionListIssues(
|
|
7345
|
+
for (const issue of optionListIssues(row2)) {
|
|
6870
7346
|
ctx.addIssue({ code: "custom", path: issue.path, message: issue.message });
|
|
6871
7347
|
}
|
|
6872
|
-
const prompt =
|
|
7348
|
+
const prompt = row2.constraints.prompt;
|
|
6873
7349
|
if (prompt !== void 0) {
|
|
6874
7350
|
const parsed = PromptConventionsSchema.safeParse(prompt);
|
|
6875
7351
|
if (!parsed.success) {
|
|
@@ -6884,7 +7360,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
|
|
|
6884
7360
|
}
|
|
6885
7361
|
}
|
|
6886
7362
|
);
|
|
6887
|
-
var CatalogSchema = z3.array(CatalogModelSchemaBase.transform((
|
|
7363
|
+
var CatalogSchema = z3.array(CatalogModelSchemaBase.transform((row2) => normaliseConventions(row2).row)).superRefine((rows, ctx) => {
|
|
6888
7364
|
for (const issue of collisionIssues(rows)) {
|
|
6889
7365
|
ctx.addIssue({
|
|
6890
7366
|
code: "custom",
|
|
@@ -6958,22 +7434,22 @@ function quarantine(rawRows, logger) {
|
|
|
6958
7434
|
dropped += 1;
|
|
6959
7435
|
continue;
|
|
6960
7436
|
}
|
|
6961
|
-
const
|
|
6962
|
-
const inputSpecRaw =
|
|
7437
|
+
const row2 = parsed.data;
|
|
7438
|
+
const inputSpecRaw = row2.providerOptions?.["modelkit"]?.["inputSpec"];
|
|
6963
7439
|
if (inputSpecRaw !== void 0) {
|
|
6964
|
-
const result = validateInputSpec(inputSpecRaw,
|
|
7440
|
+
const result = validateInputSpec(inputSpecRaw, row2);
|
|
6965
7441
|
if (!result.ok) {
|
|
6966
7442
|
const first = result.issues[0];
|
|
6967
7443
|
const detail = first ? dropReason(first.path, first.message) : "invalid inputSpec";
|
|
6968
7444
|
logger.warn(
|
|
6969
|
-
`[modelkit] catalog row ${
|
|
7445
|
+
`[modelkit] catalog row ${row2.id} has an invalid providerOptions.modelkit.inputSpec: ${detail}; calls fail until it is fixed`
|
|
6970
7446
|
);
|
|
6971
7447
|
}
|
|
6972
7448
|
}
|
|
6973
|
-
const normalised = normaliseConventions(
|
|
7449
|
+
const normalised = normaliseConventions(row2);
|
|
6974
7450
|
if (normalised.invalidKeys.length > 0) {
|
|
6975
7451
|
logger.warn(
|
|
6976
|
-
`[modelkit] catalog row ${
|
|
7452
|
+
`[modelkit] catalog row ${row2.id} has an invalid ${normalised.invalidKeys.join(", ")}; read as not set`
|
|
6977
7453
|
);
|
|
6978
7454
|
}
|
|
6979
7455
|
valid.push(normalised.row);
|
|
@@ -6987,10 +7463,10 @@ function quarantine(rawRows, logger) {
|
|
|
6987
7463
|
if (!firstByIndex.has(issue.index)) firstByIndex.set(issue.index, issue);
|
|
6988
7464
|
}
|
|
6989
7465
|
for (const [index, issue] of [...firstByIndex.entries()].sort((a, b) => a[0] - b[0])) {
|
|
6990
|
-
const
|
|
6991
|
-
if (!
|
|
7466
|
+
const row2 = kept[index];
|
|
7467
|
+
if (!row2) continue;
|
|
6992
7468
|
logger.warn(
|
|
6993
|
-
`[modelkit] catalog row dropped id=${
|
|
7469
|
+
`[modelkit] catalog row dropped id=${row2.id} reason=${String(issue.path[0] ?? "")} ${issue.message}`
|
|
6994
7470
|
);
|
|
6995
7471
|
}
|
|
6996
7472
|
const dropSet = new Set(firstByIndex.keys());
|
|
@@ -7209,9 +7685,9 @@ var ToolSchema = z6.object({
|
|
|
7209
7685
|
translationLanguages: z6.array(z6.string().min(1)).min(1).optional(),
|
|
7210
7686
|
maxSecondsAbove1080p: z6.number().positive().optional()
|
|
7211
7687
|
});
|
|
7212
|
-
function videoToolConstraints(
|
|
7213
|
-
if (
|
|
7214
|
-
const parsed = ToolSchema.safeParse(
|
|
7688
|
+
function videoToolConstraints(row2) {
|
|
7689
|
+
if (row2.type !== "video-tool") return void 0;
|
|
7690
|
+
const parsed = ToolSchema.safeParse(row2.constraints.tool);
|
|
7215
7691
|
if (!parsed.success) return void 0;
|
|
7216
7692
|
const {
|
|
7217
7693
|
kind,
|
|
@@ -7258,16 +7734,16 @@ function resolutionTier(width, height) {
|
|
|
7258
7734
|
function fail(error) {
|
|
7259
7735
|
return { ok: false, error };
|
|
7260
7736
|
}
|
|
7261
|
-
function planVideoTool(
|
|
7262
|
-
const tool = videoToolConstraints(
|
|
7263
|
-
if (!tool) return fail(`${
|
|
7737
|
+
function planVideoTool(row2, req) {
|
|
7738
|
+
const tool = videoToolConstraints(row2);
|
|
7739
|
+
if (!tool) return fail(`${row2.id} is not a video tool`);
|
|
7264
7740
|
const { width, height, durationSeconds, fps } = req.source;
|
|
7265
7741
|
if (!(width > 0 && height > 0 && durationSeconds > 0)) {
|
|
7266
7742
|
return fail("The source video's width, height and duration are required");
|
|
7267
7743
|
}
|
|
7268
|
-
const maxSeconds =
|
|
7744
|
+
const maxSeconds = row2.constraints.sourceVideoSeconds?.max;
|
|
7269
7745
|
if (maxSeconds !== void 0 && overMax(durationSeconds, maxSeconds)) {
|
|
7270
|
-
return fail(`${
|
|
7746
|
+
return fail(`${row2.label} takes source videos up to ${maxSeconds} seconds.`);
|
|
7271
7747
|
}
|
|
7272
7748
|
const base = {
|
|
7273
7749
|
durationSeconds,
|
|
@@ -7278,7 +7754,7 @@ function planVideoTool(row, req) {
|
|
|
7278
7754
|
if (factor === void 0) return fail("An upscale factor is required");
|
|
7279
7755
|
const range2 = tool.upscaleFactor;
|
|
7280
7756
|
if (range2 && (factor < range2.min || factor > range2.max)) {
|
|
7281
|
-
return fail(`${
|
|
7757
|
+
return fail(`${row2.label} upscales by ${range2.min}x to ${range2.max}x.`);
|
|
7282
7758
|
}
|
|
7283
7759
|
const outWidth = Math.round(width * factor);
|
|
7284
7760
|
const outHeight = Math.round(height * factor);
|
|
@@ -7306,7 +7782,7 @@ function planVideoTool(row, req) {
|
|
|
7306
7782
|
}
|
|
7307
7783
|
const range2 = tool.fps;
|
|
7308
7784
|
if (range2 && (target < range2.min || target > range2.max)) {
|
|
7309
|
-
return fail(`${
|
|
7785
|
+
return fail(`${row2.label} outputs ${range2.min} to ${range2.max} fps.`);
|
|
7310
7786
|
}
|
|
7311
7787
|
return {
|
|
7312
7788
|
ok: true,
|
|
@@ -7335,7 +7811,7 @@ function planVideoTool(row, req) {
|
|
|
7335
7811
|
if (tool.kind === "subtitles") {
|
|
7336
7812
|
const resolution = resolutionTier(width, height);
|
|
7337
7813
|
const problem = subtitleProblem(
|
|
7338
|
-
|
|
7814
|
+
row2.label,
|
|
7339
7815
|
tool,
|
|
7340
7816
|
req.subtitles,
|
|
7341
7817
|
resolution,
|
|
@@ -7347,9 +7823,9 @@ function planVideoTool(row, req) {
|
|
|
7347
7823
|
const formats = tool.outputFormats ?? ["h265"];
|
|
7348
7824
|
const format = req.outputFormat ?? formats[0] ?? "h265";
|
|
7349
7825
|
if (!formats.includes(format)) {
|
|
7350
|
-
return fail(`${
|
|
7826
|
+
return fail(`${row2.label} writes ${formats.join(" or ")}.`);
|
|
7351
7827
|
}
|
|
7352
|
-
const timing = renderedTiming(
|
|
7828
|
+
const timing = renderedTiming(row2, tool, durationSeconds, fps);
|
|
7353
7829
|
if (!timing.ok) return fail(timing.error);
|
|
7354
7830
|
const out = shrinkToShortEdge(width, height, tool.maxOutputShortEdge);
|
|
7355
7831
|
return {
|
|
@@ -7365,7 +7841,7 @@ function planVideoTool(row, req) {
|
|
|
7365
7841
|
};
|
|
7366
7842
|
}
|
|
7367
7843
|
var DEFAULT_FPS = 24;
|
|
7368
|
-
function renderedTiming(
|
|
7844
|
+
function renderedTiming(row2, tool, durationSeconds, fps) {
|
|
7369
7845
|
const { maxOutputFps, minOutputFrames, maxOutputFrames } = tool;
|
|
7370
7846
|
if (maxOutputFps === void 0 && minOutputFrames === void 0 && maxOutputFrames === void 0) {
|
|
7371
7847
|
return fps !== void 0 ? { ok: true, fps } : { ok: true };
|
|
@@ -7374,7 +7850,7 @@ function renderedTiming(row, tool, durationSeconds, fps) {
|
|
|
7374
7850
|
const frames = Math.max(minOutputFrames ?? 1, Math.round(durationSeconds * rate));
|
|
7375
7851
|
if (maxOutputFrames !== void 0 && frames > maxOutputFrames) {
|
|
7376
7852
|
const limit = `${maxOutputFrames} frames (${seconds(maxOutputFrames, rate)})`;
|
|
7377
|
-
return { ok: false, error: `${
|
|
7853
|
+
return { ok: false, error: `${row2.label} renders up to ${limit}.` };
|
|
7378
7854
|
}
|
|
7379
7855
|
return { ok: true, fps: rate, frames, durationSeconds: frames / rate };
|
|
7380
7856
|
}
|
|
@@ -7718,6 +8194,30 @@ function applyFalImageRules(model, req, callerSize, warnings) {
|
|
|
7718
8194
|
req.size = exact.tier;
|
|
7719
8195
|
}
|
|
7720
8196
|
|
|
8197
|
+
// src/replicate-video-kinds.ts
|
|
8198
|
+
function replicateBaseModelId(providerModelId) {
|
|
8199
|
+
const colon = providerModelId.indexOf(":");
|
|
8200
|
+
return colon === -1 ? providerModelId : providerModelId.slice(0, colon);
|
|
8201
|
+
}
|
|
8202
|
+
var REPLICATE_VIDEO_KINDS = /* @__PURE__ */ new Map([
|
|
8203
|
+
["kling-video/v2.5-turbo/pro/image-to-video", "kling"],
|
|
8204
|
+
["kling-video/v3.0/pro/image-to-video", "kling"],
|
|
8205
|
+
["kwaivgi/kling-v3-video", "kling"],
|
|
8206
|
+
["kwaivgi/kling-v3-omni-video", "kling-omni"],
|
|
8207
|
+
["minimax/hailuo-02", "hailuo"]
|
|
8208
|
+
]);
|
|
8209
|
+
function videoKind(providerModelId) {
|
|
8210
|
+
return REPLICATE_VIDEO_KINDS.get(replicateBaseModelId(providerModelId));
|
|
8211
|
+
}
|
|
8212
|
+
var KLING_TIERS = [
|
|
8213
|
+
{ mode: "standard", resolution: "720p" },
|
|
8214
|
+
{ mode: "pro", resolution: "1080p" },
|
|
8215
|
+
{ mode: "4k", resolution: "4k" }
|
|
8216
|
+
];
|
|
8217
|
+
function klingTier(req) {
|
|
8218
|
+
return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
|
|
8219
|
+
}
|
|
8220
|
+
|
|
7721
8221
|
// src/resolve-video-rules.ts
|
|
7722
8222
|
var MOTION_PRO = "fal-ai/kling-video/v3/pro/motion-control";
|
|
7723
8223
|
var MOTION_STANDARD = "fal-ai/kling-video/v3/standard/motion-control";
|
|
@@ -7891,6 +8391,16 @@ function h3EndFrameRatioWarning(model, ratio) {
|
|
|
7891
8391
|
message: `${model.id} follows the end frame's aspect ratio`
|
|
7892
8392
|
};
|
|
7893
8393
|
}
|
|
8394
|
+
function isReplicateKling(model) {
|
|
8395
|
+
if (model.adapter !== "replicate") return false;
|
|
8396
|
+
const kind = videoKind(model.providerModelId);
|
|
8397
|
+
return kind === "kling" || kind === "kling-omni";
|
|
8398
|
+
}
|
|
8399
|
+
function fillReplicateKlingResolution(model, req) {
|
|
8400
|
+
if (isReplicateKling(model) && req.resolution === void 0) {
|
|
8401
|
+
req.resolution = klingTier(req).resolution;
|
|
8402
|
+
}
|
|
8403
|
+
}
|
|
7894
8404
|
function applyFalVideoRules(model, req, callerRatio, warnings) {
|
|
7895
8405
|
if (model.adapter !== "fal") return;
|
|
7896
8406
|
const problem = falVideoProblem(model.providerModelId, withPromptForResolve(req));
|
|
@@ -8280,8 +8790,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
|
|
|
8280
8790
|
warnings
|
|
8281
8791
|
);
|
|
8282
8792
|
if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
|
|
8793
|
+
fillReplicateKlingResolution(model, merged);
|
|
8283
8794
|
const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
|
|
8284
8795
|
if (resolution !== void 0) merged.resolution = resolution;
|
|
8796
|
+
if (isReplicateKling(model)) delete merged.mode;
|
|
8285
8797
|
const duration = resolveDuration(
|
|
8286
8798
|
merged.durationSeconds,
|
|
8287
8799
|
c.durations,
|
|
@@ -8687,7 +9199,10 @@ var MEDIA_METHODS = {
|
|
|
8687
9199
|
lipsync: ["lipsync"],
|
|
8688
9200
|
dubbing: ["dub"],
|
|
8689
9201
|
transcription: ["transcribe"],
|
|
8690
|
-
"video-tool": ["submitVideoTool"]
|
|
9202
|
+
"video-tool": ["submitVideoTool"],
|
|
9203
|
+
// 3D jobs run through submitModel3d, which checks the row type itself; their preflight
|
|
9204
|
+
// is model3dInputRefusal, not resolveOptions.
|
|
9205
|
+
model3d: []
|
|
8691
9206
|
};
|
|
8692
9207
|
var METHOD_NOUN = {
|
|
8693
9208
|
generateImage: "an image model",
|
|
@@ -8801,6 +9316,8 @@ export {
|
|
|
8801
9316
|
IMAGE_MODELS,
|
|
8802
9317
|
MEDIA_METHODS,
|
|
8803
9318
|
MEDIA_NODE_MODELS,
|
|
9319
|
+
MODEL3D_IMAGE_SLOTS,
|
|
9320
|
+
MODEL3D_MODELS,
|
|
8804
9321
|
MODELS,
|
|
8805
9322
|
ModelKitError,
|
|
8806
9323
|
OTHER_MODELS,
|
|
@@ -8818,6 +9335,13 @@ export {
|
|
|
8818
9335
|
isModelKitError,
|
|
8819
9336
|
liveCatalog,
|
|
8820
9337
|
liveState,
|
|
9338
|
+
model3dConstraints,
|
|
9339
|
+
model3dInputRefusal,
|
|
9340
|
+
model3dPricingSku,
|
|
9341
|
+
model3dResolution,
|
|
9342
|
+
model3dSeedFits,
|
|
9343
|
+
model3dSkus,
|
|
9344
|
+
model3dTexture,
|
|
8821
9345
|
nearestAspectRatio,
|
|
8822
9346
|
normalizeExposure,
|
|
8823
9347
|
outputAudio,
|