@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/dist/index.js CHANGED
@@ -140,18 +140,18 @@ function normalizeExposure(value) {
140
140
  if (value.every(
141
141
  (entry) => SURFACES.includes(entry)
142
142
  )) {
143
- const present = new Set(value);
144
- return SURFACES.filter((surface) => present.has(surface));
143
+ const present2 = new Set(value);
144
+ return SURFACES.filter((surface) => present2.has(surface));
145
145
  }
146
146
  return value;
147
147
  }
148
148
  return value;
149
149
  }
150
- function isListedOn(row, surface) {
151
- return row.lifecycle === "active" && row.exposure.includes(surface);
150
+ function isListedOn(row2, surface) {
151
+ return row2.lifecycle === "active" && row2.exposure.includes(surface);
152
152
  }
153
- function isListed(row) {
154
- return row.lifecycle === "active" && row.exposure.length > 0;
153
+ function isListed(row2) {
154
+ return row2.lifecycle === "active" && row2.exposure.length > 0;
155
155
  }
156
156
 
157
157
  // src/catalog/image-fal.ts
@@ -3553,6 +3553,197 @@ var MEDIA_NODE_MODELS = [
3553
3553
  SAM_3_IMAGE
3554
3554
  ];
3555
3555
 
3556
+ // src/catalog/model3d.ts
3557
+ var REQUEST_USAGE = { unit: "requests" };
3558
+ function row(id, label, spec, display) {
3559
+ return {
3560
+ id,
3561
+ aliases: [],
3562
+ label,
3563
+ type: "model3d",
3564
+ adapter: "fal",
3565
+ // The single-image endpoint; the adapter picks the endpoint a request needs.
3566
+ providerModelId: spec.endpoints.image ?? id,
3567
+ lifecycle: "active",
3568
+ exposure: ["space_builder"],
3569
+ constraints: { supports: [], model3d: spec },
3570
+ defaults: {},
3571
+ usage: REQUEST_USAGE,
3572
+ pricingKind: "flat",
3573
+ display
3574
+ };
3575
+ }
3576
+ var MODEL3D_MODELS = [
3577
+ row(
3578
+ "trellis-2",
3579
+ "Trellis 2",
3580
+ {
3581
+ family: "trellis",
3582
+ endpoints: { image: "fal-ai/trellis-2" },
3583
+ text: false,
3584
+ imageRequired: true,
3585
+ views: "none",
3586
+ maxImages: 1,
3587
+ texture: [],
3588
+ pbr: false,
3589
+ textureRef: false,
3590
+ seed: true,
3591
+ resolutions: { label: "Resolution", options: ["512", "1024", "1536"], default: "1024" }
3592
+ },
3593
+ {
3594
+ provider: "microsoft",
3595
+ description: "One photo to a detailed textured model. Fast and the best value.",
3596
+ sortOrder: 70
3597
+ }
3598
+ ),
3599
+ row(
3600
+ "hunyuan3d-3.1-pro",
3601
+ "Hunyuan3D 3.1 Pro",
3602
+ {
3603
+ family: "hunyuan",
3604
+ endpoints: {
3605
+ text: "fal-ai/hunyuan-3d/v3.1/pro/text-to-3d",
3606
+ image: "fal-ai/hunyuan-3d/v3.1/pro/image-to-3d"
3607
+ },
3608
+ text: true,
3609
+ imageRequired: false,
3610
+ views: "named",
3611
+ maxImages: 4,
3612
+ texture: ["none", "standard"],
3613
+ pbr: true,
3614
+ textureRef: false,
3615
+ seed: false
3616
+ },
3617
+ {
3618
+ provider: "tencent",
3619
+ description: "Photo-faithful models from a prompt, a photo, or a photo with back and side views.",
3620
+ sortOrder: 60
3621
+ }
3622
+ ),
3623
+ row(
3624
+ "tripo-h3.1",
3625
+ "Tripo H3.1",
3626
+ {
3627
+ family: "tripo",
3628
+ endpoints: {
3629
+ text: "tripo3d/h3.1/text-to-3d",
3630
+ image: "tripo3d/h3.1/image-to-3d",
3631
+ multiImage: "tripo3d/h3.1/multiview-to-3d"
3632
+ },
3633
+ text: true,
3634
+ imageRequired: false,
3635
+ views: "ordered",
3636
+ maxImages: 4,
3637
+ texture: ["none", "standard", "detailed"],
3638
+ pbr: true,
3639
+ textureRef: false,
3640
+ seed: true
3641
+ },
3642
+ {
3643
+ provider: "tripo",
3644
+ description: "Clean, game-ready models from a prompt, a photo or four views.",
3645
+ sortOrder: 50
3646
+ }
3647
+ ),
3648
+ row(
3649
+ "rodin-gen-2.5",
3650
+ "Rodin Gen-2.5",
3651
+ {
3652
+ family: "rodin",
3653
+ endpoints: {
3654
+ text: "fal-ai/hyper3d/rodin/v2.5/text-to-3d",
3655
+ image: "fal-ai/hyper3d/rodin/v2.5"
3656
+ },
3657
+ text: true,
3658
+ imageRequired: false,
3659
+ views: "unordered",
3660
+ maxImages: 5,
3661
+ texture: [],
3662
+ pbr: false,
3663
+ textureRef: false,
3664
+ seed: true,
3665
+ seedMax: 65535
3666
+ },
3667
+ {
3668
+ provider: "hyper3d",
3669
+ description: "Detailed PBR models from a prompt or up to five photos.",
3670
+ sortOrder: 40
3671
+ }
3672
+ ),
3673
+ row(
3674
+ "meshy-7.1",
3675
+ "Meshy 7.1",
3676
+ {
3677
+ family: "meshy",
3678
+ endpoints: {
3679
+ text: "meshy/v7.1/text-to-3d",
3680
+ image: "meshy/v7.1/image-to-3d",
3681
+ multiImage: "meshy/v7.1/multi-image-to-3d"
3682
+ },
3683
+ text: true,
3684
+ imageRequired: false,
3685
+ views: "unordered",
3686
+ maxImages: 4,
3687
+ texture: ["none", "standard"],
3688
+ pbr: true,
3689
+ textureRef: true,
3690
+ seed: true
3691
+ },
3692
+ {
3693
+ provider: "meshy",
3694
+ description: "Models from a prompt or photos, with a texture prompt or texture image to restyle.",
3695
+ sortOrder: 30
3696
+ }
3697
+ ),
3698
+ row(
3699
+ "hi3d-3.0",
3700
+ "Hi3D 3.0",
3701
+ {
3702
+ family: "hi3d",
3703
+ endpoints: {
3704
+ image: "hitem3d/hi3d/v3.0/image-to-3d",
3705
+ multiImage: "hitem3d/hi3d/v3.0/multi-view-to-3d"
3706
+ },
3707
+ text: false,
3708
+ imageRequired: true,
3709
+ views: "named",
3710
+ maxImages: 4,
3711
+ texture: ["none", "standard"],
3712
+ pbr: true,
3713
+ textureRef: false,
3714
+ seed: false,
3715
+ resolutions: { label: "Quality", options: ["quality", "master"], default: "quality" }
3716
+ },
3717
+ {
3718
+ provider: "hitem3d",
3719
+ description: "Highest-fidelity product models from a photo or four views. Slowest.",
3720
+ sortOrder: 20
3721
+ }
3722
+ ),
3723
+ row(
3724
+ "sam-3d-objects",
3725
+ "SAM 3D Objects",
3726
+ {
3727
+ family: "sam",
3728
+ endpoints: { image: "fal-ai/sam-3/3d-objects" },
3729
+ text: true,
3730
+ imageRequired: true,
3731
+ promptRequired: true,
3732
+ views: "none",
3733
+ maxImages: 1,
3734
+ texture: [],
3735
+ pbr: false,
3736
+ textureRef: false,
3737
+ seed: true
3738
+ },
3739
+ {
3740
+ provider: "meta",
3741
+ description: "Lifts one named object out of a real photo into a 3D model.",
3742
+ sortOrder: 10
3743
+ }
3744
+ )
3745
+ ];
3746
+
3556
3747
  // src/catalog/other.ts
3557
3748
  var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
3558
3749
  var ELEVENLABS_LOGO2 = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/elevenlabs.png";
@@ -5871,6 +6062,7 @@ var MODELS = [
5871
6062
  ...IMAGE_MODELS,
5872
6063
  ...VIDEO_MODELS,
5873
6064
  ...VIDEO_TOOL_MODELS,
6065
+ ...MODEL3D_MODELS,
5874
6066
  ...OTHER_MODELS,
5875
6067
  ...MEDIA_NODE_MODELS
5876
6068
  ];
@@ -5879,11 +6071,11 @@ var MODELS = [
5879
6071
  import { z as z3 } from "zod";
5880
6072
 
5881
6073
  // src/resolve-provider-rules.ts
5882
- function ruleRefusal(row, message, code) {
6074
+ function ruleRefusal(row2, message, code) {
5883
6075
  return new ModelKitError({
5884
6076
  code,
5885
- message: `${row.label}: ${message}`,
5886
- model: row.id,
6077
+ message: `${row2.label}: ${message}`,
6078
+ model: row2.id,
5887
6079
  retryable: false
5888
6080
  });
5889
6081
  }
@@ -6042,27 +6234,27 @@ function collisionIssues(rows) {
6042
6234
  const issues = [];
6043
6235
  const seenIds = /* @__PURE__ */ new Map();
6044
6236
  const seenAliases = /* @__PURE__ */ new Map();
6045
- rows.forEach((row, index) => {
6046
- if (seenIds.has(row.id)) {
6237
+ rows.forEach((row2, index) => {
6238
+ if (seenIds.has(row2.id)) {
6047
6239
  issues.push({
6048
6240
  index,
6049
6241
  path: ["id"],
6050
- message: `Duplicate model id "${row.id}"`
6242
+ message: `Duplicate model id "${row2.id}"`
6051
6243
  });
6052
6244
  } else {
6053
- const aliasOwner = seenAliases.get(row.id);
6245
+ const aliasOwner = seenAliases.get(row2.id);
6054
6246
  if (aliasOwner !== void 0) {
6055
6247
  issues.push({
6056
6248
  index: aliasOwner.index,
6057
6249
  path: ["aliases", aliasOwner.aliasIndex],
6058
- message: `Alias "${row.id}" collides with a model id`
6250
+ message: `Alias "${row2.id}" collides with a model id`
6059
6251
  });
6060
6252
  }
6061
- seenIds.set(row.id, index);
6253
+ seenIds.set(row2.id, index);
6062
6254
  }
6063
6255
  const local = /* @__PURE__ */ new Set();
6064
- for (const [aliasIndex, alias] of row.aliases.entries()) {
6065
- if (alias === row.id || seenIds.has(alias)) {
6256
+ for (const [aliasIndex, alias] of row2.aliases.entries()) {
6257
+ if (alias === row2.id || seenIds.has(alias)) {
6066
6258
  issues.push({
6067
6259
  index,
6068
6260
  path: ["aliases", aliasIndex],
@@ -6104,8 +6296,8 @@ var DEFAULT_CONVENTIONS = { referenceSyntax: "numbered" };
6104
6296
  var DefaultsReadView = z.looseObject({
6105
6297
  generateAudio: z.boolean().optional().catch(void 0)
6106
6298
  });
6107
- function promptConventions(row) {
6108
- const view = ConstraintsReadView.safeParse(row.constraints);
6299
+ function promptConventions(row2) {
6300
+ const view = ConstraintsReadView.safeParse(row2.constraints);
6109
6301
  const prompt = view.success ? view.data.prompt : void 0;
6110
6302
  if (prompt === void 0) return { ...DEFAULT_CONVENTIONS };
6111
6303
  const result = { referenceSyntax: prompt.referenceSyntax };
@@ -6116,22 +6308,111 @@ var RawConventionsView = z.looseObject({
6116
6308
  audio: z.unknown().optional(),
6117
6309
  prompt: z.unknown().optional()
6118
6310
  });
6119
- function normaliseConventions(row) {
6120
- const view = RawConventionsView.safeParse(row.constraints);
6121
- if (!view.success) return { row, invalidKeys: [] };
6311
+ function normaliseConventions(row2) {
6312
+ const view = RawConventionsView.safeParse(row2.constraints);
6313
+ if (!view.success) return { row: row2, invalidKeys: [] };
6122
6314
  const { audio, prompt } = view.data;
6123
6315
  const badAudio = audio !== void 0 && !AudioOutputSchema.safeParse(audio).success;
6124
6316
  const badPrompt = prompt !== void 0 && !PromptConventionsSchema.safeParse(prompt).success;
6125
- if (!badAudio && !badPrompt) return { row, invalidKeys: [] };
6317
+ if (!badAudio && !badPrompt) return { row: row2, invalidKeys: [] };
6126
6318
  const invalidKeys = [];
6127
6319
  if (badAudio) invalidKeys.push("constraints.audio");
6128
6320
  if (badPrompt) invalidKeys.push("constraints.prompt");
6129
- const entries = Object.entries(row.constraints).flatMap(([key, value]) => {
6321
+ const entries = Object.entries(row2.constraints).flatMap(([key, value]) => {
6130
6322
  if (key === "audio" && badAudio) return [];
6131
- if (key === "prompt" && badPrompt) return [[key, promptConventions(row)]];
6323
+ if (key === "prompt" && badPrompt) return [[key, promptConventions(row2)]];
6132
6324
  return [[key, value]];
6133
6325
  });
6134
- return { row: { ...row, constraints: Object.fromEntries(entries) }, invalidKeys };
6326
+ return { row: { ...row2, constraints: Object.fromEntries(entries) }, invalidKeys };
6327
+ }
6328
+
6329
+ // src/catalog/model3d-spec.ts
6330
+ function model3dConstraints(row2) {
6331
+ if (row2.type !== "model3d") return void 0;
6332
+ return row2.constraints.model3d;
6333
+ }
6334
+ var MODEL3D_IMAGE_SLOTS = {
6335
+ none: ["image"],
6336
+ named: ["image", "back", "left", "right"],
6337
+ ordered: ["image", "left", "back", "right"],
6338
+ unordered: ["image", "back", "left", "right", "top"]
6339
+ };
6340
+ function model3dInputRefusal(spec, wired) {
6341
+ const top = spec.views === "unordered" && wired.top === true;
6342
+ const anyView = spec.views !== "none" && (wired.back || wired.left || wired.right || top);
6343
+ if (anyView && !wired.image) return "model3d_views_need_image";
6344
+ if (spec.imageRequired && !wired.image) return "model3d_needs_image";
6345
+ if (spec.promptRequired && !wired.prompt) return "model3d_needs_prompt";
6346
+ if (!wired.image && !(spec.text && wired.prompt)) return "model3d_needs_input";
6347
+ if (spec.views === "ordered") {
6348
+ if ((wired.back || wired.right) && !wired.left) return "model3d_views_out_of_order";
6349
+ if (wired.right && !wired.back) return "model3d_views_out_of_order";
6350
+ }
6351
+ return null;
6352
+ }
6353
+ function model3dSeedFits(spec, seed) {
6354
+ return Number.isSafeInteger(seed) && seed >= 0 && seed <= (spec.seedMax ?? Number.MAX_SAFE_INTEGER);
6355
+ }
6356
+ function model3dTexture(spec, requested) {
6357
+ if (requested !== void 0 && spec.texture.includes(requested)) return requested;
6358
+ return spec.texture.includes("standard") ? "standard" : spec.texture[0] ?? "standard";
6359
+ }
6360
+ function model3dResolution(spec, requested) {
6361
+ const res = spec.resolutions;
6362
+ if (res === void 0) return void 0;
6363
+ return requested !== void 0 && res.options.includes(requested) ? requested : res.default;
6364
+ }
6365
+ function model3dPricingSku(row2, options, inputs) {
6366
+ const spec = model3dConstraints(row2);
6367
+ if (spec === void 0) throw new Error(`${row2.id} is not a 3D model`);
6368
+ const texture = model3dTexture(spec, options.texture);
6369
+ const textured = spec.texture.length > 0 && texture !== "none";
6370
+ const pbr = spec.pbr && textured && options.pbr === true;
6371
+ const resolution = model3dResolution(spec, options.resolution);
6372
+ switch (spec.family) {
6373
+ case "meshy":
6374
+ return `${row2.id}__${textured ? "textured" : "untextured"}`;
6375
+ case "tripo":
6376
+ return `${row2.id}__${inputs.image ? "image" : "text"}__${texture}`;
6377
+ case "hunyuan":
6378
+ return `${row2.id}${pbr ? "__pbr" : ""}${inputs.views ? "__views" : ""}`;
6379
+ case "trellis":
6380
+ return `${row2.id}__${resolution}`;
6381
+ case "hi3d":
6382
+ return `${row2.id}__${resolution}__${textured ? pbr ? "texture-pbr" : "texture" : "geometry"}`;
6383
+ case "rodin":
6384
+ case "sam":
6385
+ return row2.id;
6386
+ }
6387
+ }
6388
+ function model3dSkus(row2) {
6389
+ const spec = model3dConstraints(row2);
6390
+ if (spec === void 0) return [];
6391
+ const textures = spec.texture.length > 0 ? spec.texture : [void 0];
6392
+ const pbrs = spec.pbr ? [false, true] : [false];
6393
+ const resolutions = spec.resolutions?.options ?? [void 0];
6394
+ const images = spec.text && !spec.imageRequired ? [true, false] : [true];
6395
+ const views = spec.views === "none" ? [false] : [false, true];
6396
+ const skus = /* @__PURE__ */ new Set();
6397
+ for (const texture of textures)
6398
+ for (const pbr of pbrs)
6399
+ for (const resolution of resolutions)
6400
+ for (const image of images)
6401
+ for (const view of views) {
6402
+ if (view && !image) continue;
6403
+ skus.add(
6404
+ model3dPricingSku(
6405
+ row2,
6406
+ {
6407
+ ...texture !== void 0 && { texture },
6408
+ pbr,
6409
+ ...resolution !== void 0 && { resolution }
6410
+ },
6411
+ { image, views: view }
6412
+ )
6413
+ );
6414
+ }
6415
+ return [...skus].sort();
6135
6416
  }
6136
6417
 
6137
6418
  // src/catalog/input-spec.ts
@@ -6282,7 +6563,7 @@ function isInputSpecKey(key) {
6282
6563
  function isArrayInputSpecKey(key) {
6283
6564
  return ARRAY_KEY_SET.has(key);
6284
6565
  }
6285
- function validateInputSpec(raw, row) {
6566
+ function validateInputSpec(raw, row2) {
6286
6567
  const parsed = InputSpecSchema.safeParse(raw);
6287
6568
  if (!parsed.success) {
6288
6569
  return {
@@ -6294,7 +6575,7 @@ function validateInputSpec(raw, row) {
6294
6575
  };
6295
6576
  }
6296
6577
  const spec = parsed.data;
6297
- const supportedTypes = TYPES_BY_ADAPTER.get(row.adapter);
6578
+ const supportedTypes = TYPES_BY_ADAPTER.get(row2.adapter);
6298
6579
  if (supportedTypes === void 0) {
6299
6580
  return {
6300
6581
  ok: false,
@@ -6307,18 +6588,18 @@ function validateInputSpec(raw, row) {
6307
6588
  };
6308
6589
  }
6309
6590
  const issues = [];
6310
- const allowed = ALLOWED_KEYS_BY_TYPE.get(row.type);
6311
- if (allowed === void 0 || !supportedTypes.includes(row.type)) {
6591
+ const allowed = ALLOWED_KEYS_BY_TYPE.get(row2.type);
6592
+ if (allowed === void 0 || !supportedTypes.includes(row2.type)) {
6312
6593
  issues.push({
6313
6594
  path: [],
6314
- message: row.adapter === "fal" ? `inputSpec on fal rows is only supported for image rows, not "${row.type}"` : `inputSpec is not supported for "${row.type}" rows`
6595
+ 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`
6315
6596
  });
6316
6597
  } else {
6317
6598
  for (const key of Object.keys(spec.fields)) {
6318
6599
  if (!allowed.has(key)) {
6319
6600
  issues.push({
6320
6601
  path: ["fields", key],
6321
- message: `inputSpec.fields "${key}" is not supported for ${row.type} rows`
6602
+ message: `inputSpec.fields "${key}" is not supported for ${row2.type} rows`
6322
6603
  });
6323
6604
  }
6324
6605
  }
@@ -6326,13 +6607,13 @@ function validateInputSpec(raw, row) {
6326
6607
  if (!allowed.has(key)) {
6327
6608
  issues.push({
6328
6609
  path: ["values", key],
6329
- message: `inputSpec.values "${key}" is not supported for ${row.type} rows`
6610
+ message: `inputSpec.values "${key}" is not supported for ${row2.type} rows`
6330
6611
  });
6331
6612
  }
6332
6613
  }
6333
6614
  }
6334
6615
  if (spec.editEndpoint !== void 0) {
6335
- if (row.adapter !== "fal") {
6616
+ if (row2.adapter !== "fal") {
6336
6617
  issues.push({
6337
6618
  path: ["editEndpoint"],
6338
6619
  message: "inputSpec.editEndpoint is only supported on fal rows"
@@ -6376,7 +6657,7 @@ function validateInputSpec(raw, row) {
6376
6657
  if (allowed !== void 0 && !allowed.has(key)) {
6377
6658
  issues.push({
6378
6659
  path: ["arrays", name],
6379
- message: `inputSpec.arrays "${key}" is not supported for ${row.type} rows`
6660
+ message: `inputSpec.arrays "${key}" is not supported for ${row2.type} rows`
6380
6661
  });
6381
6662
  }
6382
6663
  if (key in spec.fields) {
@@ -6396,7 +6677,7 @@ function validateInputSpec(raw, row) {
6396
6677
  }
6397
6678
  }
6398
6679
  if (spec.dimensions !== void 0) {
6399
- if (row.type !== "image") {
6680
+ if (row2.type !== "image") {
6400
6681
  issues.push({
6401
6682
  path: ["dimensions"],
6402
6683
  message: "inputSpec.dimensions is only supported on image rows"
@@ -6418,7 +6699,7 @@ function validateInputSpec(raw, row) {
6418
6699
  });
6419
6700
  }
6420
6701
  }
6421
- const supports = row.constraints.supports ?? [];
6702
+ const supports = row2.constraints.supports ?? [];
6422
6703
  for (const key of INPUT_SPEC_SUPPORTS_KEYS) {
6423
6704
  if (supports.includes(key)) continue;
6424
6705
  if (key in spec.fields) {
@@ -6463,8 +6744,8 @@ function listIssues(name, values, fallback, defaultKey) {
6463
6744
  }
6464
6745
  return issues;
6465
6746
  }
6466
- function optionListIssues(row) {
6467
- const { constraints, defaults } = row;
6747
+ function optionListIssues(row2) {
6748
+ const { constraints, defaults } = row2;
6468
6749
  const issues = [
6469
6750
  ...listIssues(
6470
6751
  "voices",
@@ -6522,7 +6803,8 @@ var ModelTypeSchema = z3.enum([
6522
6803
  "voice-change",
6523
6804
  "dubbing",
6524
6805
  "lipsync",
6525
- "transcription"
6806
+ "transcription",
6807
+ "model3d"
6526
6808
  ]);
6527
6809
  var LifecycleSchema = z3.enum(["active", "deprecated", "retired"]);
6528
6810
  var SurfaceSchema = z3.enum(["cowork", "space_builder"]);
@@ -6586,7 +6868,8 @@ var UsageUnitSchema = z3.enum([
6586
6868
  "images",
6587
6869
  "seconds",
6588
6870
  "reported_cost_usd",
6589
- "compute_seconds"
6871
+ "compute_seconds",
6872
+ "requests"
6590
6873
  ]);
6591
6874
  var PricingKindSchema = z3.enum(["token", "image_size", "video_per_second", "flat"]);
6592
6875
  var ProviderOptionValueSchema = z3.lazy(
@@ -6640,6 +6923,156 @@ var LanguageOptionSchema = z3.looseObject({
6640
6923
  code: z3.string().min(1),
6641
6924
  name: z3.string().min(1)
6642
6925
  });
6926
+ var MODEL3D_FAMILY_RULES = {
6927
+ trellis: {
6928
+ textPath: false,
6929
+ views: ["none"],
6930
+ multiImage: false,
6931
+ texture: null,
6932
+ pbr: false,
6933
+ seed: true,
6934
+ textureRef: false,
6935
+ resolutions: "integer"
6936
+ },
6937
+ hunyuan: {
6938
+ textPath: true,
6939
+ views: ["none", "named"],
6940
+ multiImage: false,
6941
+ texture: ["none", "standard"],
6942
+ pbr: true,
6943
+ seed: false,
6944
+ textureRef: false,
6945
+ resolutions: null
6946
+ },
6947
+ tripo: {
6948
+ textPath: true,
6949
+ views: ["none", "ordered"],
6950
+ multiImage: true,
6951
+ texture: ["none", "standard", "detailed"],
6952
+ pbr: true,
6953
+ seed: true,
6954
+ textureRef: false,
6955
+ resolutions: null
6956
+ },
6957
+ rodin: {
6958
+ textPath: true,
6959
+ views: ["none", "unordered"],
6960
+ multiImage: false,
6961
+ texture: null,
6962
+ pbr: false,
6963
+ seed: true,
6964
+ textureRef: false,
6965
+ resolutions: null
6966
+ },
6967
+ meshy: {
6968
+ textPath: true,
6969
+ views: ["none", "unordered"],
6970
+ multiImage: true,
6971
+ texture: ["none", "standard"],
6972
+ pbr: true,
6973
+ seed: true,
6974
+ textureRef: true,
6975
+ resolutions: null
6976
+ },
6977
+ hi3d: {
6978
+ textPath: false,
6979
+ views: ["none", "named"],
6980
+ multiImage: true,
6981
+ texture: ["none", "standard"],
6982
+ pbr: true,
6983
+ seed: false,
6984
+ textureRef: false,
6985
+ resolutions: ["quality", "master"]
6986
+ },
6987
+ sam: {
6988
+ textPath: false,
6989
+ views: ["none"],
6990
+ multiImage: false,
6991
+ texture: null,
6992
+ pbr: false,
6993
+ seed: true,
6994
+ textureRef: false,
6995
+ resolutions: null
6996
+ }
6997
+ };
6998
+ function model3dSpecIssues(spec) {
6999
+ const issues = [];
7000
+ const add = (path, message) => issues.push({ path, message });
7001
+ const rules = MODEL3D_FAMILY_RULES[spec.family];
7002
+ const promptOnly = spec.text && !spec.imageRequired;
7003
+ if (spec.endpoints.image === void 0)
7004
+ add(["endpoints", "image"], "every row needs an image endpoint");
7005
+ if (promptOnly && !rules.textPath) {
7006
+ add(
7007
+ ["imageRequired"],
7008
+ `${spec.family} has no text-to-3D endpoint; a text row needs an image`
7009
+ );
7010
+ }
7011
+ if (promptOnly && spec.endpoints.text === void 0) {
7012
+ add(["endpoints", "text"], "a text row needs a text endpoint");
7013
+ }
7014
+ if (!rules.views.includes(spec.views)) {
7015
+ add(["views"], `${spec.family} takes views ${rules.views.join(" or ")}`);
7016
+ }
7017
+ if (spec.views === "none" && spec.maxImages !== 1) {
7018
+ add(["maxImages"], "a row without views takes 1 image");
7019
+ }
7020
+ if (spec.views === "unordered" && spec.maxImages < 2) {
7021
+ add(["maxImages"], "a row with views takes at least 2 images");
7022
+ }
7023
+ const slots = MODEL3D_IMAGE_SLOTS[spec.views].length;
7024
+ if (spec.views !== "none" && spec.maxImages > slots) {
7025
+ add(["maxImages"], `a row with ${spec.views} views sends at most ${slots} images`);
7026
+ }
7027
+ if ((spec.views === "named" || spec.views === "ordered") && spec.maxImages < slots) {
7028
+ add(
7029
+ ["maxImages"],
7030
+ `a row with ${spec.views} views takes ${slots} images (front and three sides)`
7031
+ );
7032
+ }
7033
+ if (spec.views !== "none" && rules.multiImage && spec.endpoints.multiImage === void 0) {
7034
+ add(["endpoints", "multiImage"], `${spec.family} sends views to a multi-image endpoint`);
7035
+ }
7036
+ if (rules.texture === null) {
7037
+ if (spec.texture.length > 0) add(["texture"], `${spec.family} has no texture switch`);
7038
+ } else {
7039
+ const allowed = rules.texture;
7040
+ if (spec.texture.length === 0) add(["texture"], `${spec.family} needs its texture options`);
7041
+ if (new Set(spec.texture).size !== spec.texture.length)
7042
+ add(["texture"], "texture options repeat");
7043
+ for (const t of spec.texture) {
7044
+ if (!allowed.includes(t)) add(["texture"], `${spec.family} has no "${t}" texture`);
7045
+ }
7046
+ }
7047
+ if (spec.pbr && !rules.pbr) add(["pbr"], `${spec.family} has no PBR switch`);
7048
+ if (spec.pbr && !spec.texture.some((t) => t !== "none")) {
7049
+ add(["pbr"], "PBR needs a textured option");
7050
+ }
7051
+ if (spec.seed && !rules.seed) add(["seed"], `${spec.family} takes no seed`);
7052
+ if (spec.seedMax !== void 0 && !spec.seed) add(["seedMax"], "seedMax needs seed");
7053
+ if (spec.textureRef && !rules.textureRef)
7054
+ add(["textureRef"], `${spec.family} takes no texture reference`);
7055
+ const res = spec.resolutions;
7056
+ if (rules.resolutions === null) {
7057
+ if (res !== void 0) add(["resolutions"], `${spec.family} has no resolution option`);
7058
+ } else if (res === void 0) {
7059
+ add(["resolutions"], `${spec.family} needs its resolution options`);
7060
+ } else {
7061
+ if (!res.options.includes(res.default)) {
7062
+ add(["resolutions", "default"], "default must be an option");
7063
+ }
7064
+ if (new Set(res.options).size !== res.options.length) {
7065
+ add(["resolutions", "options"], "resolution options repeat");
7066
+ }
7067
+ const allowed = rules.resolutions;
7068
+ for (const option of res.options) {
7069
+ const ok = allowed === "integer" ? /^[1-9][0-9]*$/.test(option) : allowed.includes(option);
7070
+ if (!ok)
7071
+ add(["resolutions", "options"], `${spec.family} has no "${option}" resolution`);
7072
+ }
7073
+ }
7074
+ return issues;
7075
+ }
6643
7076
  var VideoToolConstraintsSchema = z3.looseObject({
6644
7077
  kind: z3.enum(["upscale", "interpolate", "hdr", "bg-remove", "subtitles"]),
6645
7078
  upscaleFactor: RangeSchema.optional(),
@@ -6656,6 +7089,30 @@ var VideoToolConstraintsSchema = z3.looseObject({
6656
7089
  translationLanguages: z3.array(z3.string().min(1)).min(1).optional(),
6657
7090
  maxSecondsAbove1080p: z3.number().positive().optional()
6658
7091
  });
7092
+ var Model3dTextureSchema = z3.enum(["none", "standard", "detailed"]);
7093
+ var Model3dConstraintsSchema = z3.looseObject({
7094
+ family: z3.enum(["trellis", "hunyuan", "tripo", "rodin", "meshy", "hi3d", "sam"]),
7095
+ endpoints: z3.looseObject({
7096
+ text: z3.string().min(1).optional(),
7097
+ image: z3.string().min(1).optional(),
7098
+ multiImage: z3.string().min(1).optional()
7099
+ }),
7100
+ text: z3.boolean(),
7101
+ imageRequired: z3.boolean(),
7102
+ promptRequired: z3.boolean().optional(),
7103
+ views: z3.enum(["none", "unordered", "ordered", "named"]),
7104
+ maxImages: z3.number().int().positive(),
7105
+ texture: z3.array(Model3dTextureSchema),
7106
+ pbr: z3.boolean(),
7107
+ textureRef: z3.boolean(),
7108
+ seed: z3.boolean(),
7109
+ seedMax: z3.number().int().positive().optional(),
7110
+ resolutions: z3.looseObject({
7111
+ label: z3.string().min(1),
7112
+ options: z3.array(z3.string().min(1)).min(1),
7113
+ default: z3.string().min(1)
7114
+ }).optional()
7115
+ });
6659
7116
  var ModelConstraintsSchema = z3.looseObject({
6660
7117
  aspectRatios: z3.array(AspectRatioSchema).optional(),
6661
7118
  sizes: z3.array(ImageSizeSchema).optional(),
@@ -6683,6 +7140,7 @@ var ModelConstraintsSchema = z3.looseObject({
6683
7140
  returns: z3.enum(["new", "joined"]).optional()
6684
7141
  }).optional(),
6685
7142
  tool: VideoToolConstraintsSchema.optional(),
7143
+ model3d: Model3dConstraintsSchema.optional(),
6686
7144
  // Loose on purpose: the read path keeps a row whose value is invalid (the accessors in
6687
7145
  // conventions.ts read it as "not set"); CatalogModelSchema below rejects it on write.
6688
7146
  audio: z3.unknown().optional(),
@@ -6798,29 +7256,47 @@ var CatalogModelSchemaBase = z3.looseObject({
6798
7256
  pricingKind: PricingKindSchema,
6799
7257
  display: CatalogDisplaySchema.optional(),
6800
7258
  capabilities: CatalogCapabilitiesSchema.optional()
6801
- }).superRefine((row, ctx) => {
6802
- if (row.lifecycle === "active" && !row.display) {
7259
+ }).superRefine((row2, ctx) => {
7260
+ if (row2.lifecycle === "active" && !row2.display) {
6803
7261
  ctx.addIssue({
6804
7262
  code: "custom",
6805
7263
  path: ["display"],
6806
7264
  message: "active rows need display"
6807
7265
  });
6808
7266
  }
6809
- if (row.lifecycle === "active" && row.type === "text" && !row.capabilities?.contextWindow) {
7267
+ if (row2.lifecycle === "active" && row2.type === "text" && !row2.capabilities?.contextWindow) {
6810
7268
  ctx.addIssue({
6811
7269
  code: "custom",
6812
7270
  path: ["capabilities", "contextWindow"],
6813
7271
  message: "active text rows need contextWindow"
6814
7272
  });
6815
7273
  }
6816
- if (row.type === "video-tool" && row.constraints.tool === void 0) {
7274
+ if (row2.type === "video-tool" && row2.constraints.tool === void 0) {
6817
7275
  ctx.addIssue({
6818
7276
  code: "custom",
6819
7277
  path: ["constraints", "tool"],
6820
7278
  message: "video-tool rows need constraints.tool"
6821
7279
  });
6822
7280
  }
6823
- if (row.replacedBy !== void 0 && row.replacedBy === row.id) {
7281
+ if (row2.type === "model3d") {
7282
+ const spec = row2.constraints.model3d;
7283
+ if (spec === void 0) {
7284
+ ctx.addIssue({
7285
+ code: "custom",
7286
+ path: ["constraints", "model3d"],
7287
+ message: "model3d rows need constraints.model3d"
7288
+ });
7289
+ } else {
7290
+ for (const issue of model3dSpecIssues(spec)) {
7291
+ ctx.addIssue({
7292
+ code: "custom",
7293
+ path: ["constraints", "model3d", ...issue.path],
7294
+ message: issue.message
7295
+ });
7296
+ }
7297
+ }
7298
+ }
7299
+ if (row2.replacedBy !== void 0 && row2.replacedBy === row2.id) {
6824
7300
  ctx.addIssue({
6825
7301
  code: "custom",
6826
7302
  path: ["replacedBy"],
@@ -6829,8 +7305,8 @@ var CatalogModelSchemaBase = z3.looseObject({
6829
7305
  }
6830
7306
  });
6831
7307
  var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6832
- (row, ctx) => {
6833
- const transport = row.providerOptions?.["modelkit"]?.["transport"];
7308
+ (row2, ctx) => {
7309
+ const transport = row2.providerOptions?.["modelkit"]?.["transport"];
6834
7310
  if (transport !== void 0 && transport !== "direct" && transport !== "bedrock") {
6835
7311
  ctx.addIssue({
6836
7312
  code: "custom",
@@ -6838,9 +7314,9 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6838
7314
  message: 'transport must be "direct" or "bedrock"'
6839
7315
  });
6840
7316
  }
6841
- const inputSpecRaw = row.providerOptions?.["modelkit"]?.["inputSpec"];
7317
+ const inputSpecRaw = row2.providerOptions?.["modelkit"]?.["inputSpec"];
6842
7318
  if (inputSpecRaw !== void 0) {
6843
- const result = validateInputSpec(inputSpecRaw, row);
7319
+ const result = validateInputSpec(inputSpecRaw, row2);
6844
7320
  if (!result.ok) {
6845
7321
  for (const issue of result.issues) {
6846
7322
  ctx.addIssue({
@@ -6851,7 +7327,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6851
7327
  }
6852
7328
  }
6853
7329
  }
6854
- const audio = row.constraints.audio;
7330
+ const audio = row2.constraints.audio;
6855
7331
  if (audio !== void 0 && !AudioOutputSchema.safeParse(audio).success) {
6856
7332
  ctx.addIssue({
6857
7333
  code: "custom",
@@ -6859,7 +7335,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6859
7335
  message: 'audio must be "always", "optional" or "never"'
6860
7336
  });
6861
7337
  }
6862
- const refs = row.constraints.references;
7338
+ const refs = row2.constraints.references;
6863
7339
  for (const kind of ["images", "videos", "audios"]) {
6864
7340
  const least = refs?.min?.[kind];
6865
7341
  const most = refs?.[kind];
@@ -6871,10 +7347,10 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6871
7347
  });
6872
7348
  }
6873
7349
  }
6874
- for (const issue of optionListIssues(row)) {
7350
+ for (const issue of optionListIssues(row2)) {
6875
7351
  ctx.addIssue({ code: "custom", path: issue.path, message: issue.message });
6876
7352
  }
6877
- const prompt = row.constraints.prompt;
7353
+ const prompt = row2.constraints.prompt;
6878
7354
  if (prompt !== void 0) {
6879
7355
  const parsed = PromptConventionsSchema.safeParse(prompt);
6880
7356
  if (!parsed.success) {
@@ -6889,7 +7365,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6889
7365
  }
6890
7366
  }
6891
7367
  );
6892
- var CatalogSchema = z3.array(CatalogModelSchemaBase.transform((row) => normaliseConventions(row).row)).superRefine((rows, ctx) => {
7368
+ var CatalogSchema = z3.array(CatalogModelSchemaBase.transform((row2) => normaliseConventions(row2).row)).superRefine((rows, ctx) => {
6893
7369
  for (const issue of collisionIssues(rows)) {
6894
7370
  ctx.addIssue({
6895
7371
  code: "custom",
@@ -7892,7 +8368,7 @@ async function generateSeedanceVideo(req, ctx) {
7892
8368
  }
7893
8369
 
7894
8370
  // src/adapters/fal.ts
7895
- import { z as z18 } from "zod";
8371
+ import { z as z20 } from "zod";
7896
8372
  import { createFalClient } from "@fal-ai/client";
7897
8373
 
7898
8374
  // src/adapters/fal-http.ts
@@ -8197,7 +8673,7 @@ async function passthroughVideoJob(ctx, endpoint, input, decode) {
8197
8673
  }
8198
8674
 
8199
8675
  // src/adapters/fal-video-tools.ts
8200
- import { z as z12 } from "zod";
8676
+ import { z as z13 } from "zod";
8201
8677
 
8202
8678
  // src/video-length.ts
8203
8679
  function tenths(seconds3) {
@@ -8288,28 +8764,99 @@ function subtitleFields(tool, options) {
8288
8764
  return out;
8289
8765
  }
8290
8766
 
8291
- // src/catalog/video-tools-spec.ts
8767
+ // src/adapters/fal-queue.ts
8292
8768
  import { z as z11 } from "zod";
8293
- var RangeSchema2 = z11.object({ min: z11.number(), max: z11.number() });
8294
- var ToolSchema = z11.object({
8295
- kind: z11.enum(["upscale", "interpolate", "hdr", "bg-remove", "subtitles"]),
8769
+ var FAL_QUEUE_ORIGIN = "https://queue.fal.run";
8770
+ var queueUrlSchema = z11.url().refine((value) => new URL(value).origin === FAL_QUEUE_ORIGIN, {
8771
+ message: "not a fal queue URL"
8772
+ });
8773
+ var submitResponseSchema = z11.object({
8774
+ request_id: z11.string().min(1),
8775
+ status_url: queueUrlSchema,
8776
+ response_url: queueUrlSchema,
8777
+ cancel_url: queueUrlSchema
8778
+ });
8779
+ var statusResponseSchema = z11.object({ status: z11.string() });
8780
+ var falWebhookBodySchema = z11.object({
8781
+ request_id: z11.string().min(1),
8782
+ gateway_request_id: z11.string().nullish(),
8783
+ status: z11.enum(["OK", "ERROR"]),
8784
+ payload: JsonValueSchema.nullish(),
8785
+ error: z11.string().nullish(),
8786
+ payload_error: JsonValueSchema.nullish()
8787
+ });
8788
+ async function queueFetch(ctx, url, method, body) {
8789
+ const payload = body === void 0 ? void 0 : JSON.stringify(body);
8790
+ try {
8791
+ if (ctx.routing.fal === "cloudflare-passthrough") {
8792
+ return await gatewayFetch(gatewayConfig(ctx), ctx.fetch, url, {
8793
+ method,
8794
+ ...payload !== void 0 && { body: payload }
8795
+ });
8796
+ }
8797
+ const falKey = ctx.keys.fal;
8798
+ if (!falKey) {
8799
+ throw new ModelKitError({
8800
+ code: "auth",
8801
+ message: "Missing API key for fal",
8802
+ provider: "fal",
8803
+ model: ctx.model.id,
8804
+ retryable: false
8805
+ });
8806
+ }
8807
+ return await ctx.fetch(url, {
8808
+ method,
8809
+ headers: {
8810
+ Authorization: `Key ${falKey}`,
8811
+ ...payload !== void 0 && { "Content-Type": "application/json" }
8812
+ },
8813
+ ...payload !== void 0 && { body: payload },
8814
+ ...ctx.signal !== void 0 && { signal: ctx.signal }
8815
+ });
8816
+ } catch (cause) {
8817
+ if (cause instanceof ModelKitError) throw cause;
8818
+ throw classifyThrown("fal", cause, ctx.model.id);
8819
+ }
8820
+ }
8821
+ async function readJson(ctx, res) {
8822
+ if (!res.ok) throw falError(res.status, await readBody(res), ctx.model.id);
8823
+ return JsonValueSchema.parse(await res.json());
8824
+ }
8825
+ function checkedQueueUrl(ctx, url, what) {
8826
+ if (!queueUrlSchema.safeParse(url).success) {
8827
+ throw new ModelKitError({
8828
+ code: "provider_rejected",
8829
+ message: `${what} submission carries a URL outside fal's queue`,
8830
+ provider: "fal",
8831
+ model: ctx.model.id,
8832
+ retryable: false
8833
+ });
8834
+ }
8835
+ return url;
8836
+ }
8837
+
8838
+ // src/catalog/video-tools-spec.ts
8839
+ import { z as z12 } from "zod";
8840
+ var RangeSchema2 = z12.object({ min: z12.number(), max: z12.number() });
8841
+ var ToolSchema = z12.object({
8842
+ kind: z12.enum(["upscale", "interpolate", "hdr", "bg-remove", "subtitles"]),
8296
8843
  upscaleFactor: RangeSchema2.optional(),
8297
- maxOutputLongEdge: z11.number().positive().optional(),
8298
- prompt: z11.boolean().optional(),
8844
+ maxOutputLongEdge: z12.number().positive().optional(),
8845
+ prompt: z12.boolean().optional(),
8299
8846
  fps: RangeSchema2.optional(),
8300
- outputFormats: z11.array(z11.enum(["h265", "prores", "exr"])).min(1).optional(),
8301
- maxOutputShortEdge: z11.number().positive().optional(),
8302
- maxOutputFrames: z11.number().positive().optional(),
8303
- minOutputFrames: z11.number().positive().optional(),
8304
- maxOutputFps: z11.number().positive().optional(),
8305
- presets: z11.array(z11.string().min(1)).min(1).optional(),
8306
- languages: z11.array(z11.string().min(1)).min(1).optional(),
8307
- translationLanguages: z11.array(z11.string().min(1)).min(1).optional(),
8308
- maxSecondsAbove1080p: z11.number().positive().optional()
8847
+ outputFormats: z12.array(z12.enum(["h265", "prores", "exr"])).min(1).optional(),
8848
+ maxOutputShortEdge: z12.number().positive().optional(),
8849
+ maxOutputFrames: z12.number().positive().optional(),
8850
+ minOutputFrames: z12.number().positive().optional(),
8851
+ maxOutputFps: z12.number().positive().optional(),
8852
+ presets: z12.array(z12.string().min(1)).min(1).optional(),
8853
+ languages: z12.array(z12.string().min(1)).min(1).optional(),
8854
+ translationLanguages: z12.array(z12.string().min(1)).min(1).optional(),
8855
+ maxSecondsAbove1080p: z12.number().positive().optional()
8309
8856
  });
8310
- function videoToolConstraints(row) {
8311
- if (row.type !== "video-tool") return void 0;
8312
- const parsed = ToolSchema.safeParse(row.constraints.tool);
8857
+ function videoToolConstraints(row2) {
8858
+ if (row2.type !== "video-tool") return void 0;
8859
+ const parsed = ToolSchema.safeParse(row2.constraints.tool);
8313
8860
  if (!parsed.success) return void 0;
8314
8861
  const {
8315
8862
  kind,
@@ -8356,16 +8903,16 @@ function resolutionTier(width, height) {
8356
8903
  function fail(error) {
8357
8904
  return { ok: false, error };
8358
8905
  }
8359
- function planVideoTool(row, req) {
8360
- const tool = videoToolConstraints(row);
8361
- if (!tool) return fail(`${row.id} is not a video tool`);
8906
+ function planVideoTool(row2, req) {
8907
+ const tool = videoToolConstraints(row2);
8908
+ if (!tool) return fail(`${row2.id} is not a video tool`);
8362
8909
  const { width, height, durationSeconds, fps } = req.source;
8363
8910
  if (!(width > 0 && height > 0 && durationSeconds > 0)) {
8364
8911
  return fail("The source video's width, height and duration are required");
8365
8912
  }
8366
- const maxSeconds = row.constraints.sourceVideoSeconds?.max;
8913
+ const maxSeconds = row2.constraints.sourceVideoSeconds?.max;
8367
8914
  if (maxSeconds !== void 0 && overMax(durationSeconds, maxSeconds)) {
8368
- return fail(`${row.label} takes source videos up to ${maxSeconds} seconds.`);
8915
+ return fail(`${row2.label} takes source videos up to ${maxSeconds} seconds.`);
8369
8916
  }
8370
8917
  const base = {
8371
8918
  durationSeconds,
@@ -8376,7 +8923,7 @@ function planVideoTool(row, req) {
8376
8923
  if (factor === void 0) return fail("An upscale factor is required");
8377
8924
  const range2 = tool.upscaleFactor;
8378
8925
  if (range2 && (factor < range2.min || factor > range2.max)) {
8379
- return fail(`${row.label} upscales by ${range2.min}x to ${range2.max}x.`);
8926
+ return fail(`${row2.label} upscales by ${range2.min}x to ${range2.max}x.`);
8380
8927
  }
8381
8928
  const outWidth = Math.round(width * factor);
8382
8929
  const outHeight = Math.round(height * factor);
@@ -8404,7 +8951,7 @@ function planVideoTool(row, req) {
8404
8951
  }
8405
8952
  const range2 = tool.fps;
8406
8953
  if (range2 && (target < range2.min || target > range2.max)) {
8407
- return fail(`${row.label} outputs ${range2.min} to ${range2.max} fps.`);
8954
+ return fail(`${row2.label} outputs ${range2.min} to ${range2.max} fps.`);
8408
8955
  }
8409
8956
  return {
8410
8957
  ok: true,
@@ -8433,7 +8980,7 @@ function planVideoTool(row, req) {
8433
8980
  if (tool.kind === "subtitles") {
8434
8981
  const resolution = resolutionTier(width, height);
8435
8982
  const problem = subtitleProblem(
8436
- row.label,
8983
+ row2.label,
8437
8984
  tool,
8438
8985
  req.subtitles,
8439
8986
  resolution,
@@ -8445,9 +8992,9 @@ function planVideoTool(row, req) {
8445
8992
  const formats = tool.outputFormats ?? ["h265"];
8446
8993
  const format = req.outputFormat ?? formats[0] ?? "h265";
8447
8994
  if (!formats.includes(format)) {
8448
- return fail(`${row.label} writes ${formats.join(" or ")}.`);
8995
+ return fail(`${row2.label} writes ${formats.join(" or ")}.`);
8449
8996
  }
8450
- const timing = renderedTiming(row, tool, durationSeconds, fps);
8997
+ const timing = renderedTiming(row2, tool, durationSeconds, fps);
8451
8998
  if (!timing.ok) return fail(timing.error);
8452
8999
  const out = shrinkToShortEdge(width, height, tool.maxOutputShortEdge);
8453
9000
  return {
@@ -8463,7 +9010,7 @@ function planVideoTool(row, req) {
8463
9010
  };
8464
9011
  }
8465
9012
  var DEFAULT_FPS = 24;
8466
- function renderedTiming(row, tool, durationSeconds, fps) {
9013
+ function renderedTiming(row2, tool, durationSeconds, fps) {
8467
9014
  const { maxOutputFps, minOutputFrames, maxOutputFrames } = tool;
8468
9015
  if (maxOutputFps === void 0 && minOutputFrames === void 0 && maxOutputFrames === void 0) {
8469
9016
  return fps !== void 0 ? { ok: true, fps } : { ok: true };
@@ -8472,7 +9019,7 @@ function renderedTiming(row, tool, durationSeconds, fps) {
8472
9019
  const frames = Math.max(minOutputFrames ?? 1, Math.round(durationSeconds * rate));
8473
9020
  if (maxOutputFrames !== void 0 && frames > maxOutputFrames) {
8474
9021
  const limit = `${maxOutputFrames} frames (${seconds(maxOutputFrames, rate)})`;
8475
- return { ok: false, error: `${row.label} renders up to ${limit}.` };
9022
+ return { ok: false, error: `${row2.label} renders up to ${limit}.` };
8476
9023
  }
8477
9024
  return { ok: true, fps: rate, frames, durationSeconds: frames / rate };
8478
9025
  }
@@ -8487,76 +9034,20 @@ function shrinkToShortEdge(width, height, limit) {
8487
9034
  }
8488
9035
 
8489
9036
  // src/adapters/fal-video-tools.ts
8490
- var FAL_QUEUE_ORIGIN = "https://queue.fal.run";
8491
- var queueUrlSchema = z12.url().refine((value) => new URL(value).origin === FAL_QUEUE_ORIGIN, {
8492
- message: "not a fal queue URL"
8493
- });
8494
- var submitResponseSchema = z12.object({
8495
- request_id: z12.string().min(1),
8496
- status_url: queueUrlSchema,
8497
- response_url: queueUrlSchema,
8498
- cancel_url: queueUrlSchema
9037
+ var videoFileSchema = z13.object({
9038
+ url: z13.url(),
9039
+ content_type: z13.string().nullish(),
9040
+ file_size: z13.number().nullish()
8499
9041
  });
8500
- var statusResponseSchema = z12.object({ status: z12.string() });
8501
- var videoFileSchema = z12.object({
8502
- url: z12.url(),
8503
- content_type: z12.string().nullish(),
8504
- file_size: z12.number().nullish()
9042
+ var toolOutputSchema = z13.object({
9043
+ video: z13.union([videoFileSchema, z13.array(videoFileSchema).min(1)])
8505
9044
  });
8506
- var toolOutputSchema = z12.object({
8507
- video: z12.union([videoFileSchema, z12.array(videoFileSchema).min(1)])
8508
- });
8509
- var exrOutputSchema = z12.object({
9045
+ var exrOutputSchema = z13.object({
8510
9046
  preview_video: videoFileSchema,
8511
9047
  exr_frames_url: videoFileSchema
8512
9048
  });
8513
- var falWebhookBodySchema = z12.object({
8514
- request_id: z12.string().min(1),
8515
- gateway_request_id: z12.string().nullish(),
8516
- status: z12.enum(["OK", "ERROR"]),
8517
- payload: JsonValueSchema.nullish(),
8518
- error: z12.string().nullish(),
8519
- payload_error: JsonValueSchema.nullish()
8520
- });
8521
- async function queueFetch(ctx, url, method, body) {
8522
- const payload = body === void 0 ? void 0 : JSON.stringify(body);
8523
- try {
8524
- if (ctx.routing.fal === "cloudflare-passthrough") {
8525
- return await gatewayFetch(gatewayConfig(ctx), ctx.fetch, url, {
8526
- method,
8527
- ...payload !== void 0 && { body: payload }
8528
- });
8529
- }
8530
- const falKey = ctx.keys.fal;
8531
- if (!falKey) {
8532
- throw new ModelKitError({
8533
- code: "auth",
8534
- message: "Missing API key for fal",
8535
- provider: "fal",
8536
- model: ctx.model.id,
8537
- retryable: false
8538
- });
8539
- }
8540
- return await ctx.fetch(url, {
8541
- method,
8542
- headers: {
8543
- Authorization: `Key ${falKey}`,
8544
- ...payload !== void 0 && { "Content-Type": "application/json" }
8545
- },
8546
- ...payload !== void 0 && { body: payload },
8547
- ...ctx.signal !== void 0 && { signal: ctx.signal }
8548
- });
8549
- } catch (cause) {
8550
- if (cause instanceof ModelKitError) throw cause;
8551
- throw classifyThrown("fal", cause, ctx.model.id);
8552
- }
8553
- }
8554
- async function readJson(ctx, res) {
8555
- if (!res.ok) throw falError(res.status, await readBody(res), ctx.model.id);
8556
- return JsonValueSchema.parse(await res.json());
8557
- }
8558
9049
  function providerModelName(ctx) {
8559
- return z12.string().safeParse(ctx.model.providerOptions?.["fal"]?.["model"]).data;
9050
+ return z13.string().safeParse(ctx.model.providerOptions?.["fal"]?.["model"]).data;
8560
9051
  }
8561
9052
  function staticInput(ctx) {
8562
9053
  return JsonObjectSchema.safeParse(ctx.model.providerOptions?.["fal"]?.["input"]).data ?? {};
@@ -8627,20 +9118,8 @@ async function submitFalVideoTool(req, ctx, opts) {
8627
9118
  output: plan3.output
8628
9119
  };
8629
9120
  }
8630
- function checkedQueueUrl(ctx, url) {
8631
- if (!queueUrlSchema.safeParse(url).success) {
8632
- throw new ModelKitError({
8633
- code: "provider_rejected",
8634
- message: "Video-tool submission carries a URL outside fal's queue",
8635
- provider: "fal",
8636
- model: ctx.model.id,
8637
- retryable: false
8638
- });
8639
- }
8640
- return url;
8641
- }
8642
9121
  async function falVideoToolStatus(sub, ctx) {
8643
- const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.statusUrl), "GET");
9122
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.statusUrl, "Video-tool"), "GET");
8644
9123
  const { status } = statusResponseSchema.parse(await readJson(ctx, res));
8645
9124
  if (status === "IN_QUEUE") return "queued";
8646
9125
  if (status === "COMPLETED") return "completed";
@@ -8737,18 +9216,18 @@ async function falVideoToolResult(sub, ctx, webhook) {
8737
9216
  }
8738
9217
  return resultOf(ctx, sub, webhook.payload);
8739
9218
  }
8740
- const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.responseUrl), "GET");
9219
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.responseUrl, "Video-tool"), "GET");
8741
9220
  return resultOf(ctx, sub, await readJson(ctx, res));
8742
9221
  }
8743
9222
  async function cancelFalVideoTool(sub, ctx) {
8744
- const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.cancelUrl), "PUT");
9223
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.cancelUrl, "Video-tool"), "PUT");
8745
9224
  if (res.ok) return true;
8746
9225
  if (res.status === 400) return false;
8747
9226
  throw falError(res.status, await readBody(res), ctx.model.id);
8748
9227
  }
8749
9228
 
8750
9229
  // src/adapters/fal-image.ts
8751
- import { z as z13 } from "zod";
9230
+ import { z as z14 } from "zod";
8752
9231
 
8753
9232
  // src/resolve-image-rules.ts
8754
9233
  var WIDE_RATIOS = [
@@ -9334,9 +9813,9 @@ function planFalImage(req, providerModelId, model) {
9334
9813
  if (built.imageSize !== void 0) plan3.imageSize = built.imageSize;
9335
9814
  return plan3;
9336
9815
  }
9337
- var FalFileSchema = z13.object({ url: z13.string(), content_type: z13.string().nullish() });
9338
- var ImagesPayloadSchema = z13.object({ images: z13.array(FalFileSchema) });
9339
- var ImagePayloadSchema = z13.object({ image: FalFileSchema });
9816
+ var FalFileSchema = z14.object({ url: z14.string(), content_type: z14.string().nullish() });
9817
+ var ImagesPayloadSchema = z14.object({ images: z14.array(FalFileSchema) });
9818
+ var ImagePayloadSchema = z14.object({ image: FalFileSchema });
9340
9819
  function decodeDataUri(url) {
9341
9820
  const comma = url.indexOf(",");
9342
9821
  const meta = url.slice(5, comma);
@@ -9395,15 +9874,15 @@ async function generateFalFamilyImage(req, ctx, run) {
9395
9874
  }
9396
9875
 
9397
9876
  // src/adapters/fal-mask.ts
9398
- import { z as z14 } from "zod";
9877
+ import { z as z15 } from "zod";
9399
9878
  var SAM3_IMAGE = "fal-ai/sam-3/image";
9400
9879
  var MAX_MASKS = 32;
9401
- function fail3(row, message, code) {
9880
+ function fail3(row2, message, code) {
9402
9881
  return new ModelKitError({
9403
9882
  code,
9404
- message: `${row.label}: ${message}`,
9883
+ message: `${row2.label}: ${message}`,
9405
9884
  provider: "fal",
9406
- model: row.id,
9885
+ model: row2.id,
9407
9886
  retryable: false
9408
9887
  });
9409
9888
  }
@@ -9413,22 +9892,22 @@ function pointPrompts(points) {
9413
9892
  function boxPrompts(boxes) {
9414
9893
  return boxes.map((b) => ({ x_min: b.xMin, y_min: b.yMin, x_max: b.xMax, y_max: b.yMax }));
9415
9894
  }
9416
- function planFalMask(row, req) {
9417
- if (row.providerModelId !== SAM3_IMAGE) {
9895
+ function planFalMask(row2, req) {
9896
+ if (row2.providerModelId !== SAM3_IMAGE) {
9418
9897
  throw fail3(
9419
- row,
9420
- `fal has no mask mapper for "${row.providerModelId}"`,
9898
+ row2,
9899
+ `fal has no mask mapper for "${row2.providerModelId}"`,
9421
9900
  "unsupported_option"
9422
9901
  );
9423
9902
  }
9424
9903
  const refs = req.references ?? [];
9425
9904
  const [image] = refs;
9426
- if (image === void 0) throw fail3(row, "needs one source image", "missing_input");
9905
+ if (image === void 0) throw fail3(row2, "needs one source image", "missing_input");
9427
9906
  if (refs.length > 1) {
9428
- throw fail3(row, `takes one source image; got ${refs.length}`, "unsupported_option");
9907
+ throw fail3(row2, `takes one source image; got ${refs.length}`, "unsupported_option");
9429
9908
  }
9430
9909
  const problem = maskProblem(req);
9431
- if (problem !== void 0) throw fail3(row, problem.message, problem.code);
9910
+ if (problem !== void 0) throw fail3(row2, problem.message, problem.code);
9432
9911
  const input = {
9433
9912
  image_url: refToUrl(image),
9434
9913
  prompt: req.prompt.trim(),
@@ -9445,17 +9924,17 @@ function planFalMask(row, req) {
9445
9924
  }
9446
9925
  return { endpoint: SAM3_IMAGE, input };
9447
9926
  }
9448
- var masksSchema = z14.object({
9449
- masks: z14.array(z14.object({ url: z14.string().min(1), content_type: z14.string().nullish() }))
9927
+ var masksSchema = z15.object({
9928
+ masks: z15.array(z15.object({ url: z15.string().min(1), content_type: z15.string().nullish() }))
9450
9929
  });
9451
- function parseFalMasks(row, payload) {
9930
+ function parseFalMasks(row2, payload) {
9452
9931
  const parsed = masksSchema.safeParse(payload);
9453
9932
  if (!parsed.success) {
9454
9933
  throw new ModelKitError({
9455
9934
  code: "provider_rejected",
9456
9935
  message: `fal ${SAM3_IMAGE} returned no mask list`,
9457
9936
  provider: "fal",
9458
- model: row.id,
9937
+ model: row2.id,
9459
9938
  retryable: false
9460
9939
  });
9461
9940
  }
@@ -9488,7 +9967,7 @@ async function generateFalMask(req, ctx, run) {
9488
9967
  }
9489
9968
 
9490
9969
  // src/adapters/fal-audio-plan.ts
9491
- import { z as z15 } from "zod";
9970
+ import { z as z16 } from "zod";
9492
9971
  var ELEVENLABS_MUSIC = FAL_AUDIO.elevenLabsMusic;
9493
9972
  var MINIMAX_MUSIC_32 = FAL_AUDIO.minimaxMusic;
9494
9973
  var ELEVENLABS_SFX = FAL_AUDIO.elevenLabsSfx;
@@ -9535,65 +10014,65 @@ var FAL_MEDIA_TYPES = /* @__PURE__ */ new Set([
9535
10014
  function isFalMediaKnown(type, providerModelId) {
9536
10015
  return KNOWN[type]?.has(providerModelId) ?? false;
9537
10016
  }
9538
- function falMediaError(row, message, code) {
10017
+ function falMediaError(row2, message, code) {
9539
10018
  return new ModelKitError({
9540
10019
  code,
9541
- message: `${row.label}: ${message}`,
10020
+ message: `${row2.label}: ${message}`,
9542
10021
  provider: "fal",
9543
- model: row.id,
10022
+ model: row2.id,
9544
10023
  retryable: false
9545
10024
  });
9546
10025
  }
9547
- function refuseMedia(row, present) {
9548
- const extra = Object.entries(present).find(([, set]) => set);
9549
- if (extra) throw falMediaError(row, `does not take ${extra[0]}`, "unsupported_option");
10026
+ function refuseMedia(row2, present2) {
10027
+ const extra = Object.entries(present2).find(([, set]) => set);
10028
+ if (extra) throw falMediaError(row2, `does not take ${extra[0]}`, "unsupported_option");
9550
10029
  }
9551
10030
  function setIf(input, key, value) {
9552
10031
  if (value !== void 0) input[key] = value;
9553
10032
  }
9554
- function unmapped(row) {
10033
+ function unmapped(row2) {
9555
10034
  return falMediaError(
9556
- row,
9557
- `fal has no ${row.type} mapper for "${row.providerModelId}"`,
10035
+ row2,
10036
+ `fal has no ${row2.type} mapper for "${row2.providerModelId}"`,
9558
10037
  "unsupported_option"
9559
10038
  );
9560
10039
  }
9561
- function mediaUrl(row, field, ref) {
9562
- if (ref === void 0) throw falMediaError(row, `needs ${field}`, "missing_input");
10040
+ function mediaUrl(row2, field, ref) {
10041
+ if (ref === void 0) throw falMediaError(row2, `needs ${field}`, "missing_input");
9563
10042
  return refToUrl(ref);
9564
10043
  }
9565
10044
  function trimmed(text2) {
9566
10045
  const value = text2?.trim();
9567
10046
  return value ? value : void 0;
9568
10047
  }
9569
- function requireText(row, text2, what) {
10048
+ function requireText(row2, text2, what) {
9570
10049
  const value = trimmed(text2);
9571
- if (value === void 0) throw falMediaError(row, `needs ${what}`, "missing_input");
10050
+ if (value === void 0) throw falMediaError(row2, `needs ${what}`, "missing_input");
9572
10051
  return value;
9573
10052
  }
9574
- function planMirelo(row, req) {
9575
- const id = row.providerModelId;
10053
+ function planMirelo(row2, req) {
10054
+ const id = row2.providerModelId;
9576
10055
  const input = { num_samples: 1 };
9577
10056
  setIf(input, "duration", req.durationSeconds);
9578
10057
  setIf(input, "negative_prompt", req.negativePrompt);
9579
10058
  setIf(input, "seed", req.seed);
9580
10059
  setIf(input, "upload_audio_format", req.outputFormat);
9581
10060
  if (id === MIRELO_VIDEO) {
9582
- input["video_url"] = mediaUrl(row, "sourceVideo", req.sourceVideo);
10061
+ input["video_url"] = mediaUrl(row2, "sourceVideo", req.sourceVideo);
9583
10062
  setIf(input, "text_prompt", trimmed(req.prompt));
9584
10063
  return { endpoint: id, input };
9585
10064
  }
9586
10065
  input["prompt"] = req.prompt.trim();
9587
10066
  return { endpoint: id, input };
9588
10067
  }
9589
- function planFalAudio(row, req) {
9590
- if (row.type !== "audio" && row.type !== "sound-effect") {
9591
- throw falMediaError(row, `${row.type} rows do not generate audio`, "unsupported_option");
10068
+ function planFalAudio(row2, req) {
10069
+ if (row2.type !== "audio" && row2.type !== "sound-effect") {
10070
+ throw falMediaError(row2, `${row2.type} rows do not generate audio`, "unsupported_option");
9592
10071
  }
9593
- const id = row.providerModelId;
10072
+ const id = row2.providerModelId;
9594
10073
  const problem = falAudioProblem(id, req);
9595
- if (problem !== void 0) throw falMediaError(row, problem.message, problem.code);
9596
- if (id === MIRELO_TEXT || id === MIRELO_VIDEO) return planMirelo(row, req);
10074
+ if (problem !== void 0) throw falMediaError(row2, problem.message, problem.code);
10075
+ if (id === MIRELO_TEXT || id === MIRELO_VIDEO) return planMirelo(row2, req);
9597
10076
  const prompt = req.prompt.trim();
9598
10077
  if (id === ELEVENLABS_MUSIC) {
9599
10078
  const input = { prompt };
@@ -9618,12 +10097,12 @@ function planFalAudio(row, req) {
9618
10097
  setIf(input, "output_format", req.outputFormat);
9619
10098
  return { endpoint: id, input };
9620
10099
  }
9621
- throw unmapped(row);
10100
+ throw unmapped(row2);
9622
10101
  }
9623
- function planFalSpeech(row, req) {
9624
- const id = row.providerModelId;
9625
- if (row.type !== "speech") throw unmapped(row);
9626
- const script = requireText(row, req.text, "text");
10102
+ function planFalSpeech(row2, req) {
10103
+ const id = row2.providerModelId;
10104
+ if (row2.type !== "speech") throw unmapped(row2);
10105
+ const script = requireText(row2, req.text, "text");
9627
10106
  if (ELEVENLABS_TTS.has(id)) {
9628
10107
  const input = { text: script };
9629
10108
  setIf(input, "voice", req.voice);
@@ -9643,31 +10122,31 @@ function planFalSpeech(row, req) {
9643
10122
  setIf(input, "language_boost", req.language);
9644
10123
  return { endpoint: id, input };
9645
10124
  }
9646
- throw unmapped(row);
10125
+ throw unmapped(row2);
9647
10126
  }
9648
- function planFalVoiceChange(row, req) {
9649
- if (row.type !== "voice-change" || row.providerModelId !== VOICE_CHANGER) throw unmapped(row);
9650
- const input = { audio_url: mediaUrl(row, "sourceAudio", req.sourceAudio) };
10127
+ function planFalVoiceChange(row2, req) {
10128
+ if (row2.type !== "voice-change" || row2.providerModelId !== VOICE_CHANGER) throw unmapped(row2);
10129
+ const input = { audio_url: mediaUrl(row2, "sourceAudio", req.sourceAudio) };
9651
10130
  setIf(input, "voice", req.voice);
9652
10131
  setIf(input, "output_format", req.outputFormat);
9653
10132
  return { endpoint: VOICE_CHANGER, input };
9654
10133
  }
9655
- var fileSchema = z15.object({
9656
- url: z15.string().min(1),
9657
- content_type: z15.string().nullish()
10134
+ var fileSchema = z16.object({
10135
+ url: z16.string().min(1),
10136
+ content_type: z16.string().nullish()
9658
10137
  });
9659
- var audioOutputSchema = z15.object({
9660
- audio: z15.union([fileSchema, z15.array(fileSchema).min(1)]),
9661
- duration: z15.number().nullish(),
9662
- duration_ms: z15.number().nullish(),
9663
- lyrics: z15.string().nullish()
10138
+ var audioOutputSchema = z16.object({
10139
+ audio: z16.union([fileSchema, z16.array(fileSchema).min(1)]),
10140
+ duration: z16.number().nullish(),
10141
+ duration_ms: z16.number().nullish(),
10142
+ lyrics: z16.string().nullish()
9664
10143
  });
9665
- function noFalOutput(row, what, endpoint) {
10144
+ function noFalOutput(row2, what, endpoint) {
9666
10145
  return new ModelKitError({
9667
10146
  code: "provider_rejected",
9668
10147
  message: `fal ${endpoint} returned no ${what}`,
9669
10148
  provider: "fal",
9670
- model: row.id,
10149
+ model: row2.id,
9671
10150
  retryable: false
9672
10151
  });
9673
10152
  }
@@ -9675,12 +10154,12 @@ function reportedSeconds(seconds3, ms) {
9675
10154
  if (seconds3 != null) return seconds3;
9676
10155
  return ms != null ? ms / 1e3 : void 0;
9677
10156
  }
9678
- function parseFalAudio(row, endpoint, payload) {
10157
+ function parseFalAudio(row2, endpoint, payload) {
9679
10158
  const parsed = audioOutputSchema.safeParse(payload);
9680
- if (!parsed.success) throw noFalOutput(row, "audio", endpoint);
10159
+ if (!parsed.success) throw noFalOutput(row2, "audio", endpoint);
9681
10160
  const { audio, duration, duration_ms: durationMs, lyrics } = parsed.data;
9682
10161
  const file = Array.isArray(audio) ? audio[0] : audio;
9683
- if (file === void 0) throw noFalOutput(row, "audio", endpoint);
10162
+ if (file === void 0) throw noFalOutput(row2, "audio", endpoint);
9684
10163
  const seconds3 = reportedSeconds(duration, durationMs);
9685
10164
  return {
9686
10165
  url: file.url,
@@ -9691,114 +10170,114 @@ function parseFalAudio(row, endpoint, payload) {
9691
10170
  }
9692
10171
 
9693
10172
  // src/adapters/fal-media-plan.ts
9694
- import { z as z16 } from "zod";
10173
+ import { z as z17 } from "zod";
9695
10174
  var MINIMAX_LIPSYNC_RESOLUTIONS = {
9696
10175
  "480p": "480P",
9697
10176
  "768p": "768P",
9698
10177
  "1080p": "1080P",
9699
10178
  "2k": "2K"
9700
10179
  };
9701
- function syncModelName(row) {
9702
- return z16.string().safeParse(row.providerOptions?.["fal"]?.["model"]).data;
10180
+ function syncModelName(row2) {
10181
+ return z17.string().safeParse(row2.providerOptions?.["fal"]?.["model"]).data;
9703
10182
  }
9704
- function planFalLipsync(row, req) {
9705
- const id = row.providerModelId;
9706
- if (row.type !== "lipsync") throw unmapped(row);
9707
- const audio = mediaUrl(row, "audio", req.audio);
10183
+ function planFalLipsync(row2, req) {
10184
+ const id = row2.providerModelId;
10185
+ if (row2.type !== "lipsync") throw unmapped(row2);
10186
+ const audio = mediaUrl(row2, "audio", req.audio);
9708
10187
  if (id === FAL_LIPSYNC.minimax) {
9709
- refuseMedia(row, { sourceVideo: req.sourceVideo !== void 0 });
10188
+ refuseMedia(row2, { sourceVideo: req.sourceVideo !== void 0 });
9710
10189
  const input = {
9711
- image_url: mediaUrl(row, "image", req.image),
10190
+ image_url: mediaUrl(row2, "image", req.image),
9712
10191
  audio_url: audio
9713
10192
  };
9714
10193
  if (req.resolution !== void 0) {
9715
10194
  const resolution = MINIMAX_LIPSYNC_RESOLUTIONS[req.resolution];
9716
10195
  if (resolution === void 0) {
9717
- throw falMediaError(row, `does not render ${req.resolution}`, "unsupported_option");
10196
+ throw falMediaError(row2, `does not render ${req.resolution}`, "unsupported_option");
9718
10197
  }
9719
10198
  input["resolution"] = resolution;
9720
10199
  }
9721
10200
  return { endpoint: id, input };
9722
10201
  }
9723
- refuseMedia(row, { image: req.image !== void 0 });
9724
- const video = mediaUrl(row, "sourceVideo", req.sourceVideo);
10202
+ refuseMedia(row2, { image: req.image !== void 0 });
10203
+ const video = mediaUrl(row2, "sourceVideo", req.sourceVideo);
9725
10204
  if (id === FAL_LIPSYNC.veed) {
9726
10205
  return { endpoint: id, input: { video_url: video, audio_url: audio } };
9727
10206
  }
9728
10207
  if (id === FAL_LIPSYNC.syncV2 || id === FAL_LIPSYNC.syncV3) {
9729
10208
  const input = { video_url: video, audio_url: audio, sync_mode: "cut_off" };
9730
- const model = syncModelName(row);
10209
+ const model = syncModelName(row2);
9731
10210
  if (id === FAL_LIPSYNC.syncV2 && model !== void 0) input["model"] = model;
9732
10211
  return { endpoint: id, input };
9733
10212
  }
9734
- throw unmapped(row);
10213
+ throw unmapped(row2);
9735
10214
  }
9736
- function planFalDubbing(row, req) {
9737
- if (row.type !== "dubbing" || row.providerModelId !== FAL_DUBBING) throw unmapped(row);
10215
+ function planFalDubbing(row2, req) {
10216
+ if (row2.type !== "dubbing" || row2.providerModelId !== FAL_DUBBING) throw unmapped(row2);
9738
10217
  if (req.sourceVideo !== void 0 && req.sourceAudio !== void 0) {
9739
10218
  throw falMediaError(
9740
- row,
10219
+ row2,
9741
10220
  "takes sourceVideo or sourceAudio, not both",
9742
10221
  "unsupported_option"
9743
10222
  );
9744
10223
  }
9745
10224
  const target = req.targetLanguage.trim();
9746
- if (!target) throw falMediaError(row, "needs targetLanguage", "missing_input");
10225
+ if (!target) throw falMediaError(row2, "needs targetLanguage", "missing_input");
9747
10226
  const input = { target_lang: target };
9748
10227
  if (req.sourceVideo !== void 0) input["video_url"] = refToUrl(req.sourceVideo);
9749
- else input["audio_url"] = mediaUrl(row, "sourceVideo or sourceAudio", req.sourceAudio);
10228
+ else input["audio_url"] = mediaUrl(row2, "sourceVideo or sourceAudio", req.sourceAudio);
9750
10229
  return { endpoint: FAL_DUBBING, input };
9751
10230
  }
9752
- function planFalTranscription(row, req) {
9753
- if (row.type !== "transcription" || row.providerModelId !== FAL_SCRIBE) throw unmapped(row);
9754
- const input = { audio_url: mediaUrl(row, "source", req.source) };
10231
+ function planFalTranscription(row2, req) {
10232
+ if (row2.type !== "transcription" || row2.providerModelId !== FAL_SCRIBE) throw unmapped(row2);
10233
+ const input = { audio_url: mediaUrl(row2, "source", req.source) };
9755
10234
  setIf(input, "language_code", req.language?.trim() || void 0);
9756
10235
  return { endpoint: FAL_SCRIBE, input };
9757
10236
  }
9758
- var fileSchema2 = z16.object({
9759
- url: z16.string().min(1),
9760
- content_type: z16.string().nullish()
10237
+ var fileSchema2 = z17.object({
10238
+ url: z17.string().min(1),
10239
+ content_type: z17.string().nullish()
9761
10240
  });
9762
- var videoOutputSchema = z16.object({
10241
+ var videoOutputSchema = z17.object({
9763
10242
  video: fileSchema2,
9764
- duration: z16.number().nullish()
10243
+ duration: z17.number().nullish()
9765
10244
  });
9766
- var dubbingOutputSchema = z16.object({
10245
+ var dubbingOutputSchema = z17.object({
9767
10246
  video: fileSchema2.nullish(),
9768
10247
  audio: fileSchema2.nullish()
9769
10248
  });
9770
- var transcriptSchema = z16.object({
9771
- text: z16.string(),
9772
- language_code: z16.string().nullish(),
9773
- words: z16.array(
9774
- z16.object({
9775
- text: z16.string(),
9776
- type: z16.string(),
9777
- start: z16.number().nullish(),
9778
- end: z16.number().nullish(),
9779
- speaker_id: z16.string().nullish()
10249
+ var transcriptSchema = z17.object({
10250
+ text: z17.string(),
10251
+ language_code: z17.string().nullish(),
10252
+ words: z17.array(
10253
+ z17.object({
10254
+ text: z17.string(),
10255
+ type: z17.string(),
10256
+ start: z17.number().nullish(),
10257
+ end: z17.number().nullish(),
10258
+ speaker_id: z17.string().nullish()
9780
10259
  })
9781
10260
  ).nullish()
9782
10261
  });
9783
- function parseFalVideo(row, endpoint, payload) {
10262
+ function parseFalVideo(row2, endpoint, payload) {
9784
10263
  const parsed = videoOutputSchema.safeParse(payload);
9785
- if (!parsed.success) throw noFalOutput(row, "video", endpoint);
10264
+ if (!parsed.success) throw noFalOutput(row2, "video", endpoint);
9786
10265
  const { video, duration } = parsed.data;
9787
10266
  return { url: video.url, ...duration != null && { durationSeconds: duration } };
9788
10267
  }
9789
- function parseFalDubbing(row, kind, payload) {
10268
+ function parseFalDubbing(row2, kind, payload) {
9790
10269
  const parsed = dubbingOutputSchema.safeParse(payload);
9791
10270
  const file = parsed.success ? parsed.data[kind] : void 0;
9792
- if (file == null) throw noFalOutput(row, kind, FAL_DUBBING);
10271
+ if (file == null) throw noFalOutput(row2, kind, FAL_DUBBING);
9793
10272
  return {
9794
10273
  kind,
9795
10274
  url: file.url,
9796
10275
  ...file.content_type != null && { mime: file.content_type }
9797
10276
  };
9798
10277
  }
9799
- function parseFalTranscript(row, endpoint, payload) {
10278
+ function parseFalTranscript(row2, endpoint, payload) {
9800
10279
  const parsed = transcriptSchema.safeParse(payload);
9801
- if (!parsed.success) throw noFalOutput(row, "transcript", endpoint);
10280
+ if (!parsed.success) throw noFalOutput(row2, "transcript", endpoint);
9802
10281
  const words = (parsed.data.words ?? []).map(
9803
10282
  (w) => ({
9804
10283
  text: w.text,
@@ -9961,8 +10440,313 @@ async function transcribeFal(req, ctx, run) {
9961
10440
  };
9962
10441
  }
9963
10442
 
10443
+ // src/adapters/fal-model3d.ts
10444
+ import { z as z18 } from "zod";
10445
+ var fileSchema3 = z18.object({
10446
+ url: z18.url(),
10447
+ content_type: z18.string().nullish(),
10448
+ file_size: z18.number().nullish()
10449
+ });
10450
+ var resultSchema = z18.looseObject({
10451
+ model_glb: fileSchema3.nullish(),
10452
+ model_mesh: fileSchema3.nullish(),
10453
+ thumbnail: fileSchema3.nullish(),
10454
+ rendered_image: fileSchema3.nullish()
10455
+ });
10456
+ function rejected(ctx, message) {
10457
+ return new ModelKitError({
10458
+ code: "provider_rejected",
10459
+ message,
10460
+ provider: "fal",
10461
+ model: ctx.model.id,
10462
+ retryable: false
10463
+ });
10464
+ }
10465
+ function specOf(ctx) {
10466
+ const spec = model3dConstraints(ctx.model);
10467
+ if (spec === void 0) {
10468
+ throw new ModelKitError({
10469
+ code: "unsupported_option",
10470
+ message: `${ctx.model.id} is not a 3D model`,
10471
+ model: ctx.model.id
10472
+ });
10473
+ }
10474
+ return spec;
10475
+ }
10476
+ var present = (v) => v !== void 0 && v.length > 0;
10477
+ function model3dCall(row2, spec, req) {
10478
+ const prompt = req.prompt?.trim() || void 0;
10479
+ const texture = model3dTexture(spec, req.texture);
10480
+ const textured = spec.texture.length > 0 && texture !== "none";
10481
+ const pbr = spec.pbr && textured && req.pbr === true;
10482
+ const resolution = model3dResolution(spec, req.resolution);
10483
+ const views = spec.views === "none" ? {} : req.views ?? {};
10484
+ const seed = spec.seed && req.seed !== void 0 ? req.seed : void 0;
10485
+ const endpoint = (path) => {
10486
+ if (path === void 0) {
10487
+ throw new ModelKitError({
10488
+ code: "unsupported_option",
10489
+ message: `${row2.id} has no endpoint for this request`,
10490
+ provider: "fal",
10491
+ model: row2.id,
10492
+ retryable: false
10493
+ });
10494
+ }
10495
+ return path;
10496
+ };
10497
+ const slotted = (kind) => MODEL3D_IMAGE_SLOTS[kind].map((slot) => slot === "image" ? req.image : views[slot]).filter(present).slice(0, spec.maxImages);
10498
+ const images = slotted("unordered");
10499
+ switch (spec.family) {
10500
+ case "trellis":
10501
+ return {
10502
+ endpoint: endpoint(spec.endpoints.image),
10503
+ input: {
10504
+ image_url: req.image ?? "",
10505
+ resolution: Number(resolution),
10506
+ ...seed !== void 0 && { seed }
10507
+ }
10508
+ };
10509
+ case "sam":
10510
+ return {
10511
+ endpoint: endpoint(spec.endpoints.image),
10512
+ input: {
10513
+ image_url: req.image ?? "",
10514
+ ...prompt !== void 0 && { prompt },
10515
+ export_textured_glb: true,
10516
+ ...seed !== void 0 && { seed }
10517
+ }
10518
+ };
10519
+ case "hunyuan": {
10520
+ const opts = { generate_type: textured ? "Normal" : "Geometry", enable_pbr: pbr };
10521
+ if (!present(req.image)) {
10522
+ return {
10523
+ endpoint: endpoint(spec.endpoints.text),
10524
+ input: { prompt: prompt ?? "", ...opts }
10525
+ };
10526
+ }
10527
+ return {
10528
+ endpoint: endpoint(spec.endpoints.image),
10529
+ input: {
10530
+ input_image_url: req.image,
10531
+ ...present(views.back) && { back_image_url: views.back },
10532
+ ...present(views.left) && { left_image_url: views.left },
10533
+ ...present(views.right) && { right_image_url: views.right },
10534
+ ...opts
10535
+ }
10536
+ };
10537
+ }
10538
+ case "tripo": {
10539
+ const opts = {
10540
+ texture: textured,
10541
+ pbr,
10542
+ ...textured && {
10543
+ texture_quality: texture === "detailed" ? "detailed" : "standard"
10544
+ },
10545
+ ...seed !== void 0 && { model_seed: seed }
10546
+ };
10547
+ if (!present(req.image)) {
10548
+ return {
10549
+ endpoint: endpoint(spec.endpoints.text),
10550
+ input: { prompt: prompt ?? "", ...opts }
10551
+ };
10552
+ }
10553
+ const ordered = slotted("ordered");
10554
+ return ordered.length > 1 ? {
10555
+ endpoint: endpoint(spec.endpoints.multiImage),
10556
+ input: { image_urls: ordered, ...opts }
10557
+ } : {
10558
+ endpoint: endpoint(spec.endpoints.image),
10559
+ input: { image_url: req.image, ...opts }
10560
+ };
10561
+ }
10562
+ case "rodin": {
10563
+ const opts = {
10564
+ geometry_file_format: "glb",
10565
+ material: "PBR",
10566
+ ...seed !== void 0 && { seed }
10567
+ };
10568
+ if (images.length === 0) {
10569
+ return {
10570
+ endpoint: endpoint(spec.endpoints.text),
10571
+ input: { prompt: prompt ?? "", ...opts }
10572
+ };
10573
+ }
10574
+ return {
10575
+ endpoint: endpoint(spec.endpoints.image),
10576
+ input: { image_urls: images, ...prompt !== void 0 && { prompt }, ...opts }
10577
+ };
10578
+ }
10579
+ case "meshy": {
10580
+ const texturePrompt = req.texturePrompt?.trim() || void 0;
10581
+ const opts = {
10582
+ enable_pbr: pbr,
10583
+ ...spec.textureRef && texturePrompt !== void 0 && { texture_prompt: texturePrompt },
10584
+ ...spec.textureRef && present(req.textureImage) && { texture_image_url: req.textureImage }
10585
+ };
10586
+ if (images.length === 0) {
10587
+ return {
10588
+ endpoint: endpoint(spec.endpoints.text),
10589
+ input: {
10590
+ prompt: prompt ?? "",
10591
+ mode: textured ? "full" : "preview",
10592
+ ...opts,
10593
+ ...seed !== void 0 && { seed }
10594
+ }
10595
+ };
10596
+ }
10597
+ return images.length > 1 ? {
10598
+ endpoint: endpoint(spec.endpoints.multiImage),
10599
+ input: { image_urls: images, should_texture: textured, ...opts }
10600
+ } : {
10601
+ endpoint: endpoint(spec.endpoints.image),
10602
+ input: { image_url: req.image ?? "", should_texture: textured, ...opts }
10603
+ };
10604
+ }
10605
+ case "hi3d": {
10606
+ const opts = {
10607
+ resolution: resolution === "master" ? "2048master" : "2048quality",
10608
+ enable_texture: textured,
10609
+ enable_pbr: pbr,
10610
+ export_format: "glb"
10611
+ };
10612
+ const anyView = present(views.back) || present(views.left) || present(views.right);
10613
+ return anyView ? {
10614
+ endpoint: endpoint(spec.endpoints.multiImage),
10615
+ input: {
10616
+ front_image_url: req.image ?? "",
10617
+ ...present(views.back) && { back_image_url: views.back },
10618
+ ...present(views.left) && { left_image_url: views.left },
10619
+ ...present(views.right) && { right_image_url: views.right },
10620
+ ...opts
10621
+ }
10622
+ } : {
10623
+ endpoint: endpoint(spec.endpoints.image),
10624
+ input: { image_url: req.image ?? "", ...opts }
10625
+ };
10626
+ }
10627
+ }
10628
+ }
10629
+ async function submitFalModel3d(req, ctx, opts) {
10630
+ const spec = specOf(ctx);
10631
+ const views = req.views ?? {};
10632
+ const refusal2 = model3dInputRefusal(spec, {
10633
+ prompt: present(req.prompt?.trim()),
10634
+ image: present(req.image),
10635
+ back: present(views.back),
10636
+ left: present(views.left),
10637
+ right: present(views.right),
10638
+ top: present(views.top)
10639
+ });
10640
+ if (refusal2 !== null) {
10641
+ throw new ModelKitError({
10642
+ code: "unsupported_option",
10643
+ message: `${ctx.model.id}: ${refusal2}`,
10644
+ provider: "fal",
10645
+ model: ctx.model.id,
10646
+ retryable: false
10647
+ });
10648
+ }
10649
+ if (spec.seed && req.seed !== void 0 && !model3dSeedFits(spec, req.seed)) {
10650
+ throw new ModelKitError({
10651
+ code: "unsupported_option",
10652
+ message: `${ctx.model.id} takes a seed from 0 to ${spec.seedMax ?? Number.MAX_SAFE_INTEGER}`,
10653
+ provider: "fal",
10654
+ model: ctx.model.id,
10655
+ retryable: false
10656
+ });
10657
+ }
10658
+ const call = model3dCall(ctx.model, spec, req);
10659
+ const sku = model3dPricingSku(
10660
+ ctx.model,
10661
+ {
10662
+ ...req.texture !== void 0 && { texture: req.texture },
10663
+ ...req.pbr !== void 0 && { pbr: req.pbr },
10664
+ ...req.resolution !== void 0 && { resolution: req.resolution }
10665
+ },
10666
+ {
10667
+ image: present(req.image),
10668
+ views: spec.views !== "none" && (present(views.back) || present(views.left) || present(views.right) || spec.views === "unordered" && present(views.top))
10669
+ }
10670
+ );
10671
+ const target = new URL(`${FAL_QUEUE_ORIGIN}/${call.endpoint}`);
10672
+ if (opts.webhookUrl !== void 0) target.searchParams.set("fal_webhook", opts.webhookUrl);
10673
+ const res = await queueFetch(ctx, target.toString(), "POST", call.input);
10674
+ const parsed = submitResponseSchema.safeParse(await readJson(ctx, res));
10675
+ if (!parsed.success) throw rejected(ctx, `fal ${call.endpoint} submit returned no queue URLs`);
10676
+ return {
10677
+ model: ctx.model.id,
10678
+ provider: "fal",
10679
+ endpoint: call.endpoint,
10680
+ sku,
10681
+ requestId: parsed.data.request_id,
10682
+ statusUrl: parsed.data.status_url,
10683
+ responseUrl: parsed.data.response_url,
10684
+ cancelUrl: parsed.data.cancel_url
10685
+ };
10686
+ }
10687
+ async function falModel3dStatus(sub, ctx) {
10688
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.statusUrl, "3D"), "GET");
10689
+ const { status } = statusResponseSchema.parse(await readJson(ctx, res));
10690
+ if (status === "IN_QUEUE") return "queued";
10691
+ if (status === "COMPLETED") return "completed";
10692
+ return "running";
10693
+ }
10694
+ function httpsUrl(ctx, sub, url, what) {
10695
+ if (new URL(url).protocol === "https:") return url;
10696
+ throw rejected(ctx, `fal ${sub.endpoint} returned a ${what} URL that is not https`);
10697
+ }
10698
+ function resultOf2(ctx, sub, payload) {
10699
+ const parsed = resultSchema.safeParse(payload);
10700
+ const glb = parsed.success ? parsed.data.model_glb ?? parsed.data.model_mesh : void 0;
10701
+ if (!glb) throw rejected(ctx, `fal ${sub.endpoint} returned no GLB`);
10702
+ const still = parsed.success ? parsed.data.thumbnail ?? parsed.data.rendered_image : void 0;
10703
+ const glbUrl = httpsUrl(ctx, sub, glb.url, "GLB");
10704
+ const stillUrl = still ? httpsUrl(ctx, sub, still.url, "thumbnail") : void 0;
10705
+ return {
10706
+ glb: {
10707
+ url: glbUrl,
10708
+ ...glb.content_type != null && { mime: glb.content_type },
10709
+ ...glb.file_size != null && { bytes: glb.file_size }
10710
+ },
10711
+ ...stillUrl !== void 0 && { thumbnail: { url: stillUrl } },
10712
+ sku: sub.sku,
10713
+ usage: {
10714
+ model: ctx.model.id,
10715
+ provider: "fal",
10716
+ // The sink has no 3D modality; IMAGE is the nearest. The unit is what bills it.
10717
+ modality: "IMAGE",
10718
+ unit: "requests",
10719
+ quantity: 1
10720
+ },
10721
+ raw: payload
10722
+ };
10723
+ }
10724
+ async function falModel3dResult(sub, ctx, webhook) {
10725
+ if (webhook !== void 0) {
10726
+ if (webhook.request_id !== sub.requestId) {
10727
+ throw rejected(ctx, "fal webhook is for a different request");
10728
+ }
10729
+ if (webhook.status === "ERROR") {
10730
+ throw falError(
10731
+ void 0,
10732
+ webhook.payload ?? webhook.error ?? "fal job failed",
10733
+ ctx.model.id
10734
+ );
10735
+ }
10736
+ return resultOf2(ctx, sub, webhook.payload);
10737
+ }
10738
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.responseUrl, "3D"), "GET");
10739
+ return resultOf2(ctx, sub, await readJson(ctx, res));
10740
+ }
10741
+ async function cancelFalModel3d(sub, ctx) {
10742
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.cancelUrl, "3D"), "PUT");
10743
+ if (res.ok) return true;
10744
+ if (res.status === 400) return false;
10745
+ throw falError(res.status, await readBody(res), ctx.model.id);
10746
+ }
10747
+
9964
10748
  // src/adapters/fal-video-plan.ts
9965
- import { z as z17 } from "zod";
10749
+ import { z as z19 } from "zod";
9966
10750
  function refusal(ctx, message, code = "unsupported_option") {
9967
10751
  return new ModelKitError({
9968
10752
  code,
@@ -9999,9 +10783,9 @@ function wholeSeconds(req, ctx) {
9999
10783
  if (!Number.isInteger(duration)) throw refusal(ctx, "takes whole-second durations");
10000
10784
  return duration;
10001
10785
  }
10002
- var lengthSchema = z17.object({
10003
- duration: z17.number().positive().optional(),
10004
- video: z17.object({ duration: z17.number().positive().nullish() }).optional()
10786
+ var lengthSchema = z19.object({
10787
+ duration: z19.number().positive().optional(),
10788
+ video: z19.object({ duration: z19.number().positive().nullish() }).optional()
10005
10789
  });
10006
10790
  function reportedSeconds2(payload) {
10007
10791
  const parsed = lengthSchema.safeParse(payload);
@@ -10133,6 +10917,30 @@ var klingV3Family = {
10133
10917
  }
10134
10918
  };
10135
10919
 
10920
+ // src/replicate-video-kinds.ts
10921
+ function replicateBaseModelId(providerModelId) {
10922
+ const colon = providerModelId.indexOf(":");
10923
+ return colon === -1 ? providerModelId : providerModelId.slice(0, colon);
10924
+ }
10925
+ var REPLICATE_VIDEO_KINDS = /* @__PURE__ */ new Map([
10926
+ ["kling-video/v2.5-turbo/pro/image-to-video", "kling"],
10927
+ ["kling-video/v3.0/pro/image-to-video", "kling"],
10928
+ ["kwaivgi/kling-v3-video", "kling"],
10929
+ ["kwaivgi/kling-v3-omni-video", "kling-omni"],
10930
+ ["minimax/hailuo-02", "hailuo"]
10931
+ ]);
10932
+ function videoKind(providerModelId) {
10933
+ return REPLICATE_VIDEO_KINDS.get(replicateBaseModelId(providerModelId));
10934
+ }
10935
+ var KLING_TIERS = [
10936
+ { mode: "standard", resolution: "720p" },
10937
+ { mode: "pro", resolution: "1080p" },
10938
+ { mode: "4k", resolution: "4k" }
10939
+ ];
10940
+ function klingTier(req) {
10941
+ return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
10942
+ }
10943
+
10136
10944
  // src/resolve-video-rules.ts
10137
10945
  var MOTION_PRO2 = "fal-ai/kling-video/v3/pro/motion-control";
10138
10946
  var MOTION_STANDARD2 = "fal-ai/kling-video/v3/standard/motion-control";
@@ -10306,6 +11114,16 @@ function h3EndFrameRatioWarning(model, ratio) {
10306
11114
  message: `${model.id} follows the end frame's aspect ratio`
10307
11115
  };
10308
11116
  }
11117
+ function isReplicateKling(model) {
11118
+ if (model.adapter !== "replicate") return false;
11119
+ const kind = videoKind(model.providerModelId);
11120
+ return kind === "kling" || kind === "kling-omni";
11121
+ }
11122
+ function fillReplicateKlingResolution(model, req) {
11123
+ if (isReplicateKling(model) && req.resolution === void 0) {
11124
+ req.resolution = klingTier(req).resolution;
11125
+ }
11126
+ }
10309
11127
  function applyFalVideoRules(model, req, callerRatio, warnings) {
10310
11128
  if (model.adapter !== "fal") return;
10311
11129
  const problem = falVideoProblem(model.providerModelId, withPromptForResolve(req));
@@ -10514,7 +11332,7 @@ var MUSE_T2I_ENDPOINT = "meta/muse-image/text-to-image";
10514
11332
  var MUSE_EDIT_ENDPOINT = "meta/muse-image/edit";
10515
11333
  var KLING_O1_ENDPOINT = "fal-ai/kling-video/o1/video-to-video/reference";
10516
11334
  var PASSTHROUGH_MAX_WAIT_MS = 18e4;
10517
- var falSubscribePayloadSchema = z18.object({ data: JsonValueSchema });
11335
+ var falSubscribePayloadSchema = z20.object({ data: JsonValueSchema });
10518
11336
  function defaultCreateFalClient(opts) {
10519
11337
  if (opts.maxRetries !== void 0)
10520
11338
  return createFalHttpClient({
@@ -10592,7 +11410,11 @@ function createFalAdapter(deps = defaultDeps) {
10592
11410
  submitVideoTool: submitFalVideoTool,
10593
11411
  videoToolStatus: falVideoToolStatus,
10594
11412
  videoToolResult: falVideoToolResult,
10595
- cancelVideoTool: cancelFalVideoTool
11413
+ cancelVideoTool: cancelFalVideoTool,
11414
+ submitModel3d: submitFalModel3d,
11415
+ model3dStatus: falModel3dStatus,
11416
+ model3dResult: falModel3dResult,
11417
+ cancelModel3d: cancelFalModel3d
10596
11418
  };
10597
11419
  }
10598
11420
  function falRun(ctx, deps) {
@@ -10740,11 +11562,11 @@ async function decodeImage(ctx, url, contentType) {
10740
11562
  const mime = res.headers.get("content-type") ?? contentType ?? "image/png";
10741
11563
  return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
10742
11564
  }
10743
- var museImageResultSchema = z18.object({
10744
- images: z18.array(
10745
- z18.object({
10746
- url: z18.string().optional(),
10747
- content_type: z18.string().nullable().optional()
11565
+ var museImageResultSchema = z20.object({
11566
+ images: z20.array(
11567
+ z20.object({
11568
+ url: z20.string().optional(),
11569
+ content_type: z20.string().nullable().optional()
10748
11570
  })
10749
11571
  ).optional()
10750
11572
  });
@@ -10944,8 +11766,8 @@ function klingO1Input(req) {
10944
11766
  if (refs.length > 0) input.image_urls = refs;
10945
11767
  return input;
10946
11768
  }
10947
- var falVideoResultSchema = z18.object({
10948
- video: z18.object({ url: z18.string().optional() }).optional()
11769
+ var falVideoResultSchema = z20.object({
11770
+ video: z20.object({ url: z20.string().optional() }).optional()
10949
11771
  });
10950
11772
  function extractVideoUrl(result, endpoint, model) {
10951
11773
  const parsed = falVideoResultSchema.safeParse(result);
@@ -11037,13 +11859,13 @@ function planUsage(ctx, plan3) {
11037
11859
  }
11038
11860
 
11039
11861
  // src/adapters/google-genai.ts
11040
- import { z as z20 } from "zod";
11862
+ import { z as z22 } from "zod";
11041
11863
  import {
11042
11864
  GoogleGenAI
11043
11865
  } from "@google/genai";
11044
11866
 
11045
11867
  // src/adapters/google-files.ts
11046
- import { z as z19 } from "zod";
11868
+ import { z as z21 } from "zod";
11047
11869
  var GOOGLE_FILES_BASE = "https://generativelanguage.googleapis.com";
11048
11870
  var GOOGLE_FILES_POLL_INTERVAL_MS = 2e3;
11049
11871
  var GOOGLE_FILES_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
@@ -11053,17 +11875,17 @@ var GENERIC_MEDIA_TYPES = /* @__PURE__ */ new Set([
11053
11875
  "binary/octet-stream",
11054
11876
  "application/binary"
11055
11877
  ]);
11056
- var uploadedFileSchema = z19.object({
11057
- file: z19.object({
11058
- uri: z19.string().optional(),
11059
- name: z19.string().optional(),
11060
- state: z19.string().optional(),
11061
- mimeType: z19.string().optional()
11878
+ var uploadedFileSchema = z21.object({
11879
+ file: z21.object({
11880
+ uri: z21.string().optional(),
11881
+ name: z21.string().optional(),
11882
+ state: z21.string().optional(),
11883
+ mimeType: z21.string().optional()
11062
11884
  }).optional()
11063
11885
  });
11064
- var fileStateSchema = z19.object({
11065
- state: z19.string().optional(),
11066
- error: z19.object({ message: z19.string().optional() }).optional()
11886
+ var fileStateSchema = z21.object({
11887
+ state: z21.string().optional(),
11888
+ error: z21.object({ message: z21.string().optional() }).optional()
11067
11889
  });
11068
11890
  function resolveMime(declared, fallback) {
11069
11891
  const clean = declared?.split(";")[0]?.trim().toLowerCase();
@@ -11284,7 +12106,7 @@ var OMNI_POLL_INTERVAL_MS = 1e4;
11284
12106
  var RESULT_TIMEOUT_MS3 = 15 * 60 * 1e3;
11285
12107
  var OMNI_INLINE_LIMIT_BYTES = 4 * 1024 * 1024;
11286
12108
  var MEDIA_PART_INLINE_LIMIT_BYTES = 20 * 1024 * 1024;
11287
- var errorTextSchema = z20.string();
12109
+ var errorTextSchema = z22.string();
11288
12110
  function isGoogleGenaiVideoKnown(providerModelId) {
11289
12111
  return providerModelId.startsWith("veo-") || providerModelId.startsWith("gemini-omni");
11290
12112
  }
@@ -11948,15 +12770,15 @@ async function prepareGoogleMediaPart(ref, mediaType, ctx) {
11948
12770
  // src/adapters/google-image.ts
11949
12771
  import { createGoogleGenerativeAI as createGoogleGenerativeAI2 } from "@ai-sdk/google";
11950
12772
  import { generateText } from "ai";
11951
- import { z as z21 } from "zod";
12773
+ import { z as z23 } from "zod";
11952
12774
  var GEMINI_IMAGE_TIMEOUT_MS = 6e5;
11953
12775
  var defaultGoogleImageDeps = {
11954
12776
  createGoogleClient: (opts) => createGoogleGenerativeAI2(opts),
11955
12777
  runTextGeneration: (opts) => generateText(opts)
11956
12778
  };
11957
- var causeChainNodeSchema = z21.object({
11958
- message: z21.string().optional(),
11959
- cause: z21.unknown().optional()
12779
+ var causeChainNodeSchema = z23.object({
12780
+ message: z23.string().optional(),
12781
+ cause: z23.unknown().optional()
11960
12782
  });
11961
12783
  function extractBlockReason(cause) {
11962
12784
  let current = cause;
@@ -12076,7 +12898,7 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
12076
12898
  var googleImageAdapter = createGoogleImageAdapter();
12077
12899
 
12078
12900
  // src/adapters/higgsfield.ts
12079
- import { z as z22 } from "zod";
12901
+ import { z as z24 } from "zod";
12080
12902
 
12081
12903
  // src/adapters/higgsfield-motions.ts
12082
12904
  var MOTION_MAP = {
@@ -12295,14 +13117,14 @@ function klingEndpointFields(providerModelId) {
12295
13117
  const path = (providerModelId.startsWith("/") ? providerModelId.slice(1) : providerModelId).toLowerCase();
12296
13118
  return KLING_ENDPOINT_FIELDS.get(path) ?? UNLISTED_KLING_FIELDS;
12297
13119
  }
12298
- var klingCreateSchema = z22.object({ status_url: z22.string() });
12299
- var klingStatusSchema = z22.object({
12300
- status: z22.string().optional(),
12301
- video: z22.object({ url: z22.string().optional() }).optional(),
13120
+ var klingCreateSchema = z24.object({ status_url: z24.string() });
13121
+ var klingStatusSchema = z24.object({
13122
+ status: z24.string().optional(),
13123
+ video: z24.object({ url: z24.string().optional() }).optional(),
12302
13124
  error: JsonValueSchema.optional()
12303
13125
  });
12304
- var errorMessageSchema = z22.object({ message: z22.string().optional() });
12305
- var textValueSchema = z22.string();
13126
+ var errorMessageSchema = z24.object({ message: z24.string().optional() });
13127
+ var textValueSchema = z24.string();
12306
13128
  function klingErrorDetail(error) {
12307
13129
  if (error === void 0) return "unknown_error";
12308
13130
  const asText = textValueSchema.safeParse(error);
@@ -12458,8 +13280,8 @@ async function generateKlingVideo(req, ctx) {
12458
13280
  }
12459
13281
  };
12460
13282
  }
12461
- var dopMotionOptionsSchema = z22.object({
12462
- modelkit: z22.object({ motion: z22.string().optional() }).optional()
13283
+ var dopMotionOptionsSchema = z24.object({
13284
+ modelkit: z24.object({ motion: z24.string().optional() }).optional()
12463
13285
  });
12464
13286
  function dopMotionId(ctx) {
12465
13287
  const parsed = dopMotionOptionsSchema.safeParse(ctx.model.providerOptions);
@@ -12475,7 +13297,7 @@ function dopMotionId(ctx) {
12475
13297
  });
12476
13298
  return id;
12477
13299
  }
12478
- var jsonRecordSchema = z22.record(z22.string(), JsonValueSchema);
13300
+ var jsonRecordSchema = z24.record(z24.string(), JsonValueSchema);
12479
13301
  var DOP_URL_KEYS = ["url", "video_url", "output_url", "result_url", "download_url"];
12480
13302
  var DOP_NESTED_KEYS = ["video", "result", "results"];
12481
13303
  function dopUrl(body) {
@@ -12503,8 +13325,8 @@ function dopUrl(body) {
12503
13325
  }
12504
13326
  return void 0;
12505
13327
  }
12506
- var dopCreateSchema = z22.object({ id: z22.string() });
12507
- var dopStatusSchema = z22.object({ status: z22.string().optional() });
13328
+ var dopCreateSchema = z24.object({ id: z24.string() });
13329
+ var dopStatusSchema = z24.object({ status: z24.string().optional() });
12508
13330
  async function generateDopVideo(req, ctx) {
12509
13331
  const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
12510
13332
  if (!firstFrame) {
@@ -12632,7 +13454,7 @@ var higgsfieldAdapter = {
12632
13454
 
12633
13455
  // src/adapters/openai-image.ts
12634
13456
  import OpenAI from "openai";
12635
- import { z as z23 } from "zod";
13457
+ import { z as z25 } from "zod";
12636
13458
  var MAX_EDIT_REFERENCES = 16;
12637
13459
  function aspectRatioToSize(ratio, tier) {
12638
13460
  const TIER_LONG_EDGE = {
@@ -12715,9 +13537,9 @@ function toProviderError2(cause, ctx) {
12715
13537
  ctx.model.id
12716
13538
  );
12717
13539
  }
12718
- var openaiUsageSchema = z23.object({
12719
- input_tokens: z23.number().optional(),
12720
- output_tokens: z23.number().optional()
13540
+ var openaiUsageSchema = z25.object({
13541
+ input_tokens: z25.number().optional(),
13542
+ output_tokens: z25.number().optional()
12721
13543
  });
12722
13544
  var openaiImageAdapter = {
12723
13545
  id: "openai-image",
@@ -13129,13 +13951,13 @@ var prodiaAdapter = {
13129
13951
  import Replicate from "replicate";
13130
13952
 
13131
13953
  // src/adapters/replicate-http.ts
13132
- import { z as z24 } from "zod";
13133
- var predictionSchema = z24.object({
13134
- id: z24.string(),
13135
- status: z24.string(),
13954
+ import { z as z26 } from "zod";
13955
+ var predictionSchema = z26.object({
13956
+ id: z26.string(),
13957
+ status: z26.string(),
13136
13958
  output: JsonValueSchema.optional(),
13137
13959
  error: JsonValueSchema.optional(),
13138
- metrics: z24.object({ predict_time: z24.number().optional() }).optional()
13960
+ metrics: z26.object({ predict_time: z26.number().optional() }).optional()
13139
13961
  });
13140
13962
  function createReplicateHttpClient(opts) {
13141
13963
  async function request(path, body, signal) {
@@ -13186,7 +14008,7 @@ function createReplicateHttpClient(opts) {
13186
14008
  }
13187
14009
 
13188
14010
  // src/adapters/replicate.ts
13189
- import { z as z25 } from "zod";
14011
+ import { z as z27 } from "zod";
13190
14012
  var POLL_INTERVAL_MS = 1e3;
13191
14013
  var POLL_TIMEOUT_MS = 15 * 6e4;
13192
14014
  var defaultReplicateDeps = {
@@ -13226,8 +14048,8 @@ function route(providerModelId) {
13226
14048
  if (!providerModelId.includes("/")) return { version: providerModelId };
13227
14049
  return { model: providerModelId };
13228
14050
  }
13229
- var replicateResponseStatusSchema = z25.object({
13230
- response: z25.object({ status: z25.number() }).partial()
14051
+ var replicateResponseStatusSchema = z27.object({
14052
+ response: z27.object({ status: z27.number() }).partial()
13231
14053
  });
13232
14054
  function replicateError(cause, ctx) {
13233
14055
  if (isModelKitError(cause)) return cause;
@@ -13236,10 +14058,6 @@ function replicateError(cause, ctx) {
13236
14058
  const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
13237
14059
  return classifyThrown("replicate", cause, ctx.model.id, { status, body: info.body });
13238
14060
  }
13239
- function baseModelId(providerModelId) {
13240
- const colon = providerModelId.indexOf(":");
13241
- return colon === -1 ? providerModelId : providerModelId.slice(0, colon);
13242
- }
13243
14061
  function predictionErrorBody(cause) {
13244
14062
  const parsed = JsonValueSchema.safeParse(cause);
13245
14063
  if (parsed.success) return parsed.data;
@@ -13254,7 +14072,7 @@ function isUrlFn(value) {
13254
14072
  function extractOutputUrl(output) {
13255
14073
  const root = Array.isArray(output) ? output[0] : output;
13256
14074
  if (root === void 0) throw noOutput();
13257
- const asString = z25.string().safeParse(root);
14075
+ const asString = z27.string().safeParse(root);
13258
14076
  if (asString.success && asString.data) return asString.data;
13259
14077
  if (root instanceof URL) return root.href;
13260
14078
  if (isObjectOutput(root)) {
@@ -13263,15 +14081,15 @@ function extractOutputUrl(output) {
13263
14081
  if (urlValue !== void 0 && isUrlFn(urlValue)) {
13264
14082
  const called = urlValue();
13265
14083
  if (called instanceof URL) return called.href;
13266
- const calledString = z25.string().safeParse(called);
14084
+ const calledString = z27.string().safeParse(called);
13267
14085
  if (calledString.success && calledString.data) return calledString.data;
13268
14086
  } else {
13269
- const direct = z25.string().safeParse(urlValue);
14087
+ const direct = z27.string().safeParse(urlValue);
13270
14088
  if (direct.success && direct.data) return direct.data;
13271
14089
  }
13272
14090
  }
13273
14091
  if ("default" in root) {
13274
- const fallback = z25.string().safeParse(root.default);
14092
+ const fallback = z27.string().safeParse(root.default);
13275
14093
  if (fallback.success && fallback.data) return fallback.data;
13276
14094
  }
13277
14095
  }
@@ -13332,7 +14150,7 @@ async function runPrediction(ctx, input, deps) {
13332
14150
  }
13333
14151
  return void 0;
13334
14152
  }, pollOpts);
13335
- const predictTime = z25.number().safeParse(done.metrics?.predict_time);
14153
+ const predictTime = z27.number().safeParse(done.metrics?.predict_time);
13336
14154
  if (done.output === void 0) throw noOutput();
13337
14155
  return {
13338
14156
  url: extractOutputUrl(done.output),
@@ -13393,17 +14211,7 @@ var REPLICATE_IMAGE_KINDS = {
13393
14211
  "qwen-edit-apps/qwen-image-edit-plus-lora-skin": "qwen-edit"
13394
14212
  };
13395
14213
  function imageKind(providerModelId) {
13396
- return REPLICATE_IMAGE_KINDS[baseModelId(providerModelId)] ?? "generic";
13397
- }
13398
- var REPLICATE_VIDEO_KINDS = {
13399
- "kling-video/v2.5-turbo/pro/image-to-video": "kling",
13400
- "kling-video/v3.0/pro/image-to-video": "kling",
13401
- "kwaivgi/kling-v3-video": "kling",
13402
- "kwaivgi/kling-v3-omni-video": "kling-omni",
13403
- "minimax/hailuo-02": "hailuo"
13404
- };
13405
- function videoKind(providerModelId) {
13406
- return REPLICATE_VIDEO_KINDS[baseModelId(providerModelId)];
14214
+ return REPLICATE_IMAGE_KINDS[replicateBaseModelId(providerModelId)] ?? "generic";
13407
14215
  }
13408
14216
  function isReplicateVideoKnown(providerModelId) {
13409
14217
  return videoKind(providerModelId) !== void 0;
@@ -13414,7 +14222,7 @@ var REPLICATE_AUDIO_KINDS = {
13414
14222
  "google/lyria-2": "lyria"
13415
14223
  };
13416
14224
  function audioKind(providerModelId) {
13417
- return REPLICATE_AUDIO_KINDS[baseModelId(providerModelId)];
14225
+ return REPLICATE_AUDIO_KINDS[replicateBaseModelId(providerModelId)];
13418
14226
  }
13419
14227
  function isReplicateAudioKnown(providerModelId) {
13420
14228
  return audioKind(providerModelId) !== void 0;
@@ -13618,14 +14426,6 @@ function replicateVideoResolution(providerModelId, req) {
13618
14426
  if (kind === "hailuo") return hailuoResolution(req);
13619
14427
  return req.resolution;
13620
14428
  }
13621
- var KLING_TIERS = [
13622
- { mode: "standard", resolution: "720p" },
13623
- { mode: "pro", resolution: "1080p" },
13624
- { mode: "4k", resolution: "4k" }
13625
- ];
13626
- function klingTier(req) {
13627
- return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
13628
- }
13629
14429
  function klingOmniInput(req) {
13630
14430
  const input = {
13631
14431
  prompt: req.prompt,
@@ -13703,7 +14503,7 @@ async function generateReplicateVideo(req, ctx, deps) {
13703
14503
  throw replicateError(cause, ctx);
13704
14504
  }
13705
14505
  if (current.status === "succeeded") {
13706
- const predictTime = z25.number().safeParse(current.metrics?.predict_time);
14506
+ const predictTime = z27.number().safeParse(current.metrics?.predict_time);
13707
14507
  if (current.output === void 0) throw noOutput();
13708
14508
  return {
13709
14509
  url: extractOutputUrl(current.output),
@@ -13845,7 +14645,7 @@ async function generateReplicateAudio(req, ctx, deps) {
13845
14645
  // src/adapters/xai-video.ts
13846
14646
  import { experimental_generateVideo } from "ai";
13847
14647
  import { createXai as createXai2 } from "@ai-sdk/xai";
13848
- import { z as z26 } from "zod";
14648
+ import { z as z28 } from "zod";
13849
14649
  var POLL_INTERVAL_MS2 = 1e4;
13850
14650
  var POLL_TIMEOUT_MS2 = 15 * 6e4;
13851
14651
  var defaultXaiDeps = {
@@ -13858,8 +14658,8 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
13858
14658
  };
13859
14659
  }
13860
14660
  var xaiVideoAdapter = createXaiVideoAdapter();
13861
- var xaiResponseStatusSchema = z26.object({
13862
- response: z26.object({ status: z26.number() }).partial()
14661
+ var xaiResponseStatusSchema = z28.object({
14662
+ response: z28.object({ status: z28.number() }).partial()
13863
14663
  });
13864
14664
  function xaiError(cause, ctx) {
13865
14665
  const info = describeThrown(cause);
@@ -13867,12 +14667,12 @@ function xaiError(cause, ctx) {
13867
14667
  const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
13868
14668
  return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
13869
14669
  }
13870
- var xaiMetaSchema = z26.object({
14670
+ var xaiMetaSchema = z28.object({
13871
14671
  videoUrl: JsonValueSchema.optional(),
13872
14672
  costInUsdTicks: JsonValueSchema.optional(),
13873
14673
  duration: JsonValueSchema.optional()
13874
14674
  });
13875
- var xaiProviderMetadataSchema = z26.object({ xai: xaiMetaSchema });
14675
+ var xaiProviderMetadataSchema = z28.object({ xai: xaiMetaSchema });
13876
14676
  function metaOf(result) {
13877
14677
  const parsed = xaiProviderMetadataSchema.partial().safeParse(result.providerMetadata);
13878
14678
  if (!parsed.success) return {};
@@ -13988,7 +14788,7 @@ async function mapResult(ctx, req, result) {
13988
14788
  };
13989
14789
  }
13990
14790
  const meta = metaOf(result);
13991
- const videoUrl = z26.string().safeParse(meta.videoUrl);
14791
+ const videoUrl = z28.string().safeParse(meta.videoUrl);
13992
14792
  if (videoUrl.success && videoUrl.data) {
13993
14793
  const res = await ctx.fetch(videoUrl.data);
13994
14794
  if (!res.ok) {
@@ -14011,7 +14811,7 @@ async function mapResult(ctx, req, result) {
14011
14811
  });
14012
14812
  }
14013
14813
  function usage2(ctx, req, meta) {
14014
- const costTicks = z26.number().safeParse(meta.costInUsdTicks);
14814
+ const costTicks = z28.number().safeParse(meta.costInUsdTicks);
14015
14815
  const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
14016
14816
  const event = {
14017
14817
  model: ctx.model.id,
@@ -14063,10 +14863,10 @@ var DEFAULT_ADAPTERS = {
14063
14863
  };
14064
14864
 
14065
14865
  // src/catalog/data-only.ts
14066
- function hasValidInputSpec(row) {
14067
- const raw = row.providerOptions?.["modelkit"]?.["inputSpec"];
14866
+ function hasValidInputSpec(row2) {
14867
+ const raw = row2.providerOptions?.["modelkit"]?.["inputSpec"];
14068
14868
  if (raw === void 0) return false;
14069
- return validateInputSpec(raw, row).ok;
14869
+ return validateInputSpec(raw, row2).ok;
14070
14870
  }
14071
14871
  function assertNever(value) {
14072
14872
  throw new Error(`Unhandled adapter: ${String(value)}`);
@@ -14084,6 +14884,7 @@ function adapterServesType(adapter, type) {
14084
14884
  if (type === "lipsync") return adapter.lipsync !== void 0;
14085
14885
  if (type === "transcription") return adapter.transcribe !== void 0;
14086
14886
  if (type === "video-tool") return adapter.submitVideoTool !== void 0;
14887
+ if (type === "model3d") return adapter.submitModel3d !== void 0;
14087
14888
  return adapter.languageModel !== void 0;
14088
14889
  }
14089
14890
  var FAL_NODE_TYPES = /* @__PURE__ */ new Set([
@@ -14095,18 +14896,18 @@ var FAL_NODE_TYPES = /* @__PURE__ */ new Set([
14095
14896
  "transcription",
14096
14897
  "mask"
14097
14898
  ]);
14098
- function dataOnlyCapable(row) {
14099
- const adapter = DEFAULT_ADAPTERS[row.adapter];
14100
- if (!adapterServesType(adapter, row.type)) {
14101
- return { ok: false, reason: `${row.adapter} cannot serve ${row.type} rows` };
14899
+ function dataOnlyCapable(row2) {
14900
+ const adapter = DEFAULT_ADAPTERS[row2.adapter];
14901
+ if (!adapterServesType(adapter, row2.type)) {
14902
+ return { ok: false, reason: `${row2.adapter} cannot serve ${row2.type} rows` };
14102
14903
  }
14103
- if (FAL_NODE_TYPES.has(row.type) && row.adapter !== "fal") {
14104
- return { ok: false, reason: `only fal serves ${row.type} rows` };
14904
+ if (FAL_NODE_TYPES.has(row2.type) && row2.adapter !== "fal") {
14905
+ return { ok: false, reason: `only fal serves ${row2.type} rows` };
14105
14906
  }
14106
- switch (row.adapter) {
14907
+ switch (row2.adapter) {
14107
14908
  case "ai-sdk-text": {
14108
14909
  try {
14109
- textProviderOf(row);
14910
+ textProviderOf(row2);
14110
14911
  return { ok: true };
14111
14912
  } catch {
14112
14913
  return {
@@ -14124,14 +14925,14 @@ function dataOnlyCapable(row) {
14124
14925
  return { ok: true };
14125
14926
  }
14126
14927
  case "google-genai": {
14127
- if (row.type === "video") {
14128
- return isGoogleGenaiVideoKnown(row.providerModelId) ? { ok: true } : { ok: false, reason: "google-genai video needs a veo- or gemini-omni id" };
14928
+ if (row2.type === "video") {
14929
+ return isGoogleGenaiVideoKnown(row2.providerModelId) ? { ok: true } : { ok: false, reason: "google-genai video needs a veo- or gemini-omni id" };
14129
14930
  }
14130
- return isGoogleGenaiAudioKnown(row.providerModelId) ? { ok: true } : { ok: false, reason: "google-genai audio needs a lyria- id" };
14931
+ return isGoogleGenaiAudioKnown(row2.providerModelId) ? { ok: true } : { ok: false, reason: "google-genai audio needs a lyria- id" };
14131
14932
  }
14132
14933
  case "replicate": {
14133
- if (row.type === "video") {
14134
- if (isReplicateVideoKnown(row.providerModelId) || hasValidInputSpec(row)) {
14934
+ if (row2.type === "video") {
14935
+ if (isReplicateVideoKnown(row2.providerModelId) || hasValidInputSpec(row2)) {
14135
14936
  return { ok: true };
14136
14937
  }
14137
14938
  return {
@@ -14139,8 +14940,8 @@ function dataOnlyCapable(row) {
14139
14940
  reason: "replicate video needs a known kind or a valid inputSpec"
14140
14941
  };
14141
14942
  }
14142
- if (row.type === "audio") {
14143
- if (isReplicateAudioKnown(row.providerModelId) || hasValidInputSpec(row)) {
14943
+ if (row2.type === "audio") {
14944
+ if (isReplicateAudioKnown(row2.providerModelId) || hasValidInputSpec(row2)) {
14144
14945
  return { ok: true };
14145
14946
  }
14146
14947
  return {
@@ -14151,31 +14952,31 @@ function dataOnlyCapable(row) {
14151
14952
  return { ok: true };
14152
14953
  }
14153
14954
  case "fal": {
14154
- if (row.type === "video") {
14155
- return isFalVideoKnown(row.providerModelId) ? { ok: true } : { ok: false, reason: "fal video needs an id from a fal video family" };
14955
+ if (row2.type === "video") {
14956
+ return isFalVideoKnown(row2.providerModelId) ? { ok: true } : { ok: false, reason: "fal video needs an id from a fal video family" };
14156
14957
  }
14157
- if (row.type === "mask") {
14158
- return row.providerModelId === SAM3_IMAGE ? { ok: true } : { ok: false, reason: `fal maps mask rows only to ${SAM3_IMAGE}` };
14958
+ if (row2.type === "mask") {
14959
+ return row2.providerModelId === SAM3_IMAGE ? { ok: true } : { ok: false, reason: `fal maps mask rows only to ${SAM3_IMAGE}` };
14159
14960
  }
14160
- if (row.type === "video-tool" && row.constraints.tool?.kind === "subtitles") {
14161
- return row.providerModelId === VEED_SUBTITLES2 ? { ok: true } : { ok: false, reason: `fal maps subtitles only to ${VEED_SUBTITLES2}` };
14961
+ if (row2.type === "video-tool" && row2.constraints.tool?.kind === "subtitles") {
14962
+ return row2.providerModelId === VEED_SUBTITLES2 ? { ok: true } : { ok: false, reason: `fal maps subtitles only to ${VEED_SUBTITLES2}` };
14162
14963
  }
14163
- if (FAL_MEDIA_TYPES.has(row.type)) {
14164
- return isFalMediaKnown(row.type, row.providerModelId) ? { ok: true } : { ok: false, reason: `fal has no ${row.type} mapping for this id` };
14964
+ if (FAL_MEDIA_TYPES.has(row2.type)) {
14965
+ return isFalMediaKnown(row2.type, row2.providerModelId) ? { ok: true } : { ok: false, reason: `fal has no ${row2.type} mapping for this id` };
14165
14966
  }
14166
14967
  return { ok: true };
14167
14968
  }
14168
14969
  case "prodia": {
14169
- return isProdiaCapable(row.providerModelId) ? { ok: true } : { ok: false, reason: "prodia has no job mapping for this id" };
14970
+ return isProdiaCapable(row2.providerModelId) ? { ok: true } : { ok: false, reason: "prodia has no job mapping for this id" };
14170
14971
  }
14171
14972
  case "higgsfield": {
14172
- return isHiggsfieldCapable(row.providerModelId) ? { ok: true } : {
14973
+ return isHiggsfieldCapable(row2.providerModelId) ? { ok: true } : {
14173
14974
  ok: false,
14174
14975
  reason: "higgsfield providerModelId must be a platform path, not a URL"
14175
14976
  };
14176
14977
  }
14177
14978
  default: {
14178
- return assertNever(row.adapter);
14979
+ return assertNever(row2.adapter);
14179
14980
  }
14180
14981
  }
14181
14982
  }
@@ -14193,22 +14994,22 @@ var liveState = store[KEY] ??= {
14193
14994
  var liveCatalog = liveState.catalog;
14194
14995
 
14195
14996
  // src/catalog/load.ts
14196
- import { z as z27 } from "zod";
14997
+ import { z as z29 } from "zod";
14197
14998
  function rowCount() {
14198
14999
  return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
14199
15000
  }
14200
15001
  function authHeaders(auth) {
14201
15002
  return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
14202
15003
  }
14203
- var EnvelopeSchema = z27.object({
14204
- rows: z27.array(JsonValueSchema),
14205
- revision: z27.string().optional()
15004
+ var EnvelopeSchema = z29.object({
15005
+ rows: z29.array(JsonValueSchema),
15006
+ revision: z29.string().optional()
14206
15007
  });
14207
15008
  function dropReason(path, message) {
14208
15009
  return path.length === 0 ? message : `${path.map((part) => String(part)).join(".")} ${message}`;
14209
15010
  }
14210
15011
  function rowId(raw) {
14211
- const parsed = z27.object({ id: z27.string().min(1) }).loose().safeParse(raw);
15012
+ const parsed = z29.object({ id: z29.string().min(1) }).loose().safeParse(raw);
14212
15013
  if (!parsed.success) return "?";
14213
15014
  return parsed.data.id;
14214
15015
  }
@@ -14224,22 +15025,22 @@ function quarantine(rawRows, logger) {
14224
15025
  dropped += 1;
14225
15026
  continue;
14226
15027
  }
14227
- const row = parsed.data;
14228
- const inputSpecRaw = row.providerOptions?.["modelkit"]?.["inputSpec"];
15028
+ const row2 = parsed.data;
15029
+ const inputSpecRaw = row2.providerOptions?.["modelkit"]?.["inputSpec"];
14229
15030
  if (inputSpecRaw !== void 0) {
14230
- const result = validateInputSpec(inputSpecRaw, row);
15031
+ const result = validateInputSpec(inputSpecRaw, row2);
14231
15032
  if (!result.ok) {
14232
15033
  const first = result.issues[0];
14233
15034
  const detail = first ? dropReason(first.path, first.message) : "invalid inputSpec";
14234
15035
  logger.warn(
14235
- `[modelkit] catalog row ${row.id} has an invalid providerOptions.modelkit.inputSpec: ${detail}; calls fail until it is fixed`
15036
+ `[modelkit] catalog row ${row2.id} has an invalid providerOptions.modelkit.inputSpec: ${detail}; calls fail until it is fixed`
14236
15037
  );
14237
15038
  }
14238
15039
  }
14239
- const normalised = normaliseConventions(row);
15040
+ const normalised = normaliseConventions(row2);
14240
15041
  if (normalised.invalidKeys.length > 0) {
14241
15042
  logger.warn(
14242
- `[modelkit] catalog row ${row.id} has an invalid ${normalised.invalidKeys.join(", ")}; read as not set`
15043
+ `[modelkit] catalog row ${row2.id} has an invalid ${normalised.invalidKeys.join(", ")}; read as not set`
14243
15044
  );
14244
15045
  }
14245
15046
  valid.push(normalised.row);
@@ -14253,10 +15054,10 @@ function quarantine(rawRows, logger) {
14253
15054
  if (!firstByIndex.has(issue.index)) firstByIndex.set(issue.index, issue);
14254
15055
  }
14255
15056
  for (const [index, issue] of [...firstByIndex.entries()].sort((a, b) => a[0] - b[0])) {
14256
- const row = kept[index];
14257
- if (!row) continue;
15057
+ const row2 = kept[index];
15058
+ if (!row2) continue;
14258
15059
  logger.warn(
14259
- `[modelkit] catalog row dropped id=${row.id} reason=${String(issue.path[0] ?? "")} ${issue.message}`
15060
+ `[modelkit] catalog row dropped id=${row2.id} reason=${String(issue.path[0] ?? "")} ${issue.message}`
14260
15061
  );
14261
15062
  }
14262
15063
  const dropSet = new Set(firstByIndex.keys());
@@ -14852,8 +15653,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
14852
15653
  warnings
14853
15654
  );
14854
15655
  if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
15656
+ fillReplicateKlingResolution(model, merged);
14855
15657
  const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
14856
15658
  if (resolution !== void 0) merged.resolution = resolution;
15659
+ if (isReplicateKling(model)) delete merged.mode;
14857
15660
  const duration = resolveDuration(
14858
15661
  merged.durationSeconds,
14859
15662
  c.durations,
@@ -14956,16 +15759,16 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
14956
15759
  }
14957
15760
  function checkVideoRequired(model, req) {
14958
15761
  const c = model.constraints;
14959
- const present = (input) => input === "references" ? compact(req.referenceImages).length + compact(req.referenceVideos).length + compact(req.referenceAudios).length > 0 : input !== "sourceAudio" && req[input] !== void 0;
15762
+ const present2 = (input) => input === "references" ? compact(req.referenceImages).length + compact(req.referenceVideos).length + compact(req.referenceAudios).length > 0 : input !== "sourceAudio" && req[input] !== void 0;
14960
15763
  for (const input of c.requires ?? []) {
14961
- if (!present(input))
15764
+ if (!present2(input))
14962
15765
  throw new ModelKitError({
14963
15766
  code: "missing_input",
14964
15767
  message: `${model.id} requires ${input}`,
14965
15768
  model: model.id
14966
15769
  });
14967
15770
  }
14968
- if (c.requiresOneOf && !c.requiresOneOf.some(present)) {
15771
+ if (c.requiresOneOf && !c.requiresOneOf.some(present2)) {
14969
15772
  throw new ModelKitError({
14970
15773
  code: "missing_input",
14971
15774
  message: `${model.id} requires one of: ${c.requiresOneOf.join(", ")}`,
@@ -15013,8 +15816,8 @@ function resolveAudioOptions(model, request, onUnsupported = "error") {
15013
15816
  if (references.length > 0) merged.references = references;
15014
15817
  else delete merged.references;
15015
15818
  for (const input of c.requires ?? []) {
15016
- const present = input === "references" ? references.length > 0 : input === "sourceVideo" && merged.sourceVideo !== void 0;
15017
- if (!present)
15819
+ const present2 = input === "references" ? references.length > 0 : input === "sourceVideo" && merged.sourceVideo !== void 0;
15820
+ if (!present2)
15018
15821
  throw new ModelKitError({
15019
15822
  code: "missing_input",
15020
15823
  message: `${model.id} requires ${input}`,
@@ -15068,12 +15871,12 @@ function unsupported3(model, message) {
15068
15871
  model: model.id
15069
15872
  });
15070
15873
  }
15071
- function checkRequired(model, present) {
15874
+ function checkRequired(model, present2) {
15072
15875
  for (const input of model.constraints.requires ?? []) {
15073
- if (present[input] !== true) throw missing2(model, input);
15876
+ if (present2[input] !== true) throw missing2(model, input);
15074
15877
  }
15075
15878
  const oneOf = model.constraints.requiresOneOf;
15076
- if (oneOf !== void 0 && !oneOf.some((input) => present[input] === true)) {
15879
+ if (oneOf !== void 0 && !oneOf.some((input) => present2[input] === true)) {
15077
15880
  throw missing2(model, `one of ${oneOf.join(", ")}`);
15078
15881
  }
15079
15882
  }
@@ -15335,7 +16138,7 @@ function keysFromEnv(env, prefix = "") {
15335
16138
 
15336
16139
  // src/text.ts
15337
16140
  import "ai";
15338
- import { z as z28 } from "zod";
16141
+ import { z as z30 } from "zod";
15339
16142
  function mergeTextProviderOptions(catalog, caller) {
15340
16143
  const merged = {};
15341
16144
  const catalogOptions = catalog.providerOptions ?? {};
@@ -15374,8 +16177,8 @@ function passthroughTextModel(model) {
15374
16177
  pricingKind: "token"
15375
16178
  };
15376
16179
  }
15377
- var perplexityCostSchema = z28.object({
15378
- perplexity: z28.object({ cost: z28.object({ totalCost: z28.number().finite().nonnegative() }) })
16180
+ var perplexityCostSchema = z30.object({
16181
+ perplexity: z30.object({ cost: z30.object({ totalCost: z30.number().finite().nonnegative() }) })
15379
16182
  });
15380
16183
  function reportedCostUsd(metadata) {
15381
16184
  const parsed = perplexityCostSchema.safeParse(metadata);
@@ -15455,7 +16258,7 @@ import {
15455
16258
  streamObject as aiStreamObject2,
15456
16259
  streamText as aiStreamText2
15457
16260
  } from "ai";
15458
- import { z as z29 } from "zod";
16261
+ import { z as z31 } from "zod";
15459
16262
 
15460
16263
  // src/generated-image.ts
15461
16264
  function toGeneratedImage(image) {
@@ -15482,8 +16285,8 @@ function isAnthropicTransport(value) {
15482
16285
  return ANTHROPIC_TRANSPORTS.some((transport) => transport === value);
15483
16286
  }
15484
16287
  function preferredAnthropicTransport(model, routing) {
15485
- const row = model.providerOptions?.["modelkit"]?.["transport"];
15486
- if (isAnthropicTransport(row)) return row;
16288
+ const row2 = model.providerOptions?.["modelkit"]?.["transport"];
16289
+ if (isAnthropicTransport(row2)) return row2;
15487
16290
  return routing.anthropic ?? "direct";
15488
16291
  }
15489
16292
  function resolveAnthropicTransport(model, config, tier, warn) {
@@ -15510,6 +16313,85 @@ function textUsageProvider(model, transport) {
15510
16313
  return transport === "bedrock" ? BEDROCK_USAGE_PROVIDER : textProviderOf(model);
15511
16314
  }
15512
16315
 
16316
+ // src/provider-job.ts
16317
+ var VIDEO_TOOL_JOB = {
16318
+ type: "video-tool",
16319
+ noun: "a video tool",
16320
+ plural: "video tools",
16321
+ methods: (a) => ({
16322
+ submit: a.submitVideoTool?.bind(a),
16323
+ status: a.videoToolStatus?.bind(a),
16324
+ result: a.videoToolResult?.bind(a),
16325
+ cancel: a.cancelVideoTool?.bind(a)
16326
+ })
16327
+ };
16328
+ var MODEL3D_JOB = {
16329
+ type: "model3d",
16330
+ noun: "a 3D model",
16331
+ plural: "3D models",
16332
+ methods: (a) => ({
16333
+ submit: a.submitModel3d?.bind(a),
16334
+ status: a.model3dStatus?.bind(a),
16335
+ result: a.model3dResult?.bind(a),
16336
+ cancel: a.cancelModel3d?.bind(a)
16337
+ })
16338
+ };
16339
+ function providerJobMethods(kind, deps) {
16340
+ function target(modelId, call) {
16341
+ mediaRetryOptions(call);
16342
+ const model = deps.catalog.require(modelId);
16343
+ if (model.type !== kind.type)
16344
+ throw new ModelKitError({
16345
+ code: "unsupported_option",
16346
+ message: `${model.id} is not ${kind.noun}`,
16347
+ model: model.id
16348
+ });
16349
+ const { adapter, ctx } = deps.context(model, call);
16350
+ return { methods: kind.methods(adapter), adapter, ctx };
16351
+ }
16352
+ function missing3(adapter, model) {
16353
+ return new ModelKitError({
16354
+ code: "unsupported_option",
16355
+ message: `${adapter.id} has no ${kind.plural}`,
16356
+ model: model.id
16357
+ });
16358
+ }
16359
+ return {
16360
+ async submit(req, call = {}) {
16361
+ const { webhookUrl, ...rest } = call;
16362
+ const { methods, adapter, ctx } = target(req.model, rest);
16363
+ if (!methods.submit) throw missing3(adapter, ctx.model);
16364
+ const submittedAt = Date.now();
16365
+ const submission = await methods.submit(
16366
+ req,
16367
+ ctx,
16368
+ webhookUrl !== void 0 ? { webhookUrl } : {}
16369
+ );
16370
+ return { ...submission, submittedAt };
16371
+ },
16372
+ async status(sub, call = {}) {
16373
+ const { methods, adapter, ctx } = target(sub.model, call);
16374
+ if (!methods.status) throw missing3(adapter, ctx.model);
16375
+ return methods.status(sub, ctx);
16376
+ },
16377
+ async result(sub, call = {}) {
16378
+ const { webhook, ...rest } = call;
16379
+ const { methods, adapter, ctx } = target(sub.model, rest);
16380
+ if (!methods.result) throw missing3(adapter, ctx.model);
16381
+ const result = await methods.result(sub, ctx, webhook);
16382
+ const base = { ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit };
16383
+ const usage3 = sub.submittedAt === void 0 ? base : deps.timed(base, sub.submittedAt);
16384
+ await deps.emit(usage3);
16385
+ return { ...result, usage: usage3 };
16386
+ },
16387
+ async cancel(sub, call = {}) {
16388
+ const { methods, adapter, ctx } = target(sub.model, call);
16389
+ if (!methods.cancel) throw missing3(adapter, ctx.model);
16390
+ return methods.cancel(sub, ctx);
16391
+ }
16392
+ };
16393
+ }
16394
+
15513
16395
  // src/resolve-call.ts
15514
16396
  var MEDIA_METHODS = {
15515
16397
  text: [],
@@ -15525,7 +16407,10 @@ var MEDIA_METHODS = {
15525
16407
  lipsync: ["lipsync"],
15526
16408
  dubbing: ["dub"],
15527
16409
  transcription: ["transcribe"],
15528
- "video-tool": ["submitVideoTool"]
16410
+ "video-tool": ["submitVideoTool"],
16411
+ // 3D jobs run through submitModel3d, which checks the row type itself; their preflight
16412
+ // is model3dInputRefusal, not resolveOptions.
16413
+ model3d: []
15529
16414
  };
15530
16415
  var METHOD_NOUN = {
15531
16416
  generateImage: "an image model",
@@ -15722,10 +16607,10 @@ function textAbortOptions(sdk, context) {
15722
16607
  if (abortSignal) return { abortSignal };
15723
16608
  return {};
15724
16609
  }
15725
- var catalogId = z29.string();
15726
- var exactSize = z29.templateLiteral([z29.number(), "x", z29.number()]);
15727
- var sdkRatio = z29.templateLiteral([z29.number(), ":", z29.number()]);
15728
- var sizeTier = z29.enum(["512", "1K", "2K", "4K"]);
16610
+ var catalogId = z31.string();
16611
+ var exactSize = z31.templateLiteral([z31.number(), "x", z31.number()]);
16612
+ var sdkRatio = z31.templateLiteral([z31.number(), ":", z31.number()]);
16613
+ var sizeTier = z31.enum(["512", "1K", "2K", "4K"]);
15729
16614
  function isCatalogId(model) {
15730
16615
  return catalogId.safeParse(model).success;
15731
16616
  }
@@ -15835,19 +16720,14 @@ function createModelKit(config, adapters) {
15835
16720
  if (call.signal) ctx.signal = call.signal;
15836
16721
  return { adapter, ctx };
15837
16722
  }
15838
- function videoToolTarget(modelId, call) {
15839
- mediaRetryOptions(call);
15840
- const model = catalog.require(modelId);
15841
- assertMethod(model, "submitVideoTool");
15842
- return context(model, call, []);
15843
- }
15844
- function noVideoTools(adapter, model) {
15845
- return new ModelKitError({
15846
- code: "unsupported_option",
15847
- message: `${adapter.id} has no video tools`,
15848
- model: model.id
15849
- });
15850
- }
16723
+ const jobDeps = {
16724
+ catalog,
16725
+ context: (model, call) => context(model, call, []),
16726
+ timed,
16727
+ emit
16728
+ };
16729
+ const videoToolJobs = providerJobMethods(VIDEO_TOOL_JOB, jobDeps);
16730
+ const model3dJobs = providerJobMethods(MODEL3D_JOB, jobDeps);
15851
16731
  function timed(event, startedAt) {
15852
16732
  if (event.latencyMs !== void 0) return event;
15853
16733
  return { ...event, latencyMs: Math.max(0, Date.now() - startedAt) };
@@ -15863,8 +16743,8 @@ function createModelKit(config, adapters) {
15863
16743
  }
15864
16744
  }
15865
16745
  function withRowUnit(event) {
15866
- const row = catalog.get(event.model);
15867
- return row ? { ...event, unit: row.usage.unit } : event;
16746
+ const row2 = catalog.get(event.model);
16747
+ return row2 ? { ...event, unit: row2.usage.unit } : event;
15868
16748
  }
15869
16749
  function textTarget(model, call) {
15870
16750
  if (!isCatalogId(model)) {
@@ -16278,38 +17158,14 @@ function createModelKit(config, adapters) {
16278
17158
  usageProvider: provider
16279
17159
  };
16280
17160
  },
16281
- async submitVideoTool(req, call = {}) {
16282
- const { webhookUrl, ...rest } = call;
16283
- const { adapter, ctx } = videoToolTarget(req.model, rest);
16284
- if (!adapter.submitVideoTool) throw noVideoTools(adapter, ctx.model);
16285
- const submittedAt = Date.now();
16286
- const submission = await adapter.submitVideoTool(
16287
- req,
16288
- ctx,
16289
- webhookUrl !== void 0 ? { webhookUrl } : {}
16290
- );
16291
- return { ...submission, submittedAt };
16292
- },
16293
- async videoToolStatus(sub, call = {}) {
16294
- const { adapter, ctx } = videoToolTarget(sub.model, call);
16295
- if (!adapter.videoToolStatus) throw noVideoTools(adapter, ctx.model);
16296
- return adapter.videoToolStatus(sub, ctx);
16297
- },
16298
- async videoToolResult(sub, call = {}) {
16299
- const { webhook, ...rest } = call;
16300
- const { adapter, ctx } = videoToolTarget(sub.model, rest);
16301
- if (!adapter.videoToolResult) throw noVideoTools(adapter, ctx.model);
16302
- const result = await adapter.videoToolResult(sub, ctx, webhook);
16303
- const base = { ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit };
16304
- const usage3 = sub.submittedAt === void 0 ? base : timed(base, sub.submittedAt);
16305
- await emit(usage3);
16306
- return { ...result, usage: usage3 };
16307
- },
16308
- async cancelVideoTool(sub, call = {}) {
16309
- const { adapter, ctx } = videoToolTarget(sub.model, call);
16310
- if (!adapter.cancelVideoTool) throw noVideoTools(adapter, ctx.model);
16311
- return adapter.cancelVideoTool(sub, ctx);
16312
- },
17161
+ submitVideoTool: videoToolJobs.submit,
17162
+ videoToolStatus: videoToolJobs.status,
17163
+ videoToolResult: videoToolJobs.result,
17164
+ cancelVideoTool: videoToolJobs.cancel,
17165
+ submitModel3d: model3dJobs.submit,
17166
+ model3dStatus: model3dJobs.status,
17167
+ model3dResult: model3dJobs.result,
17168
+ cancelModel3d: model3dJobs.cancel,
16313
17169
  usageProvider(modelId, call = {}) {
16314
17170
  const entry = catalog.require(modelId);
16315
17171
  if (entry.type !== "text") return entry.adapter;
@@ -16456,6 +17312,8 @@ export {
16456
17312
  InputSpecSchema,
16457
17313
  JsonObjectSchema,
16458
17314
  JsonValueSchema,
17315
+ MODEL3D_IMAGE_SLOTS,
17316
+ MODEL3D_MODELS,
16459
17317
  MODELS,
16460
17318
  ModelKitError,
16461
17319
  SURFACES2 as SURFACES,
@@ -16498,6 +17356,14 @@ export {
16498
17356
  liveState,
16499
17357
  mergeTextProviderOptions,
16500
17358
  missingTierKeys,
17359
+ model3dCall,
17360
+ model3dConstraints,
17361
+ model3dInputRefusal,
17362
+ model3dPricingSku,
17363
+ model3dResolution,
17364
+ model3dSeedFits,
17365
+ model3dSkus,
17366
+ model3dTexture,
16501
17367
  nearestAspectRatio,
16502
17368
  normalizeExposure,
16503
17369
  openaiImageAdapter,