@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.cjs CHANGED
@@ -46,6 +46,8 @@ __export(index_exports, {
46
46
  InputSpecSchema: () => InputSpecSchema,
47
47
  JsonObjectSchema: () => JsonObjectSchema,
48
48
  JsonValueSchema: () => JsonValueSchema,
49
+ MODEL3D_IMAGE_SLOTS: () => MODEL3D_IMAGE_SLOTS,
50
+ MODEL3D_MODELS: () => MODEL3D_MODELS,
49
51
  MODELS: () => MODELS,
50
52
  ModelKitError: () => ModelKitError,
51
53
  SURFACES: () => SURFACES2,
@@ -88,6 +90,14 @@ __export(index_exports, {
88
90
  liveState: () => liveState,
89
91
  mergeTextProviderOptions: () => mergeTextProviderOptions,
90
92
  missingTierKeys: () => missingTierKeys,
93
+ model3dCall: () => model3dCall,
94
+ model3dConstraints: () => model3dConstraints,
95
+ model3dInputRefusal: () => model3dInputRefusal,
96
+ model3dPricingSku: () => model3dPricingSku,
97
+ model3dResolution: () => model3dResolution,
98
+ model3dSeedFits: () => model3dSeedFits,
99
+ model3dSkus: () => model3dSkus,
100
+ model3dTexture: () => model3dTexture,
91
101
  nearestAspectRatio: () => nearestAspectRatio,
92
102
  normalizeExposure: () => normalizeExposure,
93
103
  openaiImageAdapter: () => openaiImageAdapter,
@@ -265,18 +275,18 @@ function normalizeExposure(value) {
265
275
  if (value.every(
266
276
  (entry) => SURFACES.includes(entry)
267
277
  )) {
268
- const present = new Set(value);
269
- return SURFACES.filter((surface) => present.has(surface));
278
+ const present2 = new Set(value);
279
+ return SURFACES.filter((surface) => present2.has(surface));
270
280
  }
271
281
  return value;
272
282
  }
273
283
  return value;
274
284
  }
275
- function isListedOn(row, surface) {
276
- return row.lifecycle === "active" && row.exposure.includes(surface);
285
+ function isListedOn(row2, surface) {
286
+ return row2.lifecycle === "active" && row2.exposure.includes(surface);
277
287
  }
278
- function isListed(row) {
279
- return row.lifecycle === "active" && row.exposure.length > 0;
288
+ function isListed(row2) {
289
+ return row2.lifecycle === "active" && row2.exposure.length > 0;
280
290
  }
281
291
 
282
292
  // src/catalog/image-fal.ts
@@ -3678,6 +3688,197 @@ var MEDIA_NODE_MODELS = [
3678
3688
  SAM_3_IMAGE
3679
3689
  ];
3680
3690
 
3691
+ // src/catalog/model3d.ts
3692
+ var REQUEST_USAGE = { unit: "requests" };
3693
+ function row(id, label, spec, display) {
3694
+ return {
3695
+ id,
3696
+ aliases: [],
3697
+ label,
3698
+ type: "model3d",
3699
+ adapter: "fal",
3700
+ // The single-image endpoint; the adapter picks the endpoint a request needs.
3701
+ providerModelId: spec.endpoints.image ?? id,
3702
+ lifecycle: "active",
3703
+ exposure: ["space_builder"],
3704
+ constraints: { supports: [], model3d: spec },
3705
+ defaults: {},
3706
+ usage: REQUEST_USAGE,
3707
+ pricingKind: "flat",
3708
+ display
3709
+ };
3710
+ }
3711
+ var MODEL3D_MODELS = [
3712
+ row(
3713
+ "trellis-2",
3714
+ "Trellis 2",
3715
+ {
3716
+ family: "trellis",
3717
+ endpoints: { image: "fal-ai/trellis-2" },
3718
+ text: false,
3719
+ imageRequired: true,
3720
+ views: "none",
3721
+ maxImages: 1,
3722
+ texture: [],
3723
+ pbr: false,
3724
+ textureRef: false,
3725
+ seed: true,
3726
+ resolutions: { label: "Resolution", options: ["512", "1024", "1536"], default: "1024" }
3727
+ },
3728
+ {
3729
+ provider: "microsoft",
3730
+ description: "One photo to a detailed textured model. Fast and the best value.",
3731
+ sortOrder: 70
3732
+ }
3733
+ ),
3734
+ row(
3735
+ "hunyuan3d-3.1-pro",
3736
+ "Hunyuan3D 3.1 Pro",
3737
+ {
3738
+ family: "hunyuan",
3739
+ endpoints: {
3740
+ text: "fal-ai/hunyuan-3d/v3.1/pro/text-to-3d",
3741
+ image: "fal-ai/hunyuan-3d/v3.1/pro/image-to-3d"
3742
+ },
3743
+ text: true,
3744
+ imageRequired: false,
3745
+ views: "named",
3746
+ maxImages: 4,
3747
+ texture: ["none", "standard"],
3748
+ pbr: true,
3749
+ textureRef: false,
3750
+ seed: false
3751
+ },
3752
+ {
3753
+ provider: "tencent",
3754
+ description: "Photo-faithful models from a prompt, a photo, or a photo with back and side views.",
3755
+ sortOrder: 60
3756
+ }
3757
+ ),
3758
+ row(
3759
+ "tripo-h3.1",
3760
+ "Tripo H3.1",
3761
+ {
3762
+ family: "tripo",
3763
+ endpoints: {
3764
+ text: "tripo3d/h3.1/text-to-3d",
3765
+ image: "tripo3d/h3.1/image-to-3d",
3766
+ multiImage: "tripo3d/h3.1/multiview-to-3d"
3767
+ },
3768
+ text: true,
3769
+ imageRequired: false,
3770
+ views: "ordered",
3771
+ maxImages: 4,
3772
+ texture: ["none", "standard", "detailed"],
3773
+ pbr: true,
3774
+ textureRef: false,
3775
+ seed: true
3776
+ },
3777
+ {
3778
+ provider: "tripo",
3779
+ description: "Clean, game-ready models from a prompt, a photo or four views.",
3780
+ sortOrder: 50
3781
+ }
3782
+ ),
3783
+ row(
3784
+ "rodin-gen-2.5",
3785
+ "Rodin Gen-2.5",
3786
+ {
3787
+ family: "rodin",
3788
+ endpoints: {
3789
+ text: "fal-ai/hyper3d/rodin/v2.5/text-to-3d",
3790
+ image: "fal-ai/hyper3d/rodin/v2.5"
3791
+ },
3792
+ text: true,
3793
+ imageRequired: false,
3794
+ views: "unordered",
3795
+ maxImages: 5,
3796
+ texture: [],
3797
+ pbr: false,
3798
+ textureRef: false,
3799
+ seed: true,
3800
+ seedMax: 65535
3801
+ },
3802
+ {
3803
+ provider: "hyper3d",
3804
+ description: "Detailed PBR models from a prompt or up to five photos.",
3805
+ sortOrder: 40
3806
+ }
3807
+ ),
3808
+ row(
3809
+ "meshy-7.1",
3810
+ "Meshy 7.1",
3811
+ {
3812
+ family: "meshy",
3813
+ endpoints: {
3814
+ text: "meshy/v7.1/text-to-3d",
3815
+ image: "meshy/v7.1/image-to-3d",
3816
+ multiImage: "meshy/v7.1/multi-image-to-3d"
3817
+ },
3818
+ text: true,
3819
+ imageRequired: false,
3820
+ views: "unordered",
3821
+ maxImages: 4,
3822
+ texture: ["none", "standard"],
3823
+ pbr: true,
3824
+ textureRef: true,
3825
+ seed: true
3826
+ },
3827
+ {
3828
+ provider: "meshy",
3829
+ description: "Models from a prompt or photos, with a texture prompt or texture image to restyle.",
3830
+ sortOrder: 30
3831
+ }
3832
+ ),
3833
+ row(
3834
+ "hi3d-3.0",
3835
+ "Hi3D 3.0",
3836
+ {
3837
+ family: "hi3d",
3838
+ endpoints: {
3839
+ image: "hitem3d/hi3d/v3.0/image-to-3d",
3840
+ multiImage: "hitem3d/hi3d/v3.0/multi-view-to-3d"
3841
+ },
3842
+ text: false,
3843
+ imageRequired: true,
3844
+ views: "named",
3845
+ maxImages: 4,
3846
+ texture: ["none", "standard"],
3847
+ pbr: true,
3848
+ textureRef: false,
3849
+ seed: false,
3850
+ resolutions: { label: "Quality", options: ["quality", "master"], default: "quality" }
3851
+ },
3852
+ {
3853
+ provider: "hitem3d",
3854
+ description: "Highest-fidelity product models from a photo or four views. Slowest.",
3855
+ sortOrder: 20
3856
+ }
3857
+ ),
3858
+ row(
3859
+ "sam-3d-objects",
3860
+ "SAM 3D Objects",
3861
+ {
3862
+ family: "sam",
3863
+ endpoints: { image: "fal-ai/sam-3/3d-objects" },
3864
+ text: true,
3865
+ imageRequired: true,
3866
+ promptRequired: true,
3867
+ views: "none",
3868
+ maxImages: 1,
3869
+ texture: [],
3870
+ pbr: false,
3871
+ textureRef: false,
3872
+ seed: true
3873
+ },
3874
+ {
3875
+ provider: "meta",
3876
+ description: "Lifts one named object out of a real photo into a 3D model.",
3877
+ sortOrder: 10
3878
+ }
3879
+ )
3880
+ ];
3881
+
3681
3882
  // src/catalog/other.ts
3682
3883
  var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
3683
3884
  var ELEVENLABS_LOGO2 = "https://cdn.jsdelivr.net/npm/@lobehub/icons-static-png@1.97.0/light/elevenlabs.png";
@@ -5996,6 +6197,7 @@ var MODELS = [
5996
6197
  ...IMAGE_MODELS,
5997
6198
  ...VIDEO_MODELS,
5998
6199
  ...VIDEO_TOOL_MODELS,
6200
+ ...MODEL3D_MODELS,
5999
6201
  ...OTHER_MODELS,
6000
6202
  ...MEDIA_NODE_MODELS
6001
6203
  ];
@@ -6004,11 +6206,11 @@ var MODELS = [
6004
6206
  var import_zod3 = require("zod");
6005
6207
 
6006
6208
  // src/resolve-provider-rules.ts
6007
- function ruleRefusal(row, message, code) {
6209
+ function ruleRefusal(row2, message, code) {
6008
6210
  return new ModelKitError({
6009
6211
  code,
6010
- message: `${row.label}: ${message}`,
6011
- model: row.id,
6212
+ message: `${row2.label}: ${message}`,
6213
+ model: row2.id,
6012
6214
  retryable: false
6013
6215
  });
6014
6216
  }
@@ -6167,27 +6369,27 @@ function collisionIssues(rows) {
6167
6369
  const issues = [];
6168
6370
  const seenIds = /* @__PURE__ */ new Map();
6169
6371
  const seenAliases = /* @__PURE__ */ new Map();
6170
- rows.forEach((row, index) => {
6171
- if (seenIds.has(row.id)) {
6372
+ rows.forEach((row2, index) => {
6373
+ if (seenIds.has(row2.id)) {
6172
6374
  issues.push({
6173
6375
  index,
6174
6376
  path: ["id"],
6175
- message: `Duplicate model id "${row.id}"`
6377
+ message: `Duplicate model id "${row2.id}"`
6176
6378
  });
6177
6379
  } else {
6178
- const aliasOwner = seenAliases.get(row.id);
6380
+ const aliasOwner = seenAliases.get(row2.id);
6179
6381
  if (aliasOwner !== void 0) {
6180
6382
  issues.push({
6181
6383
  index: aliasOwner.index,
6182
6384
  path: ["aliases", aliasOwner.aliasIndex],
6183
- message: `Alias "${row.id}" collides with a model id`
6385
+ message: `Alias "${row2.id}" collides with a model id`
6184
6386
  });
6185
6387
  }
6186
- seenIds.set(row.id, index);
6388
+ seenIds.set(row2.id, index);
6187
6389
  }
6188
6390
  const local = /* @__PURE__ */ new Set();
6189
- for (const [aliasIndex, alias] of row.aliases.entries()) {
6190
- if (alias === row.id || seenIds.has(alias)) {
6391
+ for (const [aliasIndex, alias] of row2.aliases.entries()) {
6392
+ if (alias === row2.id || seenIds.has(alias)) {
6191
6393
  issues.push({
6192
6394
  index,
6193
6395
  path: ["aliases", aliasIndex],
@@ -6229,8 +6431,8 @@ var DEFAULT_CONVENTIONS = { referenceSyntax: "numbered" };
6229
6431
  var DefaultsReadView = import_zod.z.looseObject({
6230
6432
  generateAudio: import_zod.z.boolean().optional().catch(void 0)
6231
6433
  });
6232
- function promptConventions(row) {
6233
- const view = ConstraintsReadView.safeParse(row.constraints);
6434
+ function promptConventions(row2) {
6435
+ const view = ConstraintsReadView.safeParse(row2.constraints);
6234
6436
  const prompt = view.success ? view.data.prompt : void 0;
6235
6437
  if (prompt === void 0) return { ...DEFAULT_CONVENTIONS };
6236
6438
  const result = { referenceSyntax: prompt.referenceSyntax };
@@ -6241,22 +6443,111 @@ var RawConventionsView = import_zod.z.looseObject({
6241
6443
  audio: import_zod.z.unknown().optional(),
6242
6444
  prompt: import_zod.z.unknown().optional()
6243
6445
  });
6244
- function normaliseConventions(row) {
6245
- const view = RawConventionsView.safeParse(row.constraints);
6246
- if (!view.success) return { row, invalidKeys: [] };
6446
+ function normaliseConventions(row2) {
6447
+ const view = RawConventionsView.safeParse(row2.constraints);
6448
+ if (!view.success) return { row: row2, invalidKeys: [] };
6247
6449
  const { audio, prompt } = view.data;
6248
6450
  const badAudio = audio !== void 0 && !AudioOutputSchema.safeParse(audio).success;
6249
6451
  const badPrompt = prompt !== void 0 && !PromptConventionsSchema.safeParse(prompt).success;
6250
- if (!badAudio && !badPrompt) return { row, invalidKeys: [] };
6452
+ if (!badAudio && !badPrompt) return { row: row2, invalidKeys: [] };
6251
6453
  const invalidKeys = [];
6252
6454
  if (badAudio) invalidKeys.push("constraints.audio");
6253
6455
  if (badPrompt) invalidKeys.push("constraints.prompt");
6254
- const entries = Object.entries(row.constraints).flatMap(([key, value]) => {
6456
+ const entries = Object.entries(row2.constraints).flatMap(([key, value]) => {
6255
6457
  if (key === "audio" && badAudio) return [];
6256
- if (key === "prompt" && badPrompt) return [[key, promptConventions(row)]];
6458
+ if (key === "prompt" && badPrompt) return [[key, promptConventions(row2)]];
6257
6459
  return [[key, value]];
6258
6460
  });
6259
- return { row: { ...row, constraints: Object.fromEntries(entries) }, invalidKeys };
6461
+ return { row: { ...row2, constraints: Object.fromEntries(entries) }, invalidKeys };
6462
+ }
6463
+
6464
+ // src/catalog/model3d-spec.ts
6465
+ function model3dConstraints(row2) {
6466
+ if (row2.type !== "model3d") return void 0;
6467
+ return row2.constraints.model3d;
6468
+ }
6469
+ var MODEL3D_IMAGE_SLOTS = {
6470
+ none: ["image"],
6471
+ named: ["image", "back", "left", "right"],
6472
+ ordered: ["image", "left", "back", "right"],
6473
+ unordered: ["image", "back", "left", "right", "top"]
6474
+ };
6475
+ function model3dInputRefusal(spec, wired) {
6476
+ const top = spec.views === "unordered" && wired.top === true;
6477
+ const anyView = spec.views !== "none" && (wired.back || wired.left || wired.right || top);
6478
+ if (anyView && !wired.image) return "model3d_views_need_image";
6479
+ if (spec.imageRequired && !wired.image) return "model3d_needs_image";
6480
+ if (spec.promptRequired && !wired.prompt) return "model3d_needs_prompt";
6481
+ if (!wired.image && !(spec.text && wired.prompt)) return "model3d_needs_input";
6482
+ if (spec.views === "ordered") {
6483
+ if ((wired.back || wired.right) && !wired.left) return "model3d_views_out_of_order";
6484
+ if (wired.right && !wired.back) return "model3d_views_out_of_order";
6485
+ }
6486
+ return null;
6487
+ }
6488
+ function model3dSeedFits(spec, seed) {
6489
+ return Number.isSafeInteger(seed) && seed >= 0 && seed <= (spec.seedMax ?? Number.MAX_SAFE_INTEGER);
6490
+ }
6491
+ function model3dTexture(spec, requested) {
6492
+ if (requested !== void 0 && spec.texture.includes(requested)) return requested;
6493
+ return spec.texture.includes("standard") ? "standard" : spec.texture[0] ?? "standard";
6494
+ }
6495
+ function model3dResolution(spec, requested) {
6496
+ const res = spec.resolutions;
6497
+ if (res === void 0) return void 0;
6498
+ return requested !== void 0 && res.options.includes(requested) ? requested : res.default;
6499
+ }
6500
+ function model3dPricingSku(row2, options, inputs) {
6501
+ const spec = model3dConstraints(row2);
6502
+ if (spec === void 0) throw new Error(`${row2.id} is not a 3D model`);
6503
+ const texture = model3dTexture(spec, options.texture);
6504
+ const textured = spec.texture.length > 0 && texture !== "none";
6505
+ const pbr = spec.pbr && textured && options.pbr === true;
6506
+ const resolution = model3dResolution(spec, options.resolution);
6507
+ switch (spec.family) {
6508
+ case "meshy":
6509
+ return `${row2.id}__${textured ? "textured" : "untextured"}`;
6510
+ case "tripo":
6511
+ return `${row2.id}__${inputs.image ? "image" : "text"}__${texture}`;
6512
+ case "hunyuan":
6513
+ return `${row2.id}${pbr ? "__pbr" : ""}${inputs.views ? "__views" : ""}`;
6514
+ case "trellis":
6515
+ return `${row2.id}__${resolution}`;
6516
+ case "hi3d":
6517
+ return `${row2.id}__${resolution}__${textured ? pbr ? "texture-pbr" : "texture" : "geometry"}`;
6518
+ case "rodin":
6519
+ case "sam":
6520
+ return row2.id;
6521
+ }
6522
+ }
6523
+ function model3dSkus(row2) {
6524
+ const spec = model3dConstraints(row2);
6525
+ if (spec === void 0) return [];
6526
+ const textures = spec.texture.length > 0 ? spec.texture : [void 0];
6527
+ const pbrs = spec.pbr ? [false, true] : [false];
6528
+ const resolutions = spec.resolutions?.options ?? [void 0];
6529
+ const images = spec.text && !spec.imageRequired ? [true, false] : [true];
6530
+ const views = spec.views === "none" ? [false] : [false, true];
6531
+ const skus = /* @__PURE__ */ new Set();
6532
+ for (const texture of textures)
6533
+ for (const pbr of pbrs)
6534
+ for (const resolution of resolutions)
6535
+ for (const image of images)
6536
+ for (const view of views) {
6537
+ if (view && !image) continue;
6538
+ skus.add(
6539
+ model3dPricingSku(
6540
+ row2,
6541
+ {
6542
+ ...texture !== void 0 && { texture },
6543
+ pbr,
6544
+ ...resolution !== void 0 && { resolution }
6545
+ },
6546
+ { image, views: view }
6547
+ )
6548
+ );
6549
+ }
6550
+ return [...skus].sort();
6260
6551
  }
6261
6552
 
6262
6553
  // src/catalog/input-spec.ts
@@ -6407,7 +6698,7 @@ function isInputSpecKey(key) {
6407
6698
  function isArrayInputSpecKey(key) {
6408
6699
  return ARRAY_KEY_SET.has(key);
6409
6700
  }
6410
- function validateInputSpec(raw, row) {
6701
+ function validateInputSpec(raw, row2) {
6411
6702
  const parsed = InputSpecSchema.safeParse(raw);
6412
6703
  if (!parsed.success) {
6413
6704
  return {
@@ -6419,7 +6710,7 @@ function validateInputSpec(raw, row) {
6419
6710
  };
6420
6711
  }
6421
6712
  const spec = parsed.data;
6422
- const supportedTypes = TYPES_BY_ADAPTER.get(row.adapter);
6713
+ const supportedTypes = TYPES_BY_ADAPTER.get(row2.adapter);
6423
6714
  if (supportedTypes === void 0) {
6424
6715
  return {
6425
6716
  ok: false,
@@ -6432,18 +6723,18 @@ function validateInputSpec(raw, row) {
6432
6723
  };
6433
6724
  }
6434
6725
  const issues = [];
6435
- const allowed = ALLOWED_KEYS_BY_TYPE.get(row.type);
6436
- if (allowed === void 0 || !supportedTypes.includes(row.type)) {
6726
+ const allowed = ALLOWED_KEYS_BY_TYPE.get(row2.type);
6727
+ if (allowed === void 0 || !supportedTypes.includes(row2.type)) {
6437
6728
  issues.push({
6438
6729
  path: [],
6439
- 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`
6730
+ 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`
6440
6731
  });
6441
6732
  } else {
6442
6733
  for (const key of Object.keys(spec.fields)) {
6443
6734
  if (!allowed.has(key)) {
6444
6735
  issues.push({
6445
6736
  path: ["fields", key],
6446
- message: `inputSpec.fields "${key}" is not supported for ${row.type} rows`
6737
+ message: `inputSpec.fields "${key}" is not supported for ${row2.type} rows`
6447
6738
  });
6448
6739
  }
6449
6740
  }
@@ -6451,13 +6742,13 @@ function validateInputSpec(raw, row) {
6451
6742
  if (!allowed.has(key)) {
6452
6743
  issues.push({
6453
6744
  path: ["values", key],
6454
- message: `inputSpec.values "${key}" is not supported for ${row.type} rows`
6745
+ message: `inputSpec.values "${key}" is not supported for ${row2.type} rows`
6455
6746
  });
6456
6747
  }
6457
6748
  }
6458
6749
  }
6459
6750
  if (spec.editEndpoint !== void 0) {
6460
- if (row.adapter !== "fal") {
6751
+ if (row2.adapter !== "fal") {
6461
6752
  issues.push({
6462
6753
  path: ["editEndpoint"],
6463
6754
  message: "inputSpec.editEndpoint is only supported on fal rows"
@@ -6501,7 +6792,7 @@ function validateInputSpec(raw, row) {
6501
6792
  if (allowed !== void 0 && !allowed.has(key)) {
6502
6793
  issues.push({
6503
6794
  path: ["arrays", name],
6504
- message: `inputSpec.arrays "${key}" is not supported for ${row.type} rows`
6795
+ message: `inputSpec.arrays "${key}" is not supported for ${row2.type} rows`
6505
6796
  });
6506
6797
  }
6507
6798
  if (key in spec.fields) {
@@ -6521,7 +6812,7 @@ function validateInputSpec(raw, row) {
6521
6812
  }
6522
6813
  }
6523
6814
  if (spec.dimensions !== void 0) {
6524
- if (row.type !== "image") {
6815
+ if (row2.type !== "image") {
6525
6816
  issues.push({
6526
6817
  path: ["dimensions"],
6527
6818
  message: "inputSpec.dimensions is only supported on image rows"
@@ -6543,7 +6834,7 @@ function validateInputSpec(raw, row) {
6543
6834
  });
6544
6835
  }
6545
6836
  }
6546
- const supports = row.constraints.supports ?? [];
6837
+ const supports = row2.constraints.supports ?? [];
6547
6838
  for (const key of INPUT_SPEC_SUPPORTS_KEYS) {
6548
6839
  if (supports.includes(key)) continue;
6549
6840
  if (key in spec.fields) {
@@ -6588,8 +6879,8 @@ function listIssues(name, values, fallback, defaultKey) {
6588
6879
  }
6589
6880
  return issues;
6590
6881
  }
6591
- function optionListIssues(row) {
6592
- const { constraints, defaults } = row;
6882
+ function optionListIssues(row2) {
6883
+ const { constraints, defaults } = row2;
6593
6884
  const issues = [
6594
6885
  ...listIssues(
6595
6886
  "voices",
@@ -6647,7 +6938,8 @@ var ModelTypeSchema = import_zod3.z.enum([
6647
6938
  "voice-change",
6648
6939
  "dubbing",
6649
6940
  "lipsync",
6650
- "transcription"
6941
+ "transcription",
6942
+ "model3d"
6651
6943
  ]);
6652
6944
  var LifecycleSchema = import_zod3.z.enum(["active", "deprecated", "retired"]);
6653
6945
  var SurfaceSchema = import_zod3.z.enum(["cowork", "space_builder"]);
@@ -6711,7 +7003,8 @@ var UsageUnitSchema = import_zod3.z.enum([
6711
7003
  "images",
6712
7004
  "seconds",
6713
7005
  "reported_cost_usd",
6714
- "compute_seconds"
7006
+ "compute_seconds",
7007
+ "requests"
6715
7008
  ]);
6716
7009
  var PricingKindSchema = import_zod3.z.enum(["token", "image_size", "video_per_second", "flat"]);
6717
7010
  var ProviderOptionValueSchema = import_zod3.z.lazy(
@@ -6765,6 +7058,156 @@ var LanguageOptionSchema = import_zod3.z.looseObject({
6765
7058
  code: import_zod3.z.string().min(1),
6766
7059
  name: import_zod3.z.string().min(1)
6767
7060
  });
7061
+ var MODEL3D_FAMILY_RULES = {
7062
+ trellis: {
7063
+ textPath: false,
7064
+ views: ["none"],
7065
+ multiImage: false,
7066
+ texture: null,
7067
+ pbr: false,
7068
+ seed: true,
7069
+ textureRef: false,
7070
+ resolutions: "integer"
7071
+ },
7072
+ hunyuan: {
7073
+ textPath: true,
7074
+ views: ["none", "named"],
7075
+ multiImage: false,
7076
+ texture: ["none", "standard"],
7077
+ pbr: true,
7078
+ seed: false,
7079
+ textureRef: false,
7080
+ resolutions: null
7081
+ },
7082
+ tripo: {
7083
+ textPath: true,
7084
+ views: ["none", "ordered"],
7085
+ multiImage: true,
7086
+ texture: ["none", "standard", "detailed"],
7087
+ pbr: true,
7088
+ seed: true,
7089
+ textureRef: false,
7090
+ resolutions: null
7091
+ },
7092
+ rodin: {
7093
+ textPath: true,
7094
+ views: ["none", "unordered"],
7095
+ multiImage: false,
7096
+ texture: null,
7097
+ pbr: false,
7098
+ seed: true,
7099
+ textureRef: false,
7100
+ resolutions: null
7101
+ },
7102
+ meshy: {
7103
+ textPath: true,
7104
+ views: ["none", "unordered"],
7105
+ multiImage: true,
7106
+ texture: ["none", "standard"],
7107
+ pbr: true,
7108
+ seed: true,
7109
+ textureRef: true,
7110
+ resolutions: null
7111
+ },
7112
+ hi3d: {
7113
+ textPath: false,
7114
+ views: ["none", "named"],
7115
+ multiImage: true,
7116
+ texture: ["none", "standard"],
7117
+ pbr: true,
7118
+ seed: false,
7119
+ textureRef: false,
7120
+ resolutions: ["quality", "master"]
7121
+ },
7122
+ sam: {
7123
+ textPath: false,
7124
+ views: ["none"],
7125
+ multiImage: false,
7126
+ texture: null,
7127
+ pbr: false,
7128
+ seed: true,
7129
+ textureRef: false,
7130
+ resolutions: null
7131
+ }
7132
+ };
7133
+ function model3dSpecIssues(spec) {
7134
+ const issues = [];
7135
+ const add = (path, message) => issues.push({ path, message });
7136
+ const rules = MODEL3D_FAMILY_RULES[spec.family];
7137
+ const promptOnly = spec.text && !spec.imageRequired;
7138
+ if (spec.endpoints.image === void 0)
7139
+ add(["endpoints", "image"], "every row needs an image endpoint");
7140
+ if (promptOnly && !rules.textPath) {
7141
+ add(
7142
+ ["imageRequired"],
7143
+ `${spec.family} has no text-to-3D endpoint; a text row needs an image`
7144
+ );
7145
+ }
7146
+ if (promptOnly && spec.endpoints.text === void 0) {
7147
+ add(["endpoints", "text"], "a text row needs a text endpoint");
7148
+ }
7149
+ if (!rules.views.includes(spec.views)) {
7150
+ add(["views"], `${spec.family} takes views ${rules.views.join(" or ")}`);
7151
+ }
7152
+ if (spec.views === "none" && spec.maxImages !== 1) {
7153
+ add(["maxImages"], "a row without views takes 1 image");
7154
+ }
7155
+ if (spec.views === "unordered" && spec.maxImages < 2) {
7156
+ add(["maxImages"], "a row with views takes at least 2 images");
7157
+ }
7158
+ const slots = MODEL3D_IMAGE_SLOTS[spec.views].length;
7159
+ if (spec.views !== "none" && spec.maxImages > slots) {
7160
+ add(["maxImages"], `a row with ${spec.views} views sends at most ${slots} images`);
7161
+ }
7162
+ if ((spec.views === "named" || spec.views === "ordered") && spec.maxImages < slots) {
7163
+ add(
7164
+ ["maxImages"],
7165
+ `a row with ${spec.views} views takes ${slots} images (front and three sides)`
7166
+ );
7167
+ }
7168
+ if (spec.views !== "none" && rules.multiImage && spec.endpoints.multiImage === void 0) {
7169
+ add(["endpoints", "multiImage"], `${spec.family} sends views to a multi-image endpoint`);
7170
+ }
7171
+ if (rules.texture === null) {
7172
+ if (spec.texture.length > 0) add(["texture"], `${spec.family} has no texture switch`);
7173
+ } else {
7174
+ const allowed = rules.texture;
7175
+ if (spec.texture.length === 0) add(["texture"], `${spec.family} needs its texture options`);
7176
+ if (new Set(spec.texture).size !== spec.texture.length)
7177
+ add(["texture"], "texture options repeat");
7178
+ for (const t of spec.texture) {
7179
+ if (!allowed.includes(t)) add(["texture"], `${spec.family} has no "${t}" texture`);
7180
+ }
7181
+ }
7182
+ if (spec.pbr && !rules.pbr) add(["pbr"], `${spec.family} has no PBR switch`);
7183
+ if (spec.pbr && !spec.texture.some((t) => t !== "none")) {
7184
+ add(["pbr"], "PBR needs a textured option");
7185
+ }
7186
+ if (spec.seed && !rules.seed) add(["seed"], `${spec.family} takes no seed`);
7187
+ if (spec.seedMax !== void 0 && !spec.seed) add(["seedMax"], "seedMax needs seed");
7188
+ if (spec.textureRef && !rules.textureRef)
7189
+ add(["textureRef"], `${spec.family} takes no texture reference`);
7190
+ const res = spec.resolutions;
7191
+ if (rules.resolutions === null) {
7192
+ if (res !== void 0) add(["resolutions"], `${spec.family} has no resolution option`);
7193
+ } else if (res === void 0) {
7194
+ add(["resolutions"], `${spec.family} needs its resolution options`);
7195
+ } else {
7196
+ if (!res.options.includes(res.default)) {
7197
+ add(["resolutions", "default"], "default must be an option");
7198
+ }
7199
+ if (new Set(res.options).size !== res.options.length) {
7200
+ add(["resolutions", "options"], "resolution options repeat");
7201
+ }
7202
+ const allowed = rules.resolutions;
7203
+ for (const option of res.options) {
7204
+ const ok = allowed === "integer" ? /^[1-9][0-9]*$/.test(option) : allowed.includes(option);
7205
+ if (!ok)
7206
+ add(["resolutions", "options"], `${spec.family} has no "${option}" resolution`);
7207
+ }
7208
+ }
7209
+ return issues;
7210
+ }
6768
7211
  var VideoToolConstraintsSchema = import_zod3.z.looseObject({
6769
7212
  kind: import_zod3.z.enum(["upscale", "interpolate", "hdr", "bg-remove", "subtitles"]),
6770
7213
  upscaleFactor: RangeSchema.optional(),
@@ -6781,6 +7224,30 @@ var VideoToolConstraintsSchema = import_zod3.z.looseObject({
6781
7224
  translationLanguages: import_zod3.z.array(import_zod3.z.string().min(1)).min(1).optional(),
6782
7225
  maxSecondsAbove1080p: import_zod3.z.number().positive().optional()
6783
7226
  });
7227
+ var Model3dTextureSchema = import_zod3.z.enum(["none", "standard", "detailed"]);
7228
+ var Model3dConstraintsSchema = import_zod3.z.looseObject({
7229
+ family: import_zod3.z.enum(["trellis", "hunyuan", "tripo", "rodin", "meshy", "hi3d", "sam"]),
7230
+ endpoints: import_zod3.z.looseObject({
7231
+ text: import_zod3.z.string().min(1).optional(),
7232
+ image: import_zod3.z.string().min(1).optional(),
7233
+ multiImage: import_zod3.z.string().min(1).optional()
7234
+ }),
7235
+ text: import_zod3.z.boolean(),
7236
+ imageRequired: import_zod3.z.boolean(),
7237
+ promptRequired: import_zod3.z.boolean().optional(),
7238
+ views: import_zod3.z.enum(["none", "unordered", "ordered", "named"]),
7239
+ maxImages: import_zod3.z.number().int().positive(),
7240
+ texture: import_zod3.z.array(Model3dTextureSchema),
7241
+ pbr: import_zod3.z.boolean(),
7242
+ textureRef: import_zod3.z.boolean(),
7243
+ seed: import_zod3.z.boolean(),
7244
+ seedMax: import_zod3.z.number().int().positive().optional(),
7245
+ resolutions: import_zod3.z.looseObject({
7246
+ label: import_zod3.z.string().min(1),
7247
+ options: import_zod3.z.array(import_zod3.z.string().min(1)).min(1),
7248
+ default: import_zod3.z.string().min(1)
7249
+ }).optional()
7250
+ });
6784
7251
  var ModelConstraintsSchema = import_zod3.z.looseObject({
6785
7252
  aspectRatios: import_zod3.z.array(AspectRatioSchema).optional(),
6786
7253
  sizes: import_zod3.z.array(ImageSizeSchema).optional(),
@@ -6808,6 +7275,7 @@ var ModelConstraintsSchema = import_zod3.z.looseObject({
6808
7275
  returns: import_zod3.z.enum(["new", "joined"]).optional()
6809
7276
  }).optional(),
6810
7277
  tool: VideoToolConstraintsSchema.optional(),
7278
+ model3d: Model3dConstraintsSchema.optional(),
6811
7279
  // Loose on purpose: the read path keeps a row whose value is invalid (the accessors in
6812
7280
  // conventions.ts read it as "not set"); CatalogModelSchema below rejects it on write.
6813
7281
  audio: import_zod3.z.unknown().optional(),
@@ -6923,29 +7391,47 @@ var CatalogModelSchemaBase = import_zod3.z.looseObject({
6923
7391
  pricingKind: PricingKindSchema,
6924
7392
  display: CatalogDisplaySchema.optional(),
6925
7393
  capabilities: CatalogCapabilitiesSchema.optional()
6926
- }).superRefine((row, ctx) => {
6927
- if (row.lifecycle === "active" && !row.display) {
7394
+ }).superRefine((row2, ctx) => {
7395
+ if (row2.lifecycle === "active" && !row2.display) {
6928
7396
  ctx.addIssue({
6929
7397
  code: "custom",
6930
7398
  path: ["display"],
6931
7399
  message: "active rows need display"
6932
7400
  });
6933
7401
  }
6934
- if (row.lifecycle === "active" && row.type === "text" && !row.capabilities?.contextWindow) {
7402
+ if (row2.lifecycle === "active" && row2.type === "text" && !row2.capabilities?.contextWindow) {
6935
7403
  ctx.addIssue({
6936
7404
  code: "custom",
6937
7405
  path: ["capabilities", "contextWindow"],
6938
7406
  message: "active text rows need contextWindow"
6939
7407
  });
6940
7408
  }
6941
- if (row.type === "video-tool" && row.constraints.tool === void 0) {
7409
+ if (row2.type === "video-tool" && row2.constraints.tool === void 0) {
6942
7410
  ctx.addIssue({
6943
7411
  code: "custom",
6944
7412
  path: ["constraints", "tool"],
6945
7413
  message: "video-tool rows need constraints.tool"
6946
7414
  });
6947
7415
  }
6948
- if (row.replacedBy !== void 0 && row.replacedBy === row.id) {
7416
+ if (row2.type === "model3d") {
7417
+ const spec = row2.constraints.model3d;
7418
+ if (spec === void 0) {
7419
+ ctx.addIssue({
7420
+ code: "custom",
7421
+ path: ["constraints", "model3d"],
7422
+ message: "model3d rows need constraints.model3d"
7423
+ });
7424
+ } else {
7425
+ for (const issue of model3dSpecIssues(spec)) {
7426
+ ctx.addIssue({
7427
+ code: "custom",
7428
+ path: ["constraints", "model3d", ...issue.path],
7429
+ message: issue.message
7430
+ });
7431
+ }
7432
+ }
7433
+ }
7434
+ if (row2.replacedBy !== void 0 && row2.replacedBy === row2.id) {
6949
7435
  ctx.addIssue({
6950
7436
  code: "custom",
6951
7437
  path: ["replacedBy"],
@@ -6954,8 +7440,8 @@ var CatalogModelSchemaBase = import_zod3.z.looseObject({
6954
7440
  }
6955
7441
  });
6956
7442
  var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6957
- (row, ctx) => {
6958
- const transport = row.providerOptions?.["modelkit"]?.["transport"];
7443
+ (row2, ctx) => {
7444
+ const transport = row2.providerOptions?.["modelkit"]?.["transport"];
6959
7445
  if (transport !== void 0 && transport !== "direct" && transport !== "bedrock") {
6960
7446
  ctx.addIssue({
6961
7447
  code: "custom",
@@ -6963,9 +7449,9 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6963
7449
  message: 'transport must be "direct" or "bedrock"'
6964
7450
  });
6965
7451
  }
6966
- const inputSpecRaw = row.providerOptions?.["modelkit"]?.["inputSpec"];
7452
+ const inputSpecRaw = row2.providerOptions?.["modelkit"]?.["inputSpec"];
6967
7453
  if (inputSpecRaw !== void 0) {
6968
- const result = validateInputSpec(inputSpecRaw, row);
7454
+ const result = validateInputSpec(inputSpecRaw, row2);
6969
7455
  if (!result.ok) {
6970
7456
  for (const issue of result.issues) {
6971
7457
  ctx.addIssue({
@@ -6976,7 +7462,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6976
7462
  }
6977
7463
  }
6978
7464
  }
6979
- const audio = row.constraints.audio;
7465
+ const audio = row2.constraints.audio;
6980
7466
  if (audio !== void 0 && !AudioOutputSchema.safeParse(audio).success) {
6981
7467
  ctx.addIssue({
6982
7468
  code: "custom",
@@ -6984,7 +7470,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6984
7470
  message: 'audio must be "always", "optional" or "never"'
6985
7471
  });
6986
7472
  }
6987
- const refs = row.constraints.references;
7473
+ const refs = row2.constraints.references;
6988
7474
  for (const kind of ["images", "videos", "audios"]) {
6989
7475
  const least = refs?.min?.[kind];
6990
7476
  const most = refs?.[kind];
@@ -6996,10 +7482,10 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
6996
7482
  });
6997
7483
  }
6998
7484
  }
6999
- for (const issue of optionListIssues(row)) {
7485
+ for (const issue of optionListIssues(row2)) {
7000
7486
  ctx.addIssue({ code: "custom", path: issue.path, message: issue.message });
7001
7487
  }
7002
- const prompt = row.constraints.prompt;
7488
+ const prompt = row2.constraints.prompt;
7003
7489
  if (prompt !== void 0) {
7004
7490
  const parsed = PromptConventionsSchema.safeParse(prompt);
7005
7491
  if (!parsed.success) {
@@ -7014,7 +7500,7 @@ var CatalogModelSchema = CatalogModelSchemaBase.superRefine(
7014
7500
  }
7015
7501
  }
7016
7502
  );
7017
- var CatalogSchema = import_zod3.z.array(CatalogModelSchemaBase.transform((row) => normaliseConventions(row).row)).superRefine((rows, ctx) => {
7503
+ var CatalogSchema = import_zod3.z.array(CatalogModelSchemaBase.transform((row2) => normaliseConventions(row2).row)).superRefine((rows, ctx) => {
7018
7504
  for (const issue of collisionIssues(rows)) {
7019
7505
  ctx.addIssue({
7020
7506
  code: "custom",
@@ -8017,7 +8503,7 @@ async function generateSeedanceVideo(req, ctx) {
8017
8503
  }
8018
8504
 
8019
8505
  // src/adapters/fal.ts
8020
- var import_zod18 = require("zod");
8506
+ var import_zod20 = require("zod");
8021
8507
  var import_client = require("@fal-ai/client");
8022
8508
 
8023
8509
  // src/adapters/fal-http.ts
@@ -8322,7 +8808,7 @@ async function passthroughVideoJob(ctx, endpoint, input, decode) {
8322
8808
  }
8323
8809
 
8324
8810
  // src/adapters/fal-video-tools.ts
8325
- var import_zod12 = require("zod");
8811
+ var import_zod13 = require("zod");
8326
8812
 
8327
8813
  // src/video-length.ts
8328
8814
  function tenths(seconds3) {
@@ -8413,28 +8899,99 @@ function subtitleFields(tool, options) {
8413
8899
  return out;
8414
8900
  }
8415
8901
 
8416
- // src/catalog/video-tools-spec.ts
8902
+ // src/adapters/fal-queue.ts
8417
8903
  var import_zod11 = require("zod");
8418
- var RangeSchema2 = import_zod11.z.object({ min: import_zod11.z.number(), max: import_zod11.z.number() });
8419
- var ToolSchema = import_zod11.z.object({
8420
- kind: import_zod11.z.enum(["upscale", "interpolate", "hdr", "bg-remove", "subtitles"]),
8904
+ var FAL_QUEUE_ORIGIN = "https://queue.fal.run";
8905
+ var queueUrlSchema = import_zod11.z.url().refine((value) => new URL(value).origin === FAL_QUEUE_ORIGIN, {
8906
+ message: "not a fal queue URL"
8907
+ });
8908
+ var submitResponseSchema = import_zod11.z.object({
8909
+ request_id: import_zod11.z.string().min(1),
8910
+ status_url: queueUrlSchema,
8911
+ response_url: queueUrlSchema,
8912
+ cancel_url: queueUrlSchema
8913
+ });
8914
+ var statusResponseSchema = import_zod11.z.object({ status: import_zod11.z.string() });
8915
+ var falWebhookBodySchema = import_zod11.z.object({
8916
+ request_id: import_zod11.z.string().min(1),
8917
+ gateway_request_id: import_zod11.z.string().nullish(),
8918
+ status: import_zod11.z.enum(["OK", "ERROR"]),
8919
+ payload: JsonValueSchema.nullish(),
8920
+ error: import_zod11.z.string().nullish(),
8921
+ payload_error: JsonValueSchema.nullish()
8922
+ });
8923
+ async function queueFetch(ctx, url, method, body) {
8924
+ const payload = body === void 0 ? void 0 : JSON.stringify(body);
8925
+ try {
8926
+ if (ctx.routing.fal === "cloudflare-passthrough") {
8927
+ return await gatewayFetch(gatewayConfig(ctx), ctx.fetch, url, {
8928
+ method,
8929
+ ...payload !== void 0 && { body: payload }
8930
+ });
8931
+ }
8932
+ const falKey = ctx.keys.fal;
8933
+ if (!falKey) {
8934
+ throw new ModelKitError({
8935
+ code: "auth",
8936
+ message: "Missing API key for fal",
8937
+ provider: "fal",
8938
+ model: ctx.model.id,
8939
+ retryable: false
8940
+ });
8941
+ }
8942
+ return await ctx.fetch(url, {
8943
+ method,
8944
+ headers: {
8945
+ Authorization: `Key ${falKey}`,
8946
+ ...payload !== void 0 && { "Content-Type": "application/json" }
8947
+ },
8948
+ ...payload !== void 0 && { body: payload },
8949
+ ...ctx.signal !== void 0 && { signal: ctx.signal }
8950
+ });
8951
+ } catch (cause) {
8952
+ if (cause instanceof ModelKitError) throw cause;
8953
+ throw classifyThrown("fal", cause, ctx.model.id);
8954
+ }
8955
+ }
8956
+ async function readJson(ctx, res) {
8957
+ if (!res.ok) throw falError(res.status, await readBody(res), ctx.model.id);
8958
+ return JsonValueSchema.parse(await res.json());
8959
+ }
8960
+ function checkedQueueUrl(ctx, url, what) {
8961
+ if (!queueUrlSchema.safeParse(url).success) {
8962
+ throw new ModelKitError({
8963
+ code: "provider_rejected",
8964
+ message: `${what} submission carries a URL outside fal's queue`,
8965
+ provider: "fal",
8966
+ model: ctx.model.id,
8967
+ retryable: false
8968
+ });
8969
+ }
8970
+ return url;
8971
+ }
8972
+
8973
+ // src/catalog/video-tools-spec.ts
8974
+ var import_zod12 = require("zod");
8975
+ var RangeSchema2 = import_zod12.z.object({ min: import_zod12.z.number(), max: import_zod12.z.number() });
8976
+ var ToolSchema = import_zod12.z.object({
8977
+ kind: import_zod12.z.enum(["upscale", "interpolate", "hdr", "bg-remove", "subtitles"]),
8421
8978
  upscaleFactor: RangeSchema2.optional(),
8422
- maxOutputLongEdge: import_zod11.z.number().positive().optional(),
8423
- prompt: import_zod11.z.boolean().optional(),
8979
+ maxOutputLongEdge: import_zod12.z.number().positive().optional(),
8980
+ prompt: import_zod12.z.boolean().optional(),
8424
8981
  fps: RangeSchema2.optional(),
8425
- outputFormats: import_zod11.z.array(import_zod11.z.enum(["h265", "prores", "exr"])).min(1).optional(),
8426
- maxOutputShortEdge: import_zod11.z.number().positive().optional(),
8427
- maxOutputFrames: import_zod11.z.number().positive().optional(),
8428
- minOutputFrames: import_zod11.z.number().positive().optional(),
8429
- maxOutputFps: import_zod11.z.number().positive().optional(),
8430
- presets: import_zod11.z.array(import_zod11.z.string().min(1)).min(1).optional(),
8431
- languages: import_zod11.z.array(import_zod11.z.string().min(1)).min(1).optional(),
8432
- translationLanguages: import_zod11.z.array(import_zod11.z.string().min(1)).min(1).optional(),
8433
- maxSecondsAbove1080p: import_zod11.z.number().positive().optional()
8982
+ outputFormats: import_zod12.z.array(import_zod12.z.enum(["h265", "prores", "exr"])).min(1).optional(),
8983
+ maxOutputShortEdge: import_zod12.z.number().positive().optional(),
8984
+ maxOutputFrames: import_zod12.z.number().positive().optional(),
8985
+ minOutputFrames: import_zod12.z.number().positive().optional(),
8986
+ maxOutputFps: import_zod12.z.number().positive().optional(),
8987
+ presets: import_zod12.z.array(import_zod12.z.string().min(1)).min(1).optional(),
8988
+ languages: import_zod12.z.array(import_zod12.z.string().min(1)).min(1).optional(),
8989
+ translationLanguages: import_zod12.z.array(import_zod12.z.string().min(1)).min(1).optional(),
8990
+ maxSecondsAbove1080p: import_zod12.z.number().positive().optional()
8434
8991
  });
8435
- function videoToolConstraints(row) {
8436
- if (row.type !== "video-tool") return void 0;
8437
- const parsed = ToolSchema.safeParse(row.constraints.tool);
8992
+ function videoToolConstraints(row2) {
8993
+ if (row2.type !== "video-tool") return void 0;
8994
+ const parsed = ToolSchema.safeParse(row2.constraints.tool);
8438
8995
  if (!parsed.success) return void 0;
8439
8996
  const {
8440
8997
  kind,
@@ -8481,16 +9038,16 @@ function resolutionTier(width, height) {
8481
9038
  function fail(error) {
8482
9039
  return { ok: false, error };
8483
9040
  }
8484
- function planVideoTool(row, req) {
8485
- const tool = videoToolConstraints(row);
8486
- if (!tool) return fail(`${row.id} is not a video tool`);
9041
+ function planVideoTool(row2, req) {
9042
+ const tool = videoToolConstraints(row2);
9043
+ if (!tool) return fail(`${row2.id} is not a video tool`);
8487
9044
  const { width, height, durationSeconds, fps } = req.source;
8488
9045
  if (!(width > 0 && height > 0 && durationSeconds > 0)) {
8489
9046
  return fail("The source video's width, height and duration are required");
8490
9047
  }
8491
- const maxSeconds = row.constraints.sourceVideoSeconds?.max;
9048
+ const maxSeconds = row2.constraints.sourceVideoSeconds?.max;
8492
9049
  if (maxSeconds !== void 0 && overMax(durationSeconds, maxSeconds)) {
8493
- return fail(`${row.label} takes source videos up to ${maxSeconds} seconds.`);
9050
+ return fail(`${row2.label} takes source videos up to ${maxSeconds} seconds.`);
8494
9051
  }
8495
9052
  const base = {
8496
9053
  durationSeconds,
@@ -8501,7 +9058,7 @@ function planVideoTool(row, req) {
8501
9058
  if (factor === void 0) return fail("An upscale factor is required");
8502
9059
  const range2 = tool.upscaleFactor;
8503
9060
  if (range2 && (factor < range2.min || factor > range2.max)) {
8504
- return fail(`${row.label} upscales by ${range2.min}x to ${range2.max}x.`);
9061
+ return fail(`${row2.label} upscales by ${range2.min}x to ${range2.max}x.`);
8505
9062
  }
8506
9063
  const outWidth = Math.round(width * factor);
8507
9064
  const outHeight = Math.round(height * factor);
@@ -8529,7 +9086,7 @@ function planVideoTool(row, req) {
8529
9086
  }
8530
9087
  const range2 = tool.fps;
8531
9088
  if (range2 && (target < range2.min || target > range2.max)) {
8532
- return fail(`${row.label} outputs ${range2.min} to ${range2.max} fps.`);
9089
+ return fail(`${row2.label} outputs ${range2.min} to ${range2.max} fps.`);
8533
9090
  }
8534
9091
  return {
8535
9092
  ok: true,
@@ -8558,7 +9115,7 @@ function planVideoTool(row, req) {
8558
9115
  if (tool.kind === "subtitles") {
8559
9116
  const resolution = resolutionTier(width, height);
8560
9117
  const problem = subtitleProblem(
8561
- row.label,
9118
+ row2.label,
8562
9119
  tool,
8563
9120
  req.subtitles,
8564
9121
  resolution,
@@ -8570,9 +9127,9 @@ function planVideoTool(row, req) {
8570
9127
  const formats = tool.outputFormats ?? ["h265"];
8571
9128
  const format = req.outputFormat ?? formats[0] ?? "h265";
8572
9129
  if (!formats.includes(format)) {
8573
- return fail(`${row.label} writes ${formats.join(" or ")}.`);
9130
+ return fail(`${row2.label} writes ${formats.join(" or ")}.`);
8574
9131
  }
8575
- const timing = renderedTiming(row, tool, durationSeconds, fps);
9132
+ const timing = renderedTiming(row2, tool, durationSeconds, fps);
8576
9133
  if (!timing.ok) return fail(timing.error);
8577
9134
  const out = shrinkToShortEdge(width, height, tool.maxOutputShortEdge);
8578
9135
  return {
@@ -8588,7 +9145,7 @@ function planVideoTool(row, req) {
8588
9145
  };
8589
9146
  }
8590
9147
  var DEFAULT_FPS = 24;
8591
- function renderedTiming(row, tool, durationSeconds, fps) {
9148
+ function renderedTiming(row2, tool, durationSeconds, fps) {
8592
9149
  const { maxOutputFps, minOutputFrames, maxOutputFrames } = tool;
8593
9150
  if (maxOutputFps === void 0 && minOutputFrames === void 0 && maxOutputFrames === void 0) {
8594
9151
  return fps !== void 0 ? { ok: true, fps } : { ok: true };
@@ -8597,7 +9154,7 @@ function renderedTiming(row, tool, durationSeconds, fps) {
8597
9154
  const frames = Math.max(minOutputFrames ?? 1, Math.round(durationSeconds * rate));
8598
9155
  if (maxOutputFrames !== void 0 && frames > maxOutputFrames) {
8599
9156
  const limit = `${maxOutputFrames} frames (${seconds(maxOutputFrames, rate)})`;
8600
- return { ok: false, error: `${row.label} renders up to ${limit}.` };
9157
+ return { ok: false, error: `${row2.label} renders up to ${limit}.` };
8601
9158
  }
8602
9159
  return { ok: true, fps: rate, frames, durationSeconds: frames / rate };
8603
9160
  }
@@ -8612,76 +9169,20 @@ function shrinkToShortEdge(width, height, limit) {
8612
9169
  }
8613
9170
 
8614
9171
  // src/adapters/fal-video-tools.ts
8615
- var FAL_QUEUE_ORIGIN = "https://queue.fal.run";
8616
- var queueUrlSchema = import_zod12.z.url().refine((value) => new URL(value).origin === FAL_QUEUE_ORIGIN, {
8617
- message: "not a fal queue URL"
8618
- });
8619
- var submitResponseSchema = import_zod12.z.object({
8620
- request_id: import_zod12.z.string().min(1),
8621
- status_url: queueUrlSchema,
8622
- response_url: queueUrlSchema,
8623
- cancel_url: queueUrlSchema
9172
+ var videoFileSchema = import_zod13.z.object({
9173
+ url: import_zod13.z.url(),
9174
+ content_type: import_zod13.z.string().nullish(),
9175
+ file_size: import_zod13.z.number().nullish()
8624
9176
  });
8625
- var statusResponseSchema = import_zod12.z.object({ status: import_zod12.z.string() });
8626
- var videoFileSchema = import_zod12.z.object({
8627
- url: import_zod12.z.url(),
8628
- content_type: import_zod12.z.string().nullish(),
8629
- file_size: import_zod12.z.number().nullish()
9177
+ var toolOutputSchema = import_zod13.z.object({
9178
+ video: import_zod13.z.union([videoFileSchema, import_zod13.z.array(videoFileSchema).min(1)])
8630
9179
  });
8631
- var toolOutputSchema = import_zod12.z.object({
8632
- video: import_zod12.z.union([videoFileSchema, import_zod12.z.array(videoFileSchema).min(1)])
8633
- });
8634
- var exrOutputSchema = import_zod12.z.object({
9180
+ var exrOutputSchema = import_zod13.z.object({
8635
9181
  preview_video: videoFileSchema,
8636
9182
  exr_frames_url: videoFileSchema
8637
9183
  });
8638
- var falWebhookBodySchema = import_zod12.z.object({
8639
- request_id: import_zod12.z.string().min(1),
8640
- gateway_request_id: import_zod12.z.string().nullish(),
8641
- status: import_zod12.z.enum(["OK", "ERROR"]),
8642
- payload: JsonValueSchema.nullish(),
8643
- error: import_zod12.z.string().nullish(),
8644
- payload_error: JsonValueSchema.nullish()
8645
- });
8646
- async function queueFetch(ctx, url, method, body) {
8647
- const payload = body === void 0 ? void 0 : JSON.stringify(body);
8648
- try {
8649
- if (ctx.routing.fal === "cloudflare-passthrough") {
8650
- return await gatewayFetch(gatewayConfig(ctx), ctx.fetch, url, {
8651
- method,
8652
- ...payload !== void 0 && { body: payload }
8653
- });
8654
- }
8655
- const falKey = ctx.keys.fal;
8656
- if (!falKey) {
8657
- throw new ModelKitError({
8658
- code: "auth",
8659
- message: "Missing API key for fal",
8660
- provider: "fal",
8661
- model: ctx.model.id,
8662
- retryable: false
8663
- });
8664
- }
8665
- return await ctx.fetch(url, {
8666
- method,
8667
- headers: {
8668
- Authorization: `Key ${falKey}`,
8669
- ...payload !== void 0 && { "Content-Type": "application/json" }
8670
- },
8671
- ...payload !== void 0 && { body: payload },
8672
- ...ctx.signal !== void 0 && { signal: ctx.signal }
8673
- });
8674
- } catch (cause) {
8675
- if (cause instanceof ModelKitError) throw cause;
8676
- throw classifyThrown("fal", cause, ctx.model.id);
8677
- }
8678
- }
8679
- async function readJson(ctx, res) {
8680
- if (!res.ok) throw falError(res.status, await readBody(res), ctx.model.id);
8681
- return JsonValueSchema.parse(await res.json());
8682
- }
8683
9184
  function providerModelName(ctx) {
8684
- return import_zod12.z.string().safeParse(ctx.model.providerOptions?.["fal"]?.["model"]).data;
9185
+ return import_zod13.z.string().safeParse(ctx.model.providerOptions?.["fal"]?.["model"]).data;
8685
9186
  }
8686
9187
  function staticInput(ctx) {
8687
9188
  return JsonObjectSchema.safeParse(ctx.model.providerOptions?.["fal"]?.["input"]).data ?? {};
@@ -8752,20 +9253,8 @@ async function submitFalVideoTool(req, ctx, opts) {
8752
9253
  output: plan3.output
8753
9254
  };
8754
9255
  }
8755
- function checkedQueueUrl(ctx, url) {
8756
- if (!queueUrlSchema.safeParse(url).success) {
8757
- throw new ModelKitError({
8758
- code: "provider_rejected",
8759
- message: "Video-tool submission carries a URL outside fal's queue",
8760
- provider: "fal",
8761
- model: ctx.model.id,
8762
- retryable: false
8763
- });
8764
- }
8765
- return url;
8766
- }
8767
9256
  async function falVideoToolStatus(sub, ctx) {
8768
- const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.statusUrl), "GET");
9257
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.statusUrl, "Video-tool"), "GET");
8769
9258
  const { status } = statusResponseSchema.parse(await readJson(ctx, res));
8770
9259
  if (status === "IN_QUEUE") return "queued";
8771
9260
  if (status === "COMPLETED") return "completed";
@@ -8862,18 +9351,18 @@ async function falVideoToolResult(sub, ctx, webhook) {
8862
9351
  }
8863
9352
  return resultOf(ctx, sub, webhook.payload);
8864
9353
  }
8865
- const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.responseUrl), "GET");
9354
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.responseUrl, "Video-tool"), "GET");
8866
9355
  return resultOf(ctx, sub, await readJson(ctx, res));
8867
9356
  }
8868
9357
  async function cancelFalVideoTool(sub, ctx) {
8869
- const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.cancelUrl), "PUT");
9358
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.cancelUrl, "Video-tool"), "PUT");
8870
9359
  if (res.ok) return true;
8871
9360
  if (res.status === 400) return false;
8872
9361
  throw falError(res.status, await readBody(res), ctx.model.id);
8873
9362
  }
8874
9363
 
8875
9364
  // src/adapters/fal-image.ts
8876
- var import_zod13 = require("zod");
9365
+ var import_zod14 = require("zod");
8877
9366
 
8878
9367
  // src/resolve-image-rules.ts
8879
9368
  var WIDE_RATIOS = [
@@ -9459,9 +9948,9 @@ function planFalImage(req, providerModelId, model) {
9459
9948
  if (built.imageSize !== void 0) plan3.imageSize = built.imageSize;
9460
9949
  return plan3;
9461
9950
  }
9462
- var FalFileSchema = import_zod13.z.object({ url: import_zod13.z.string(), content_type: import_zod13.z.string().nullish() });
9463
- var ImagesPayloadSchema = import_zod13.z.object({ images: import_zod13.z.array(FalFileSchema) });
9464
- var ImagePayloadSchema = import_zod13.z.object({ image: FalFileSchema });
9951
+ var FalFileSchema = import_zod14.z.object({ url: import_zod14.z.string(), content_type: import_zod14.z.string().nullish() });
9952
+ var ImagesPayloadSchema = import_zod14.z.object({ images: import_zod14.z.array(FalFileSchema) });
9953
+ var ImagePayloadSchema = import_zod14.z.object({ image: FalFileSchema });
9465
9954
  function decodeDataUri(url) {
9466
9955
  const comma = url.indexOf(",");
9467
9956
  const meta = url.slice(5, comma);
@@ -9520,15 +10009,15 @@ async function generateFalFamilyImage(req, ctx, run) {
9520
10009
  }
9521
10010
 
9522
10011
  // src/adapters/fal-mask.ts
9523
- var import_zod14 = require("zod");
10012
+ var import_zod15 = require("zod");
9524
10013
  var SAM3_IMAGE = "fal-ai/sam-3/image";
9525
10014
  var MAX_MASKS = 32;
9526
- function fail3(row, message, code) {
10015
+ function fail3(row2, message, code) {
9527
10016
  return new ModelKitError({
9528
10017
  code,
9529
- message: `${row.label}: ${message}`,
10018
+ message: `${row2.label}: ${message}`,
9530
10019
  provider: "fal",
9531
- model: row.id,
10020
+ model: row2.id,
9532
10021
  retryable: false
9533
10022
  });
9534
10023
  }
@@ -9538,22 +10027,22 @@ function pointPrompts(points) {
9538
10027
  function boxPrompts(boxes) {
9539
10028
  return boxes.map((b) => ({ x_min: b.xMin, y_min: b.yMin, x_max: b.xMax, y_max: b.yMax }));
9540
10029
  }
9541
- function planFalMask(row, req) {
9542
- if (row.providerModelId !== SAM3_IMAGE) {
10030
+ function planFalMask(row2, req) {
10031
+ if (row2.providerModelId !== SAM3_IMAGE) {
9543
10032
  throw fail3(
9544
- row,
9545
- `fal has no mask mapper for "${row.providerModelId}"`,
10033
+ row2,
10034
+ `fal has no mask mapper for "${row2.providerModelId}"`,
9546
10035
  "unsupported_option"
9547
10036
  );
9548
10037
  }
9549
10038
  const refs = req.references ?? [];
9550
10039
  const [image] = refs;
9551
- if (image === void 0) throw fail3(row, "needs one source image", "missing_input");
10040
+ if (image === void 0) throw fail3(row2, "needs one source image", "missing_input");
9552
10041
  if (refs.length > 1) {
9553
- throw fail3(row, `takes one source image; got ${refs.length}`, "unsupported_option");
10042
+ throw fail3(row2, `takes one source image; got ${refs.length}`, "unsupported_option");
9554
10043
  }
9555
10044
  const problem = maskProblem(req);
9556
- if (problem !== void 0) throw fail3(row, problem.message, problem.code);
10045
+ if (problem !== void 0) throw fail3(row2, problem.message, problem.code);
9557
10046
  const input = {
9558
10047
  image_url: refToUrl(image),
9559
10048
  prompt: req.prompt.trim(),
@@ -9570,17 +10059,17 @@ function planFalMask(row, req) {
9570
10059
  }
9571
10060
  return { endpoint: SAM3_IMAGE, input };
9572
10061
  }
9573
- var masksSchema = import_zod14.z.object({
9574
- masks: import_zod14.z.array(import_zod14.z.object({ url: import_zod14.z.string().min(1), content_type: import_zod14.z.string().nullish() }))
10062
+ var masksSchema = import_zod15.z.object({
10063
+ masks: import_zod15.z.array(import_zod15.z.object({ url: import_zod15.z.string().min(1), content_type: import_zod15.z.string().nullish() }))
9575
10064
  });
9576
- function parseFalMasks(row, payload) {
10065
+ function parseFalMasks(row2, payload) {
9577
10066
  const parsed = masksSchema.safeParse(payload);
9578
10067
  if (!parsed.success) {
9579
10068
  throw new ModelKitError({
9580
10069
  code: "provider_rejected",
9581
10070
  message: `fal ${SAM3_IMAGE} returned no mask list`,
9582
10071
  provider: "fal",
9583
- model: row.id,
10072
+ model: row2.id,
9584
10073
  retryable: false
9585
10074
  });
9586
10075
  }
@@ -9613,7 +10102,7 @@ async function generateFalMask(req, ctx, run) {
9613
10102
  }
9614
10103
 
9615
10104
  // src/adapters/fal-audio-plan.ts
9616
- var import_zod15 = require("zod");
10105
+ var import_zod16 = require("zod");
9617
10106
  var ELEVENLABS_MUSIC = FAL_AUDIO.elevenLabsMusic;
9618
10107
  var MINIMAX_MUSIC_32 = FAL_AUDIO.minimaxMusic;
9619
10108
  var ELEVENLABS_SFX = FAL_AUDIO.elevenLabsSfx;
@@ -9660,65 +10149,65 @@ var FAL_MEDIA_TYPES = /* @__PURE__ */ new Set([
9660
10149
  function isFalMediaKnown(type, providerModelId) {
9661
10150
  return KNOWN[type]?.has(providerModelId) ?? false;
9662
10151
  }
9663
- function falMediaError(row, message, code) {
10152
+ function falMediaError(row2, message, code) {
9664
10153
  return new ModelKitError({
9665
10154
  code,
9666
- message: `${row.label}: ${message}`,
10155
+ message: `${row2.label}: ${message}`,
9667
10156
  provider: "fal",
9668
- model: row.id,
10157
+ model: row2.id,
9669
10158
  retryable: false
9670
10159
  });
9671
10160
  }
9672
- function refuseMedia(row, present) {
9673
- const extra = Object.entries(present).find(([, set]) => set);
9674
- if (extra) throw falMediaError(row, `does not take ${extra[0]}`, "unsupported_option");
10161
+ function refuseMedia(row2, present2) {
10162
+ const extra = Object.entries(present2).find(([, set]) => set);
10163
+ if (extra) throw falMediaError(row2, `does not take ${extra[0]}`, "unsupported_option");
9675
10164
  }
9676
10165
  function setIf(input, key, value) {
9677
10166
  if (value !== void 0) input[key] = value;
9678
10167
  }
9679
- function unmapped(row) {
10168
+ function unmapped(row2) {
9680
10169
  return falMediaError(
9681
- row,
9682
- `fal has no ${row.type} mapper for "${row.providerModelId}"`,
10170
+ row2,
10171
+ `fal has no ${row2.type} mapper for "${row2.providerModelId}"`,
9683
10172
  "unsupported_option"
9684
10173
  );
9685
10174
  }
9686
- function mediaUrl(row, field, ref) {
9687
- if (ref === void 0) throw falMediaError(row, `needs ${field}`, "missing_input");
10175
+ function mediaUrl(row2, field, ref) {
10176
+ if (ref === void 0) throw falMediaError(row2, `needs ${field}`, "missing_input");
9688
10177
  return refToUrl(ref);
9689
10178
  }
9690
10179
  function trimmed(text2) {
9691
10180
  const value = text2?.trim();
9692
10181
  return value ? value : void 0;
9693
10182
  }
9694
- function requireText(row, text2, what) {
10183
+ function requireText(row2, text2, what) {
9695
10184
  const value = trimmed(text2);
9696
- if (value === void 0) throw falMediaError(row, `needs ${what}`, "missing_input");
10185
+ if (value === void 0) throw falMediaError(row2, `needs ${what}`, "missing_input");
9697
10186
  return value;
9698
10187
  }
9699
- function planMirelo(row, req) {
9700
- const id = row.providerModelId;
10188
+ function planMirelo(row2, req) {
10189
+ const id = row2.providerModelId;
9701
10190
  const input = { num_samples: 1 };
9702
10191
  setIf(input, "duration", req.durationSeconds);
9703
10192
  setIf(input, "negative_prompt", req.negativePrompt);
9704
10193
  setIf(input, "seed", req.seed);
9705
10194
  setIf(input, "upload_audio_format", req.outputFormat);
9706
10195
  if (id === MIRELO_VIDEO) {
9707
- input["video_url"] = mediaUrl(row, "sourceVideo", req.sourceVideo);
10196
+ input["video_url"] = mediaUrl(row2, "sourceVideo", req.sourceVideo);
9708
10197
  setIf(input, "text_prompt", trimmed(req.prompt));
9709
10198
  return { endpoint: id, input };
9710
10199
  }
9711
10200
  input["prompt"] = req.prompt.trim();
9712
10201
  return { endpoint: id, input };
9713
10202
  }
9714
- function planFalAudio(row, req) {
9715
- if (row.type !== "audio" && row.type !== "sound-effect") {
9716
- throw falMediaError(row, `${row.type} rows do not generate audio`, "unsupported_option");
10203
+ function planFalAudio(row2, req) {
10204
+ if (row2.type !== "audio" && row2.type !== "sound-effect") {
10205
+ throw falMediaError(row2, `${row2.type} rows do not generate audio`, "unsupported_option");
9717
10206
  }
9718
- const id = row.providerModelId;
10207
+ const id = row2.providerModelId;
9719
10208
  const problem = falAudioProblem(id, req);
9720
- if (problem !== void 0) throw falMediaError(row, problem.message, problem.code);
9721
- if (id === MIRELO_TEXT || id === MIRELO_VIDEO) return planMirelo(row, req);
10209
+ if (problem !== void 0) throw falMediaError(row2, problem.message, problem.code);
10210
+ if (id === MIRELO_TEXT || id === MIRELO_VIDEO) return planMirelo(row2, req);
9722
10211
  const prompt = req.prompt.trim();
9723
10212
  if (id === ELEVENLABS_MUSIC) {
9724
10213
  const input = { prompt };
@@ -9743,12 +10232,12 @@ function planFalAudio(row, req) {
9743
10232
  setIf(input, "output_format", req.outputFormat);
9744
10233
  return { endpoint: id, input };
9745
10234
  }
9746
- throw unmapped(row);
10235
+ throw unmapped(row2);
9747
10236
  }
9748
- function planFalSpeech(row, req) {
9749
- const id = row.providerModelId;
9750
- if (row.type !== "speech") throw unmapped(row);
9751
- const script = requireText(row, req.text, "text");
10237
+ function planFalSpeech(row2, req) {
10238
+ const id = row2.providerModelId;
10239
+ if (row2.type !== "speech") throw unmapped(row2);
10240
+ const script = requireText(row2, req.text, "text");
9752
10241
  if (ELEVENLABS_TTS.has(id)) {
9753
10242
  const input = { text: script };
9754
10243
  setIf(input, "voice", req.voice);
@@ -9768,31 +10257,31 @@ function planFalSpeech(row, req) {
9768
10257
  setIf(input, "language_boost", req.language);
9769
10258
  return { endpoint: id, input };
9770
10259
  }
9771
- throw unmapped(row);
10260
+ throw unmapped(row2);
9772
10261
  }
9773
- function planFalVoiceChange(row, req) {
9774
- if (row.type !== "voice-change" || row.providerModelId !== VOICE_CHANGER) throw unmapped(row);
9775
- const input = { audio_url: mediaUrl(row, "sourceAudio", req.sourceAudio) };
10262
+ function planFalVoiceChange(row2, req) {
10263
+ if (row2.type !== "voice-change" || row2.providerModelId !== VOICE_CHANGER) throw unmapped(row2);
10264
+ const input = { audio_url: mediaUrl(row2, "sourceAudio", req.sourceAudio) };
9776
10265
  setIf(input, "voice", req.voice);
9777
10266
  setIf(input, "output_format", req.outputFormat);
9778
10267
  return { endpoint: VOICE_CHANGER, input };
9779
10268
  }
9780
- var fileSchema = import_zod15.z.object({
9781
- url: import_zod15.z.string().min(1),
9782
- content_type: import_zod15.z.string().nullish()
10269
+ var fileSchema = import_zod16.z.object({
10270
+ url: import_zod16.z.string().min(1),
10271
+ content_type: import_zod16.z.string().nullish()
9783
10272
  });
9784
- var audioOutputSchema = import_zod15.z.object({
9785
- audio: import_zod15.z.union([fileSchema, import_zod15.z.array(fileSchema).min(1)]),
9786
- duration: import_zod15.z.number().nullish(),
9787
- duration_ms: import_zod15.z.number().nullish(),
9788
- lyrics: import_zod15.z.string().nullish()
10273
+ var audioOutputSchema = import_zod16.z.object({
10274
+ audio: import_zod16.z.union([fileSchema, import_zod16.z.array(fileSchema).min(1)]),
10275
+ duration: import_zod16.z.number().nullish(),
10276
+ duration_ms: import_zod16.z.number().nullish(),
10277
+ lyrics: import_zod16.z.string().nullish()
9789
10278
  });
9790
- function noFalOutput(row, what, endpoint) {
10279
+ function noFalOutput(row2, what, endpoint) {
9791
10280
  return new ModelKitError({
9792
10281
  code: "provider_rejected",
9793
10282
  message: `fal ${endpoint} returned no ${what}`,
9794
10283
  provider: "fal",
9795
- model: row.id,
10284
+ model: row2.id,
9796
10285
  retryable: false
9797
10286
  });
9798
10287
  }
@@ -9800,12 +10289,12 @@ function reportedSeconds(seconds3, ms) {
9800
10289
  if (seconds3 != null) return seconds3;
9801
10290
  return ms != null ? ms / 1e3 : void 0;
9802
10291
  }
9803
- function parseFalAudio(row, endpoint, payload) {
10292
+ function parseFalAudio(row2, endpoint, payload) {
9804
10293
  const parsed = audioOutputSchema.safeParse(payload);
9805
- if (!parsed.success) throw noFalOutput(row, "audio", endpoint);
10294
+ if (!parsed.success) throw noFalOutput(row2, "audio", endpoint);
9806
10295
  const { audio, duration, duration_ms: durationMs, lyrics } = parsed.data;
9807
10296
  const file = Array.isArray(audio) ? audio[0] : audio;
9808
- if (file === void 0) throw noFalOutput(row, "audio", endpoint);
10297
+ if (file === void 0) throw noFalOutput(row2, "audio", endpoint);
9809
10298
  const seconds3 = reportedSeconds(duration, durationMs);
9810
10299
  return {
9811
10300
  url: file.url,
@@ -9816,114 +10305,114 @@ function parseFalAudio(row, endpoint, payload) {
9816
10305
  }
9817
10306
 
9818
10307
  // src/adapters/fal-media-plan.ts
9819
- var import_zod16 = require("zod");
10308
+ var import_zod17 = require("zod");
9820
10309
  var MINIMAX_LIPSYNC_RESOLUTIONS = {
9821
10310
  "480p": "480P",
9822
10311
  "768p": "768P",
9823
10312
  "1080p": "1080P",
9824
10313
  "2k": "2K"
9825
10314
  };
9826
- function syncModelName(row) {
9827
- return import_zod16.z.string().safeParse(row.providerOptions?.["fal"]?.["model"]).data;
10315
+ function syncModelName(row2) {
10316
+ return import_zod17.z.string().safeParse(row2.providerOptions?.["fal"]?.["model"]).data;
9828
10317
  }
9829
- function planFalLipsync(row, req) {
9830
- const id = row.providerModelId;
9831
- if (row.type !== "lipsync") throw unmapped(row);
9832
- const audio = mediaUrl(row, "audio", req.audio);
10318
+ function planFalLipsync(row2, req) {
10319
+ const id = row2.providerModelId;
10320
+ if (row2.type !== "lipsync") throw unmapped(row2);
10321
+ const audio = mediaUrl(row2, "audio", req.audio);
9833
10322
  if (id === FAL_LIPSYNC.minimax) {
9834
- refuseMedia(row, { sourceVideo: req.sourceVideo !== void 0 });
10323
+ refuseMedia(row2, { sourceVideo: req.sourceVideo !== void 0 });
9835
10324
  const input = {
9836
- image_url: mediaUrl(row, "image", req.image),
10325
+ image_url: mediaUrl(row2, "image", req.image),
9837
10326
  audio_url: audio
9838
10327
  };
9839
10328
  if (req.resolution !== void 0) {
9840
10329
  const resolution = MINIMAX_LIPSYNC_RESOLUTIONS[req.resolution];
9841
10330
  if (resolution === void 0) {
9842
- throw falMediaError(row, `does not render ${req.resolution}`, "unsupported_option");
10331
+ throw falMediaError(row2, `does not render ${req.resolution}`, "unsupported_option");
9843
10332
  }
9844
10333
  input["resolution"] = resolution;
9845
10334
  }
9846
10335
  return { endpoint: id, input };
9847
10336
  }
9848
- refuseMedia(row, { image: req.image !== void 0 });
9849
- const video = mediaUrl(row, "sourceVideo", req.sourceVideo);
10337
+ refuseMedia(row2, { image: req.image !== void 0 });
10338
+ const video = mediaUrl(row2, "sourceVideo", req.sourceVideo);
9850
10339
  if (id === FAL_LIPSYNC.veed) {
9851
10340
  return { endpoint: id, input: { video_url: video, audio_url: audio } };
9852
10341
  }
9853
10342
  if (id === FAL_LIPSYNC.syncV2 || id === FAL_LIPSYNC.syncV3) {
9854
10343
  const input = { video_url: video, audio_url: audio, sync_mode: "cut_off" };
9855
- const model = syncModelName(row);
10344
+ const model = syncModelName(row2);
9856
10345
  if (id === FAL_LIPSYNC.syncV2 && model !== void 0) input["model"] = model;
9857
10346
  return { endpoint: id, input };
9858
10347
  }
9859
- throw unmapped(row);
10348
+ throw unmapped(row2);
9860
10349
  }
9861
- function planFalDubbing(row, req) {
9862
- if (row.type !== "dubbing" || row.providerModelId !== FAL_DUBBING) throw unmapped(row);
10350
+ function planFalDubbing(row2, req) {
10351
+ if (row2.type !== "dubbing" || row2.providerModelId !== FAL_DUBBING) throw unmapped(row2);
9863
10352
  if (req.sourceVideo !== void 0 && req.sourceAudio !== void 0) {
9864
10353
  throw falMediaError(
9865
- row,
10354
+ row2,
9866
10355
  "takes sourceVideo or sourceAudio, not both",
9867
10356
  "unsupported_option"
9868
10357
  );
9869
10358
  }
9870
10359
  const target = req.targetLanguage.trim();
9871
- if (!target) throw falMediaError(row, "needs targetLanguage", "missing_input");
10360
+ if (!target) throw falMediaError(row2, "needs targetLanguage", "missing_input");
9872
10361
  const input = { target_lang: target };
9873
10362
  if (req.sourceVideo !== void 0) input["video_url"] = refToUrl(req.sourceVideo);
9874
- else input["audio_url"] = mediaUrl(row, "sourceVideo or sourceAudio", req.sourceAudio);
10363
+ else input["audio_url"] = mediaUrl(row2, "sourceVideo or sourceAudio", req.sourceAudio);
9875
10364
  return { endpoint: FAL_DUBBING, input };
9876
10365
  }
9877
- function planFalTranscription(row, req) {
9878
- if (row.type !== "transcription" || row.providerModelId !== FAL_SCRIBE) throw unmapped(row);
9879
- const input = { audio_url: mediaUrl(row, "source", req.source) };
10366
+ function planFalTranscription(row2, req) {
10367
+ if (row2.type !== "transcription" || row2.providerModelId !== FAL_SCRIBE) throw unmapped(row2);
10368
+ const input = { audio_url: mediaUrl(row2, "source", req.source) };
9880
10369
  setIf(input, "language_code", req.language?.trim() || void 0);
9881
10370
  return { endpoint: FAL_SCRIBE, input };
9882
10371
  }
9883
- var fileSchema2 = import_zod16.z.object({
9884
- url: import_zod16.z.string().min(1),
9885
- content_type: import_zod16.z.string().nullish()
10372
+ var fileSchema2 = import_zod17.z.object({
10373
+ url: import_zod17.z.string().min(1),
10374
+ content_type: import_zod17.z.string().nullish()
9886
10375
  });
9887
- var videoOutputSchema = import_zod16.z.object({
10376
+ var videoOutputSchema = import_zod17.z.object({
9888
10377
  video: fileSchema2,
9889
- duration: import_zod16.z.number().nullish()
10378
+ duration: import_zod17.z.number().nullish()
9890
10379
  });
9891
- var dubbingOutputSchema = import_zod16.z.object({
10380
+ var dubbingOutputSchema = import_zod17.z.object({
9892
10381
  video: fileSchema2.nullish(),
9893
10382
  audio: fileSchema2.nullish()
9894
10383
  });
9895
- var transcriptSchema = import_zod16.z.object({
9896
- text: import_zod16.z.string(),
9897
- language_code: import_zod16.z.string().nullish(),
9898
- words: import_zod16.z.array(
9899
- import_zod16.z.object({
9900
- text: import_zod16.z.string(),
9901
- type: import_zod16.z.string(),
9902
- start: import_zod16.z.number().nullish(),
9903
- end: import_zod16.z.number().nullish(),
9904
- speaker_id: import_zod16.z.string().nullish()
10384
+ var transcriptSchema = import_zod17.z.object({
10385
+ text: import_zod17.z.string(),
10386
+ language_code: import_zod17.z.string().nullish(),
10387
+ words: import_zod17.z.array(
10388
+ import_zod17.z.object({
10389
+ text: import_zod17.z.string(),
10390
+ type: import_zod17.z.string(),
10391
+ start: import_zod17.z.number().nullish(),
10392
+ end: import_zod17.z.number().nullish(),
10393
+ speaker_id: import_zod17.z.string().nullish()
9905
10394
  })
9906
10395
  ).nullish()
9907
10396
  });
9908
- function parseFalVideo(row, endpoint, payload) {
10397
+ function parseFalVideo(row2, endpoint, payload) {
9909
10398
  const parsed = videoOutputSchema.safeParse(payload);
9910
- if (!parsed.success) throw noFalOutput(row, "video", endpoint);
10399
+ if (!parsed.success) throw noFalOutput(row2, "video", endpoint);
9911
10400
  const { video, duration } = parsed.data;
9912
10401
  return { url: video.url, ...duration != null && { durationSeconds: duration } };
9913
10402
  }
9914
- function parseFalDubbing(row, kind, payload) {
10403
+ function parseFalDubbing(row2, kind, payload) {
9915
10404
  const parsed = dubbingOutputSchema.safeParse(payload);
9916
10405
  const file = parsed.success ? parsed.data[kind] : void 0;
9917
- if (file == null) throw noFalOutput(row, kind, FAL_DUBBING);
10406
+ if (file == null) throw noFalOutput(row2, kind, FAL_DUBBING);
9918
10407
  return {
9919
10408
  kind,
9920
10409
  url: file.url,
9921
10410
  ...file.content_type != null && { mime: file.content_type }
9922
10411
  };
9923
10412
  }
9924
- function parseFalTranscript(row, endpoint, payload) {
10413
+ function parseFalTranscript(row2, endpoint, payload) {
9925
10414
  const parsed = transcriptSchema.safeParse(payload);
9926
- if (!parsed.success) throw noFalOutput(row, "transcript", endpoint);
10415
+ if (!parsed.success) throw noFalOutput(row2, "transcript", endpoint);
9927
10416
  const words = (parsed.data.words ?? []).map(
9928
10417
  (w) => ({
9929
10418
  text: w.text,
@@ -10086,8 +10575,313 @@ async function transcribeFal(req, ctx, run) {
10086
10575
  };
10087
10576
  }
10088
10577
 
10578
+ // src/adapters/fal-model3d.ts
10579
+ var import_zod18 = require("zod");
10580
+ var fileSchema3 = import_zod18.z.object({
10581
+ url: import_zod18.z.url(),
10582
+ content_type: import_zod18.z.string().nullish(),
10583
+ file_size: import_zod18.z.number().nullish()
10584
+ });
10585
+ var resultSchema = import_zod18.z.looseObject({
10586
+ model_glb: fileSchema3.nullish(),
10587
+ model_mesh: fileSchema3.nullish(),
10588
+ thumbnail: fileSchema3.nullish(),
10589
+ rendered_image: fileSchema3.nullish()
10590
+ });
10591
+ function rejected(ctx, message) {
10592
+ return new ModelKitError({
10593
+ code: "provider_rejected",
10594
+ message,
10595
+ provider: "fal",
10596
+ model: ctx.model.id,
10597
+ retryable: false
10598
+ });
10599
+ }
10600
+ function specOf(ctx) {
10601
+ const spec = model3dConstraints(ctx.model);
10602
+ if (spec === void 0) {
10603
+ throw new ModelKitError({
10604
+ code: "unsupported_option",
10605
+ message: `${ctx.model.id} is not a 3D model`,
10606
+ model: ctx.model.id
10607
+ });
10608
+ }
10609
+ return spec;
10610
+ }
10611
+ var present = (v) => v !== void 0 && v.length > 0;
10612
+ function model3dCall(row2, spec, req) {
10613
+ const prompt = req.prompt?.trim() || void 0;
10614
+ const texture = model3dTexture(spec, req.texture);
10615
+ const textured = spec.texture.length > 0 && texture !== "none";
10616
+ const pbr = spec.pbr && textured && req.pbr === true;
10617
+ const resolution = model3dResolution(spec, req.resolution);
10618
+ const views = spec.views === "none" ? {} : req.views ?? {};
10619
+ const seed = spec.seed && req.seed !== void 0 ? req.seed : void 0;
10620
+ const endpoint = (path) => {
10621
+ if (path === void 0) {
10622
+ throw new ModelKitError({
10623
+ code: "unsupported_option",
10624
+ message: `${row2.id} has no endpoint for this request`,
10625
+ provider: "fal",
10626
+ model: row2.id,
10627
+ retryable: false
10628
+ });
10629
+ }
10630
+ return path;
10631
+ };
10632
+ const slotted = (kind) => MODEL3D_IMAGE_SLOTS[kind].map((slot) => slot === "image" ? req.image : views[slot]).filter(present).slice(0, spec.maxImages);
10633
+ const images = slotted("unordered");
10634
+ switch (spec.family) {
10635
+ case "trellis":
10636
+ return {
10637
+ endpoint: endpoint(spec.endpoints.image),
10638
+ input: {
10639
+ image_url: req.image ?? "",
10640
+ resolution: Number(resolution),
10641
+ ...seed !== void 0 && { seed }
10642
+ }
10643
+ };
10644
+ case "sam":
10645
+ return {
10646
+ endpoint: endpoint(spec.endpoints.image),
10647
+ input: {
10648
+ image_url: req.image ?? "",
10649
+ ...prompt !== void 0 && { prompt },
10650
+ export_textured_glb: true,
10651
+ ...seed !== void 0 && { seed }
10652
+ }
10653
+ };
10654
+ case "hunyuan": {
10655
+ const opts = { generate_type: textured ? "Normal" : "Geometry", enable_pbr: pbr };
10656
+ if (!present(req.image)) {
10657
+ return {
10658
+ endpoint: endpoint(spec.endpoints.text),
10659
+ input: { prompt: prompt ?? "", ...opts }
10660
+ };
10661
+ }
10662
+ return {
10663
+ endpoint: endpoint(spec.endpoints.image),
10664
+ input: {
10665
+ input_image_url: req.image,
10666
+ ...present(views.back) && { back_image_url: views.back },
10667
+ ...present(views.left) && { left_image_url: views.left },
10668
+ ...present(views.right) && { right_image_url: views.right },
10669
+ ...opts
10670
+ }
10671
+ };
10672
+ }
10673
+ case "tripo": {
10674
+ const opts = {
10675
+ texture: textured,
10676
+ pbr,
10677
+ ...textured && {
10678
+ texture_quality: texture === "detailed" ? "detailed" : "standard"
10679
+ },
10680
+ ...seed !== void 0 && { model_seed: seed }
10681
+ };
10682
+ if (!present(req.image)) {
10683
+ return {
10684
+ endpoint: endpoint(spec.endpoints.text),
10685
+ input: { prompt: prompt ?? "", ...opts }
10686
+ };
10687
+ }
10688
+ const ordered = slotted("ordered");
10689
+ return ordered.length > 1 ? {
10690
+ endpoint: endpoint(spec.endpoints.multiImage),
10691
+ input: { image_urls: ordered, ...opts }
10692
+ } : {
10693
+ endpoint: endpoint(spec.endpoints.image),
10694
+ input: { image_url: req.image, ...opts }
10695
+ };
10696
+ }
10697
+ case "rodin": {
10698
+ const opts = {
10699
+ geometry_file_format: "glb",
10700
+ material: "PBR",
10701
+ ...seed !== void 0 && { seed }
10702
+ };
10703
+ if (images.length === 0) {
10704
+ return {
10705
+ endpoint: endpoint(spec.endpoints.text),
10706
+ input: { prompt: prompt ?? "", ...opts }
10707
+ };
10708
+ }
10709
+ return {
10710
+ endpoint: endpoint(spec.endpoints.image),
10711
+ input: { image_urls: images, ...prompt !== void 0 && { prompt }, ...opts }
10712
+ };
10713
+ }
10714
+ case "meshy": {
10715
+ const texturePrompt = req.texturePrompt?.trim() || void 0;
10716
+ const opts = {
10717
+ enable_pbr: pbr,
10718
+ ...spec.textureRef && texturePrompt !== void 0 && { texture_prompt: texturePrompt },
10719
+ ...spec.textureRef && present(req.textureImage) && { texture_image_url: req.textureImage }
10720
+ };
10721
+ if (images.length === 0) {
10722
+ return {
10723
+ endpoint: endpoint(spec.endpoints.text),
10724
+ input: {
10725
+ prompt: prompt ?? "",
10726
+ mode: textured ? "full" : "preview",
10727
+ ...opts,
10728
+ ...seed !== void 0 && { seed }
10729
+ }
10730
+ };
10731
+ }
10732
+ return images.length > 1 ? {
10733
+ endpoint: endpoint(spec.endpoints.multiImage),
10734
+ input: { image_urls: images, should_texture: textured, ...opts }
10735
+ } : {
10736
+ endpoint: endpoint(spec.endpoints.image),
10737
+ input: { image_url: req.image ?? "", should_texture: textured, ...opts }
10738
+ };
10739
+ }
10740
+ case "hi3d": {
10741
+ const opts = {
10742
+ resolution: resolution === "master" ? "2048master" : "2048quality",
10743
+ enable_texture: textured,
10744
+ enable_pbr: pbr,
10745
+ export_format: "glb"
10746
+ };
10747
+ const anyView = present(views.back) || present(views.left) || present(views.right);
10748
+ return anyView ? {
10749
+ endpoint: endpoint(spec.endpoints.multiImage),
10750
+ input: {
10751
+ front_image_url: req.image ?? "",
10752
+ ...present(views.back) && { back_image_url: views.back },
10753
+ ...present(views.left) && { left_image_url: views.left },
10754
+ ...present(views.right) && { right_image_url: views.right },
10755
+ ...opts
10756
+ }
10757
+ } : {
10758
+ endpoint: endpoint(spec.endpoints.image),
10759
+ input: { image_url: req.image ?? "", ...opts }
10760
+ };
10761
+ }
10762
+ }
10763
+ }
10764
+ async function submitFalModel3d(req, ctx, opts) {
10765
+ const spec = specOf(ctx);
10766
+ const views = req.views ?? {};
10767
+ const refusal2 = model3dInputRefusal(spec, {
10768
+ prompt: present(req.prompt?.trim()),
10769
+ image: present(req.image),
10770
+ back: present(views.back),
10771
+ left: present(views.left),
10772
+ right: present(views.right),
10773
+ top: present(views.top)
10774
+ });
10775
+ if (refusal2 !== null) {
10776
+ throw new ModelKitError({
10777
+ code: "unsupported_option",
10778
+ message: `${ctx.model.id}: ${refusal2}`,
10779
+ provider: "fal",
10780
+ model: ctx.model.id,
10781
+ retryable: false
10782
+ });
10783
+ }
10784
+ if (spec.seed && req.seed !== void 0 && !model3dSeedFits(spec, req.seed)) {
10785
+ throw new ModelKitError({
10786
+ code: "unsupported_option",
10787
+ message: `${ctx.model.id} takes a seed from 0 to ${spec.seedMax ?? Number.MAX_SAFE_INTEGER}`,
10788
+ provider: "fal",
10789
+ model: ctx.model.id,
10790
+ retryable: false
10791
+ });
10792
+ }
10793
+ const call = model3dCall(ctx.model, spec, req);
10794
+ const sku = model3dPricingSku(
10795
+ ctx.model,
10796
+ {
10797
+ ...req.texture !== void 0 && { texture: req.texture },
10798
+ ...req.pbr !== void 0 && { pbr: req.pbr },
10799
+ ...req.resolution !== void 0 && { resolution: req.resolution }
10800
+ },
10801
+ {
10802
+ image: present(req.image),
10803
+ views: spec.views !== "none" && (present(views.back) || present(views.left) || present(views.right) || spec.views === "unordered" && present(views.top))
10804
+ }
10805
+ );
10806
+ const target = new URL(`${FAL_QUEUE_ORIGIN}/${call.endpoint}`);
10807
+ if (opts.webhookUrl !== void 0) target.searchParams.set("fal_webhook", opts.webhookUrl);
10808
+ const res = await queueFetch(ctx, target.toString(), "POST", call.input);
10809
+ const parsed = submitResponseSchema.safeParse(await readJson(ctx, res));
10810
+ if (!parsed.success) throw rejected(ctx, `fal ${call.endpoint} submit returned no queue URLs`);
10811
+ return {
10812
+ model: ctx.model.id,
10813
+ provider: "fal",
10814
+ endpoint: call.endpoint,
10815
+ sku,
10816
+ requestId: parsed.data.request_id,
10817
+ statusUrl: parsed.data.status_url,
10818
+ responseUrl: parsed.data.response_url,
10819
+ cancelUrl: parsed.data.cancel_url
10820
+ };
10821
+ }
10822
+ async function falModel3dStatus(sub, ctx) {
10823
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.statusUrl, "3D"), "GET");
10824
+ const { status } = statusResponseSchema.parse(await readJson(ctx, res));
10825
+ if (status === "IN_QUEUE") return "queued";
10826
+ if (status === "COMPLETED") return "completed";
10827
+ return "running";
10828
+ }
10829
+ function httpsUrl(ctx, sub, url, what) {
10830
+ if (new URL(url).protocol === "https:") return url;
10831
+ throw rejected(ctx, `fal ${sub.endpoint} returned a ${what} URL that is not https`);
10832
+ }
10833
+ function resultOf2(ctx, sub, payload) {
10834
+ const parsed = resultSchema.safeParse(payload);
10835
+ const glb = parsed.success ? parsed.data.model_glb ?? parsed.data.model_mesh : void 0;
10836
+ if (!glb) throw rejected(ctx, `fal ${sub.endpoint} returned no GLB`);
10837
+ const still = parsed.success ? parsed.data.thumbnail ?? parsed.data.rendered_image : void 0;
10838
+ const glbUrl = httpsUrl(ctx, sub, glb.url, "GLB");
10839
+ const stillUrl = still ? httpsUrl(ctx, sub, still.url, "thumbnail") : void 0;
10840
+ return {
10841
+ glb: {
10842
+ url: glbUrl,
10843
+ ...glb.content_type != null && { mime: glb.content_type },
10844
+ ...glb.file_size != null && { bytes: glb.file_size }
10845
+ },
10846
+ ...stillUrl !== void 0 && { thumbnail: { url: stillUrl } },
10847
+ sku: sub.sku,
10848
+ usage: {
10849
+ model: ctx.model.id,
10850
+ provider: "fal",
10851
+ // The sink has no 3D modality; IMAGE is the nearest. The unit is what bills it.
10852
+ modality: "IMAGE",
10853
+ unit: "requests",
10854
+ quantity: 1
10855
+ },
10856
+ raw: payload
10857
+ };
10858
+ }
10859
+ async function falModel3dResult(sub, ctx, webhook) {
10860
+ if (webhook !== void 0) {
10861
+ if (webhook.request_id !== sub.requestId) {
10862
+ throw rejected(ctx, "fal webhook is for a different request");
10863
+ }
10864
+ if (webhook.status === "ERROR") {
10865
+ throw falError(
10866
+ void 0,
10867
+ webhook.payload ?? webhook.error ?? "fal job failed",
10868
+ ctx.model.id
10869
+ );
10870
+ }
10871
+ return resultOf2(ctx, sub, webhook.payload);
10872
+ }
10873
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.responseUrl, "3D"), "GET");
10874
+ return resultOf2(ctx, sub, await readJson(ctx, res));
10875
+ }
10876
+ async function cancelFalModel3d(sub, ctx) {
10877
+ const res = await queueFetch(ctx, checkedQueueUrl(ctx, sub.cancelUrl, "3D"), "PUT");
10878
+ if (res.ok) return true;
10879
+ if (res.status === 400) return false;
10880
+ throw falError(res.status, await readBody(res), ctx.model.id);
10881
+ }
10882
+
10089
10883
  // src/adapters/fal-video-plan.ts
10090
- var import_zod17 = require("zod");
10884
+ var import_zod19 = require("zod");
10091
10885
  function refusal(ctx, message, code = "unsupported_option") {
10092
10886
  return new ModelKitError({
10093
10887
  code,
@@ -10124,9 +10918,9 @@ function wholeSeconds(req, ctx) {
10124
10918
  if (!Number.isInteger(duration)) throw refusal(ctx, "takes whole-second durations");
10125
10919
  return duration;
10126
10920
  }
10127
- var lengthSchema = import_zod17.z.object({
10128
- duration: import_zod17.z.number().positive().optional(),
10129
- video: import_zod17.z.object({ duration: import_zod17.z.number().positive().nullish() }).optional()
10921
+ var lengthSchema = import_zod19.z.object({
10922
+ duration: import_zod19.z.number().positive().optional(),
10923
+ video: import_zod19.z.object({ duration: import_zod19.z.number().positive().nullish() }).optional()
10130
10924
  });
10131
10925
  function reportedSeconds2(payload) {
10132
10926
  const parsed = lengthSchema.safeParse(payload);
@@ -10258,6 +11052,30 @@ var klingV3Family = {
10258
11052
  }
10259
11053
  };
10260
11054
 
11055
+ // src/replicate-video-kinds.ts
11056
+ function replicateBaseModelId(providerModelId) {
11057
+ const colon = providerModelId.indexOf(":");
11058
+ return colon === -1 ? providerModelId : providerModelId.slice(0, colon);
11059
+ }
11060
+ var REPLICATE_VIDEO_KINDS = /* @__PURE__ */ new Map([
11061
+ ["kling-video/v2.5-turbo/pro/image-to-video", "kling"],
11062
+ ["kling-video/v3.0/pro/image-to-video", "kling"],
11063
+ ["kwaivgi/kling-v3-video", "kling"],
11064
+ ["kwaivgi/kling-v3-omni-video", "kling-omni"],
11065
+ ["minimax/hailuo-02", "hailuo"]
11066
+ ]);
11067
+ function videoKind(providerModelId) {
11068
+ return REPLICATE_VIDEO_KINDS.get(replicateBaseModelId(providerModelId));
11069
+ }
11070
+ var KLING_TIERS = [
11071
+ { mode: "standard", resolution: "720p" },
11072
+ { mode: "pro", resolution: "1080p" },
11073
+ { mode: "4k", resolution: "4k" }
11074
+ ];
11075
+ function klingTier(req) {
11076
+ return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
11077
+ }
11078
+
10261
11079
  // src/resolve-video-rules.ts
10262
11080
  var MOTION_PRO2 = "fal-ai/kling-video/v3/pro/motion-control";
10263
11081
  var MOTION_STANDARD2 = "fal-ai/kling-video/v3/standard/motion-control";
@@ -10431,6 +11249,16 @@ function h3EndFrameRatioWarning(model, ratio) {
10431
11249
  message: `${model.id} follows the end frame's aspect ratio`
10432
11250
  };
10433
11251
  }
11252
+ function isReplicateKling(model) {
11253
+ if (model.adapter !== "replicate") return false;
11254
+ const kind = videoKind(model.providerModelId);
11255
+ return kind === "kling" || kind === "kling-omni";
11256
+ }
11257
+ function fillReplicateKlingResolution(model, req) {
11258
+ if (isReplicateKling(model) && req.resolution === void 0) {
11259
+ req.resolution = klingTier(req).resolution;
11260
+ }
11261
+ }
10434
11262
  function applyFalVideoRules(model, req, callerRatio, warnings) {
10435
11263
  if (model.adapter !== "fal") return;
10436
11264
  const problem = falVideoProblem(model.providerModelId, withPromptForResolve(req));
@@ -10639,7 +11467,7 @@ var MUSE_T2I_ENDPOINT = "meta/muse-image/text-to-image";
10639
11467
  var MUSE_EDIT_ENDPOINT = "meta/muse-image/edit";
10640
11468
  var KLING_O1_ENDPOINT = "fal-ai/kling-video/o1/video-to-video/reference";
10641
11469
  var PASSTHROUGH_MAX_WAIT_MS = 18e4;
10642
- var falSubscribePayloadSchema = import_zod18.z.object({ data: JsonValueSchema });
11470
+ var falSubscribePayloadSchema = import_zod20.z.object({ data: JsonValueSchema });
10643
11471
  function defaultCreateFalClient(opts) {
10644
11472
  if (opts.maxRetries !== void 0)
10645
11473
  return createFalHttpClient({
@@ -10717,7 +11545,11 @@ function createFalAdapter(deps = defaultDeps) {
10717
11545
  submitVideoTool: submitFalVideoTool,
10718
11546
  videoToolStatus: falVideoToolStatus,
10719
11547
  videoToolResult: falVideoToolResult,
10720
- cancelVideoTool: cancelFalVideoTool
11548
+ cancelVideoTool: cancelFalVideoTool,
11549
+ submitModel3d: submitFalModel3d,
11550
+ model3dStatus: falModel3dStatus,
11551
+ model3dResult: falModel3dResult,
11552
+ cancelModel3d: cancelFalModel3d
10721
11553
  };
10722
11554
  }
10723
11555
  function falRun(ctx, deps) {
@@ -10865,11 +11697,11 @@ async function decodeImage(ctx, url, contentType) {
10865
11697
  const mime = res.headers.get("content-type") ?? contentType ?? "image/png";
10866
11698
  return { bytes: new Uint8Array(await res.arrayBuffer()), mime };
10867
11699
  }
10868
- var museImageResultSchema = import_zod18.z.object({
10869
- images: import_zod18.z.array(
10870
- import_zod18.z.object({
10871
- url: import_zod18.z.string().optional(),
10872
- content_type: import_zod18.z.string().nullable().optional()
11700
+ var museImageResultSchema = import_zod20.z.object({
11701
+ images: import_zod20.z.array(
11702
+ import_zod20.z.object({
11703
+ url: import_zod20.z.string().optional(),
11704
+ content_type: import_zod20.z.string().nullable().optional()
10873
11705
  })
10874
11706
  ).optional()
10875
11707
  });
@@ -11069,8 +11901,8 @@ function klingO1Input(req) {
11069
11901
  if (refs.length > 0) input.image_urls = refs;
11070
11902
  return input;
11071
11903
  }
11072
- var falVideoResultSchema = import_zod18.z.object({
11073
- video: import_zod18.z.object({ url: import_zod18.z.string().optional() }).optional()
11904
+ var falVideoResultSchema = import_zod20.z.object({
11905
+ video: import_zod20.z.object({ url: import_zod20.z.string().optional() }).optional()
11074
11906
  });
11075
11907
  function extractVideoUrl(result, endpoint, model) {
11076
11908
  const parsed = falVideoResultSchema.safeParse(result);
@@ -11162,11 +11994,11 @@ function planUsage(ctx, plan3) {
11162
11994
  }
11163
11995
 
11164
11996
  // src/adapters/google-genai.ts
11165
- var import_zod20 = require("zod");
11997
+ var import_zod22 = require("zod");
11166
11998
  var import_genai = require("@google/genai");
11167
11999
 
11168
12000
  // src/adapters/google-files.ts
11169
- var import_zod19 = require("zod");
12001
+ var import_zod21 = require("zod");
11170
12002
  var GOOGLE_FILES_BASE = "https://generativelanguage.googleapis.com";
11171
12003
  var GOOGLE_FILES_POLL_INTERVAL_MS = 2e3;
11172
12004
  var GOOGLE_FILES_POLL_TIMEOUT_MS = 5 * 60 * 1e3;
@@ -11176,17 +12008,17 @@ var GENERIC_MEDIA_TYPES = /* @__PURE__ */ new Set([
11176
12008
  "binary/octet-stream",
11177
12009
  "application/binary"
11178
12010
  ]);
11179
- var uploadedFileSchema = import_zod19.z.object({
11180
- file: import_zod19.z.object({
11181
- uri: import_zod19.z.string().optional(),
11182
- name: import_zod19.z.string().optional(),
11183
- state: import_zod19.z.string().optional(),
11184
- mimeType: import_zod19.z.string().optional()
12011
+ var uploadedFileSchema = import_zod21.z.object({
12012
+ file: import_zod21.z.object({
12013
+ uri: import_zod21.z.string().optional(),
12014
+ name: import_zod21.z.string().optional(),
12015
+ state: import_zod21.z.string().optional(),
12016
+ mimeType: import_zod21.z.string().optional()
11185
12017
  }).optional()
11186
12018
  });
11187
- var fileStateSchema = import_zod19.z.object({
11188
- state: import_zod19.z.string().optional(),
11189
- error: import_zod19.z.object({ message: import_zod19.z.string().optional() }).optional()
12019
+ var fileStateSchema = import_zod21.z.object({
12020
+ state: import_zod21.z.string().optional(),
12021
+ error: import_zod21.z.object({ message: import_zod21.z.string().optional() }).optional()
11190
12022
  });
11191
12023
  function resolveMime(declared, fallback) {
11192
12024
  const clean = declared?.split(";")[0]?.trim().toLowerCase();
@@ -11407,7 +12239,7 @@ var OMNI_POLL_INTERVAL_MS = 1e4;
11407
12239
  var RESULT_TIMEOUT_MS3 = 15 * 60 * 1e3;
11408
12240
  var OMNI_INLINE_LIMIT_BYTES = 4 * 1024 * 1024;
11409
12241
  var MEDIA_PART_INLINE_LIMIT_BYTES = 20 * 1024 * 1024;
11410
- var errorTextSchema = import_zod20.z.string();
12242
+ var errorTextSchema = import_zod22.z.string();
11411
12243
  function isGoogleGenaiVideoKnown(providerModelId) {
11412
12244
  return providerModelId.startsWith("veo-") || providerModelId.startsWith("gemini-omni");
11413
12245
  }
@@ -12071,15 +12903,15 @@ async function prepareGoogleMediaPart(ref, mediaType, ctx) {
12071
12903
  // src/adapters/google-image.ts
12072
12904
  var import_google2 = require("@ai-sdk/google");
12073
12905
  var import_ai2 = require("ai");
12074
- var import_zod21 = require("zod");
12906
+ var import_zod23 = require("zod");
12075
12907
  var GEMINI_IMAGE_TIMEOUT_MS = 6e5;
12076
12908
  var defaultGoogleImageDeps = {
12077
12909
  createGoogleClient: (opts) => (0, import_google2.createGoogleGenerativeAI)(opts),
12078
12910
  runTextGeneration: (opts) => (0, import_ai2.generateText)(opts)
12079
12911
  };
12080
- var causeChainNodeSchema = import_zod21.z.object({
12081
- message: import_zod21.z.string().optional(),
12082
- cause: import_zod21.z.unknown().optional()
12912
+ var causeChainNodeSchema = import_zod23.z.object({
12913
+ message: import_zod23.z.string().optional(),
12914
+ cause: import_zod23.z.unknown().optional()
12083
12915
  });
12084
12916
  function extractBlockReason(cause) {
12085
12917
  let current = cause;
@@ -12199,7 +13031,7 @@ function createGoogleImageAdapter(deps = defaultGoogleImageDeps) {
12199
13031
  var googleImageAdapter = createGoogleImageAdapter();
12200
13032
 
12201
13033
  // src/adapters/higgsfield.ts
12202
- var import_zod22 = require("zod");
13034
+ var import_zod24 = require("zod");
12203
13035
 
12204
13036
  // src/adapters/higgsfield-motions.ts
12205
13037
  var MOTION_MAP = {
@@ -12418,14 +13250,14 @@ function klingEndpointFields(providerModelId) {
12418
13250
  const path = (providerModelId.startsWith("/") ? providerModelId.slice(1) : providerModelId).toLowerCase();
12419
13251
  return KLING_ENDPOINT_FIELDS.get(path) ?? UNLISTED_KLING_FIELDS;
12420
13252
  }
12421
- var klingCreateSchema = import_zod22.z.object({ status_url: import_zod22.z.string() });
12422
- var klingStatusSchema = import_zod22.z.object({
12423
- status: import_zod22.z.string().optional(),
12424
- video: import_zod22.z.object({ url: import_zod22.z.string().optional() }).optional(),
13253
+ var klingCreateSchema = import_zod24.z.object({ status_url: import_zod24.z.string() });
13254
+ var klingStatusSchema = import_zod24.z.object({
13255
+ status: import_zod24.z.string().optional(),
13256
+ video: import_zod24.z.object({ url: import_zod24.z.string().optional() }).optional(),
12425
13257
  error: JsonValueSchema.optional()
12426
13258
  });
12427
- var errorMessageSchema = import_zod22.z.object({ message: import_zod22.z.string().optional() });
12428
- var textValueSchema = import_zod22.z.string();
13259
+ var errorMessageSchema = import_zod24.z.object({ message: import_zod24.z.string().optional() });
13260
+ var textValueSchema = import_zod24.z.string();
12429
13261
  function klingErrorDetail(error) {
12430
13262
  if (error === void 0) return "unknown_error";
12431
13263
  const asText = textValueSchema.safeParse(error);
@@ -12581,8 +13413,8 @@ async function generateKlingVideo(req, ctx) {
12581
13413
  }
12582
13414
  };
12583
13415
  }
12584
- var dopMotionOptionsSchema = import_zod22.z.object({
12585
- modelkit: import_zod22.z.object({ motion: import_zod22.z.string().optional() }).optional()
13416
+ var dopMotionOptionsSchema = import_zod24.z.object({
13417
+ modelkit: import_zod24.z.object({ motion: import_zod24.z.string().optional() }).optional()
12586
13418
  });
12587
13419
  function dopMotionId(ctx) {
12588
13420
  const parsed = dopMotionOptionsSchema.safeParse(ctx.model.providerOptions);
@@ -12598,7 +13430,7 @@ function dopMotionId(ctx) {
12598
13430
  });
12599
13431
  return id;
12600
13432
  }
12601
- var jsonRecordSchema = import_zod22.z.record(import_zod22.z.string(), JsonValueSchema);
13433
+ var jsonRecordSchema = import_zod24.z.record(import_zod24.z.string(), JsonValueSchema);
12602
13434
  var DOP_URL_KEYS = ["url", "video_url", "output_url", "result_url", "download_url"];
12603
13435
  var DOP_NESTED_KEYS = ["video", "result", "results"];
12604
13436
  function dopUrl(body) {
@@ -12626,8 +13458,8 @@ function dopUrl(body) {
12626
13458
  }
12627
13459
  return void 0;
12628
13460
  }
12629
- var dopCreateSchema = import_zod22.z.object({ id: import_zod22.z.string() });
12630
- var dopStatusSchema = import_zod22.z.object({ status: import_zod22.z.string().optional() });
13461
+ var dopCreateSchema = import_zod24.z.object({ id: import_zod24.z.string() });
13462
+ var dopStatusSchema = import_zod24.z.object({ status: import_zod24.z.string().optional() });
12631
13463
  async function generateDopVideo(req, ctx) {
12632
13464
  const firstFrame = req.firstFrame ? refToUrl(req.firstFrame) : void 0;
12633
13465
  if (!firstFrame) {
@@ -12755,7 +13587,7 @@ var higgsfieldAdapter = {
12755
13587
 
12756
13588
  // src/adapters/openai-image.ts
12757
13589
  var import_openai2 = __toESM(require("openai"), 1);
12758
- var import_zod23 = require("zod");
13590
+ var import_zod25 = require("zod");
12759
13591
  var MAX_EDIT_REFERENCES = 16;
12760
13592
  function aspectRatioToSize(ratio, tier) {
12761
13593
  const TIER_LONG_EDGE = {
@@ -12838,9 +13670,9 @@ function toProviderError2(cause, ctx) {
12838
13670
  ctx.model.id
12839
13671
  );
12840
13672
  }
12841
- var openaiUsageSchema = import_zod23.z.object({
12842
- input_tokens: import_zod23.z.number().optional(),
12843
- output_tokens: import_zod23.z.number().optional()
13673
+ var openaiUsageSchema = import_zod25.z.object({
13674
+ input_tokens: import_zod25.z.number().optional(),
13675
+ output_tokens: import_zod25.z.number().optional()
12844
13676
  });
12845
13677
  var openaiImageAdapter = {
12846
13678
  id: "openai-image",
@@ -13252,13 +14084,13 @@ var prodiaAdapter = {
13252
14084
  var import_replicate = __toESM(require("replicate"), 1);
13253
14085
 
13254
14086
  // src/adapters/replicate-http.ts
13255
- var import_zod24 = require("zod");
13256
- var predictionSchema = import_zod24.z.object({
13257
- id: import_zod24.z.string(),
13258
- status: import_zod24.z.string(),
14087
+ var import_zod26 = require("zod");
14088
+ var predictionSchema = import_zod26.z.object({
14089
+ id: import_zod26.z.string(),
14090
+ status: import_zod26.z.string(),
13259
14091
  output: JsonValueSchema.optional(),
13260
14092
  error: JsonValueSchema.optional(),
13261
- metrics: import_zod24.z.object({ predict_time: import_zod24.z.number().optional() }).optional()
14093
+ metrics: import_zod26.z.object({ predict_time: import_zod26.z.number().optional() }).optional()
13262
14094
  });
13263
14095
  function createReplicateHttpClient(opts) {
13264
14096
  async function request(path, body, signal) {
@@ -13309,7 +14141,7 @@ function createReplicateHttpClient(opts) {
13309
14141
  }
13310
14142
 
13311
14143
  // src/adapters/replicate.ts
13312
- var import_zod25 = require("zod");
14144
+ var import_zod27 = require("zod");
13313
14145
  var POLL_INTERVAL_MS = 1e3;
13314
14146
  var POLL_TIMEOUT_MS = 15 * 6e4;
13315
14147
  var defaultReplicateDeps = {
@@ -13349,8 +14181,8 @@ function route(providerModelId) {
13349
14181
  if (!providerModelId.includes("/")) return { version: providerModelId };
13350
14182
  return { model: providerModelId };
13351
14183
  }
13352
- var replicateResponseStatusSchema = import_zod25.z.object({
13353
- response: import_zod25.z.object({ status: import_zod25.z.number() }).partial()
14184
+ var replicateResponseStatusSchema = import_zod27.z.object({
14185
+ response: import_zod27.z.object({ status: import_zod27.z.number() }).partial()
13354
14186
  });
13355
14187
  function replicateError(cause, ctx) {
13356
14188
  if (isModelKitError(cause)) return cause;
@@ -13359,10 +14191,6 @@ function replicateError(cause, ctx) {
13359
14191
  const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
13360
14192
  return classifyThrown("replicate", cause, ctx.model.id, { status, body: info.body });
13361
14193
  }
13362
- function baseModelId(providerModelId) {
13363
- const colon = providerModelId.indexOf(":");
13364
- return colon === -1 ? providerModelId : providerModelId.slice(0, colon);
13365
- }
13366
14194
  function predictionErrorBody(cause) {
13367
14195
  const parsed = JsonValueSchema.safeParse(cause);
13368
14196
  if (parsed.success) return parsed.data;
@@ -13377,7 +14205,7 @@ function isUrlFn(value) {
13377
14205
  function extractOutputUrl(output) {
13378
14206
  const root = Array.isArray(output) ? output[0] : output;
13379
14207
  if (root === void 0) throw noOutput();
13380
- const asString = import_zod25.z.string().safeParse(root);
14208
+ const asString = import_zod27.z.string().safeParse(root);
13381
14209
  if (asString.success && asString.data) return asString.data;
13382
14210
  if (root instanceof URL) return root.href;
13383
14211
  if (isObjectOutput(root)) {
@@ -13386,15 +14214,15 @@ function extractOutputUrl(output) {
13386
14214
  if (urlValue !== void 0 && isUrlFn(urlValue)) {
13387
14215
  const called = urlValue();
13388
14216
  if (called instanceof URL) return called.href;
13389
- const calledString = import_zod25.z.string().safeParse(called);
14217
+ const calledString = import_zod27.z.string().safeParse(called);
13390
14218
  if (calledString.success && calledString.data) return calledString.data;
13391
14219
  } else {
13392
- const direct = import_zod25.z.string().safeParse(urlValue);
14220
+ const direct = import_zod27.z.string().safeParse(urlValue);
13393
14221
  if (direct.success && direct.data) return direct.data;
13394
14222
  }
13395
14223
  }
13396
14224
  if ("default" in root) {
13397
- const fallback = import_zod25.z.string().safeParse(root.default);
14225
+ const fallback = import_zod27.z.string().safeParse(root.default);
13398
14226
  if (fallback.success && fallback.data) return fallback.data;
13399
14227
  }
13400
14228
  }
@@ -13455,7 +14283,7 @@ async function runPrediction(ctx, input, deps) {
13455
14283
  }
13456
14284
  return void 0;
13457
14285
  }, pollOpts);
13458
- const predictTime = import_zod25.z.number().safeParse(done.metrics?.predict_time);
14286
+ const predictTime = import_zod27.z.number().safeParse(done.metrics?.predict_time);
13459
14287
  if (done.output === void 0) throw noOutput();
13460
14288
  return {
13461
14289
  url: extractOutputUrl(done.output),
@@ -13516,17 +14344,7 @@ var REPLICATE_IMAGE_KINDS = {
13516
14344
  "qwen-edit-apps/qwen-image-edit-plus-lora-skin": "qwen-edit"
13517
14345
  };
13518
14346
  function imageKind(providerModelId) {
13519
- return REPLICATE_IMAGE_KINDS[baseModelId(providerModelId)] ?? "generic";
13520
- }
13521
- var REPLICATE_VIDEO_KINDS = {
13522
- "kling-video/v2.5-turbo/pro/image-to-video": "kling",
13523
- "kling-video/v3.0/pro/image-to-video": "kling",
13524
- "kwaivgi/kling-v3-video": "kling",
13525
- "kwaivgi/kling-v3-omni-video": "kling-omni",
13526
- "minimax/hailuo-02": "hailuo"
13527
- };
13528
- function videoKind(providerModelId) {
13529
- return REPLICATE_VIDEO_KINDS[baseModelId(providerModelId)];
14347
+ return REPLICATE_IMAGE_KINDS[replicateBaseModelId(providerModelId)] ?? "generic";
13530
14348
  }
13531
14349
  function isReplicateVideoKnown(providerModelId) {
13532
14350
  return videoKind(providerModelId) !== void 0;
@@ -13537,7 +14355,7 @@ var REPLICATE_AUDIO_KINDS = {
13537
14355
  "google/lyria-2": "lyria"
13538
14356
  };
13539
14357
  function audioKind(providerModelId) {
13540
- return REPLICATE_AUDIO_KINDS[baseModelId(providerModelId)];
14358
+ return REPLICATE_AUDIO_KINDS[replicateBaseModelId(providerModelId)];
13541
14359
  }
13542
14360
  function isReplicateAudioKnown(providerModelId) {
13543
14361
  return audioKind(providerModelId) !== void 0;
@@ -13741,14 +14559,6 @@ function replicateVideoResolution(providerModelId, req) {
13741
14559
  if (kind === "hailuo") return hailuoResolution(req);
13742
14560
  return req.resolution;
13743
14561
  }
13744
- var KLING_TIERS = [
13745
- { mode: "standard", resolution: "720p" },
13746
- { mode: "pro", resolution: "1080p" },
13747
- { mode: "4k", resolution: "4k" }
13748
- ];
13749
- function klingTier(req) {
13750
- return KLING_TIERS.find((tier) => tier.resolution === req.resolution) ?? KLING_TIERS.find((tier) => tier.mode === req.mode) ?? KLING_TIERS[0];
13751
- }
13752
14562
  function klingOmniInput(req) {
13753
14563
  const input = {
13754
14564
  prompt: req.prompt,
@@ -13826,7 +14636,7 @@ async function generateReplicateVideo(req, ctx, deps) {
13826
14636
  throw replicateError(cause, ctx);
13827
14637
  }
13828
14638
  if (current.status === "succeeded") {
13829
- const predictTime = import_zod25.z.number().safeParse(current.metrics?.predict_time);
14639
+ const predictTime = import_zod27.z.number().safeParse(current.metrics?.predict_time);
13830
14640
  if (current.output === void 0) throw noOutput();
13831
14641
  return {
13832
14642
  url: extractOutputUrl(current.output),
@@ -13968,7 +14778,7 @@ async function generateReplicateAudio(req, ctx, deps) {
13968
14778
  // src/adapters/xai-video.ts
13969
14779
  var import_ai3 = require("ai");
13970
14780
  var import_xai2 = require("@ai-sdk/xai");
13971
- var import_zod26 = require("zod");
14781
+ var import_zod28 = require("zod");
13972
14782
  var POLL_INTERVAL_MS2 = 1e4;
13973
14783
  var POLL_TIMEOUT_MS2 = 15 * 6e4;
13974
14784
  var defaultXaiDeps = {
@@ -13981,8 +14791,8 @@ function createXaiVideoAdapter(deps = defaultXaiDeps) {
13981
14791
  };
13982
14792
  }
13983
14793
  var xaiVideoAdapter = createXaiVideoAdapter();
13984
- var xaiResponseStatusSchema = import_zod26.z.object({
13985
- response: import_zod26.z.object({ status: import_zod26.z.number() }).partial()
14794
+ var xaiResponseStatusSchema = import_zod28.z.object({
14795
+ response: import_zod28.z.object({ status: import_zod28.z.number() }).partial()
13986
14796
  });
13987
14797
  function xaiError(cause, ctx) {
13988
14798
  const info = describeThrown(cause);
@@ -13990,12 +14800,12 @@ function xaiError(cause, ctx) {
13990
14800
  const status = info.status ?? (nested.success ? nested.data.response?.status : void 0);
13991
14801
  return classifyThrown("xai-video", cause, ctx.model.id, { status, body: info.body });
13992
14802
  }
13993
- var xaiMetaSchema = import_zod26.z.object({
14803
+ var xaiMetaSchema = import_zod28.z.object({
13994
14804
  videoUrl: JsonValueSchema.optional(),
13995
14805
  costInUsdTicks: JsonValueSchema.optional(),
13996
14806
  duration: JsonValueSchema.optional()
13997
14807
  });
13998
- var xaiProviderMetadataSchema = import_zod26.z.object({ xai: xaiMetaSchema });
14808
+ var xaiProviderMetadataSchema = import_zod28.z.object({ xai: xaiMetaSchema });
13999
14809
  function metaOf(result) {
14000
14810
  const parsed = xaiProviderMetadataSchema.partial().safeParse(result.providerMetadata);
14001
14811
  if (!parsed.success) return {};
@@ -14111,7 +14921,7 @@ async function mapResult(ctx, req, result) {
14111
14921
  };
14112
14922
  }
14113
14923
  const meta = metaOf(result);
14114
- const videoUrl = import_zod26.z.string().safeParse(meta.videoUrl);
14924
+ const videoUrl = import_zod28.z.string().safeParse(meta.videoUrl);
14115
14925
  if (videoUrl.success && videoUrl.data) {
14116
14926
  const res = await ctx.fetch(videoUrl.data);
14117
14927
  if (!res.ok) {
@@ -14134,7 +14944,7 @@ async function mapResult(ctx, req, result) {
14134
14944
  });
14135
14945
  }
14136
14946
  function usage2(ctx, req, meta) {
14137
- const costTicks = import_zod26.z.number().safeParse(meta.costInUsdTicks);
14947
+ const costTicks = import_zod28.z.number().safeParse(meta.costInUsdTicks);
14138
14948
  const cost = costTicks.success ? costTicks.data / 1e10 : void 0;
14139
14949
  const event = {
14140
14950
  model: ctx.model.id,
@@ -14186,10 +14996,10 @@ var DEFAULT_ADAPTERS = {
14186
14996
  };
14187
14997
 
14188
14998
  // src/catalog/data-only.ts
14189
- function hasValidInputSpec(row) {
14190
- const raw = row.providerOptions?.["modelkit"]?.["inputSpec"];
14999
+ function hasValidInputSpec(row2) {
15000
+ const raw = row2.providerOptions?.["modelkit"]?.["inputSpec"];
14191
15001
  if (raw === void 0) return false;
14192
- return validateInputSpec(raw, row).ok;
15002
+ return validateInputSpec(raw, row2).ok;
14193
15003
  }
14194
15004
  function assertNever(value) {
14195
15005
  throw new Error(`Unhandled adapter: ${String(value)}`);
@@ -14207,6 +15017,7 @@ function adapterServesType(adapter, type) {
14207
15017
  if (type === "lipsync") return adapter.lipsync !== void 0;
14208
15018
  if (type === "transcription") return adapter.transcribe !== void 0;
14209
15019
  if (type === "video-tool") return adapter.submitVideoTool !== void 0;
15020
+ if (type === "model3d") return adapter.submitModel3d !== void 0;
14210
15021
  return adapter.languageModel !== void 0;
14211
15022
  }
14212
15023
  var FAL_NODE_TYPES = /* @__PURE__ */ new Set([
@@ -14218,18 +15029,18 @@ var FAL_NODE_TYPES = /* @__PURE__ */ new Set([
14218
15029
  "transcription",
14219
15030
  "mask"
14220
15031
  ]);
14221
- function dataOnlyCapable(row) {
14222
- const adapter = DEFAULT_ADAPTERS[row.adapter];
14223
- if (!adapterServesType(adapter, row.type)) {
14224
- return { ok: false, reason: `${row.adapter} cannot serve ${row.type} rows` };
15032
+ function dataOnlyCapable(row2) {
15033
+ const adapter = DEFAULT_ADAPTERS[row2.adapter];
15034
+ if (!adapterServesType(adapter, row2.type)) {
15035
+ return { ok: false, reason: `${row2.adapter} cannot serve ${row2.type} rows` };
14225
15036
  }
14226
- if (FAL_NODE_TYPES.has(row.type) && row.adapter !== "fal") {
14227
- return { ok: false, reason: `only fal serves ${row.type} rows` };
15037
+ if (FAL_NODE_TYPES.has(row2.type) && row2.adapter !== "fal") {
15038
+ return { ok: false, reason: `only fal serves ${row2.type} rows` };
14228
15039
  }
14229
- switch (row.adapter) {
15040
+ switch (row2.adapter) {
14230
15041
  case "ai-sdk-text": {
14231
15042
  try {
14232
- textProviderOf(row);
15043
+ textProviderOf(row2);
14233
15044
  return { ok: true };
14234
15045
  } catch {
14235
15046
  return {
@@ -14247,14 +15058,14 @@ function dataOnlyCapable(row) {
14247
15058
  return { ok: true };
14248
15059
  }
14249
15060
  case "google-genai": {
14250
- if (row.type === "video") {
14251
- return isGoogleGenaiVideoKnown(row.providerModelId) ? { ok: true } : { ok: false, reason: "google-genai video needs a veo- or gemini-omni id" };
15061
+ if (row2.type === "video") {
15062
+ return isGoogleGenaiVideoKnown(row2.providerModelId) ? { ok: true } : { ok: false, reason: "google-genai video needs a veo- or gemini-omni id" };
14252
15063
  }
14253
- return isGoogleGenaiAudioKnown(row.providerModelId) ? { ok: true } : { ok: false, reason: "google-genai audio needs a lyria- id" };
15064
+ return isGoogleGenaiAudioKnown(row2.providerModelId) ? { ok: true } : { ok: false, reason: "google-genai audio needs a lyria- id" };
14254
15065
  }
14255
15066
  case "replicate": {
14256
- if (row.type === "video") {
14257
- if (isReplicateVideoKnown(row.providerModelId) || hasValidInputSpec(row)) {
15067
+ if (row2.type === "video") {
15068
+ if (isReplicateVideoKnown(row2.providerModelId) || hasValidInputSpec(row2)) {
14258
15069
  return { ok: true };
14259
15070
  }
14260
15071
  return {
@@ -14262,8 +15073,8 @@ function dataOnlyCapable(row) {
14262
15073
  reason: "replicate video needs a known kind or a valid inputSpec"
14263
15074
  };
14264
15075
  }
14265
- if (row.type === "audio") {
14266
- if (isReplicateAudioKnown(row.providerModelId) || hasValidInputSpec(row)) {
15076
+ if (row2.type === "audio") {
15077
+ if (isReplicateAudioKnown(row2.providerModelId) || hasValidInputSpec(row2)) {
14267
15078
  return { ok: true };
14268
15079
  }
14269
15080
  return {
@@ -14274,31 +15085,31 @@ function dataOnlyCapable(row) {
14274
15085
  return { ok: true };
14275
15086
  }
14276
15087
  case "fal": {
14277
- if (row.type === "video") {
14278
- return isFalVideoKnown(row.providerModelId) ? { ok: true } : { ok: false, reason: "fal video needs an id from a fal video family" };
15088
+ if (row2.type === "video") {
15089
+ return isFalVideoKnown(row2.providerModelId) ? { ok: true } : { ok: false, reason: "fal video needs an id from a fal video family" };
14279
15090
  }
14280
- if (row.type === "mask") {
14281
- return row.providerModelId === SAM3_IMAGE ? { ok: true } : { ok: false, reason: `fal maps mask rows only to ${SAM3_IMAGE}` };
15091
+ if (row2.type === "mask") {
15092
+ return row2.providerModelId === SAM3_IMAGE ? { ok: true } : { ok: false, reason: `fal maps mask rows only to ${SAM3_IMAGE}` };
14282
15093
  }
14283
- if (row.type === "video-tool" && row.constraints.tool?.kind === "subtitles") {
14284
- return row.providerModelId === VEED_SUBTITLES2 ? { ok: true } : { ok: false, reason: `fal maps subtitles only to ${VEED_SUBTITLES2}` };
15094
+ if (row2.type === "video-tool" && row2.constraints.tool?.kind === "subtitles") {
15095
+ return row2.providerModelId === VEED_SUBTITLES2 ? { ok: true } : { ok: false, reason: `fal maps subtitles only to ${VEED_SUBTITLES2}` };
14285
15096
  }
14286
- if (FAL_MEDIA_TYPES.has(row.type)) {
14287
- return isFalMediaKnown(row.type, row.providerModelId) ? { ok: true } : { ok: false, reason: `fal has no ${row.type} mapping for this id` };
15097
+ if (FAL_MEDIA_TYPES.has(row2.type)) {
15098
+ return isFalMediaKnown(row2.type, row2.providerModelId) ? { ok: true } : { ok: false, reason: `fal has no ${row2.type} mapping for this id` };
14288
15099
  }
14289
15100
  return { ok: true };
14290
15101
  }
14291
15102
  case "prodia": {
14292
- return isProdiaCapable(row.providerModelId) ? { ok: true } : { ok: false, reason: "prodia has no job mapping for this id" };
15103
+ return isProdiaCapable(row2.providerModelId) ? { ok: true } : { ok: false, reason: "prodia has no job mapping for this id" };
14293
15104
  }
14294
15105
  case "higgsfield": {
14295
- return isHiggsfieldCapable(row.providerModelId) ? { ok: true } : {
15106
+ return isHiggsfieldCapable(row2.providerModelId) ? { ok: true } : {
14296
15107
  ok: false,
14297
15108
  reason: "higgsfield providerModelId must be a platform path, not a URL"
14298
15109
  };
14299
15110
  }
14300
15111
  default: {
14301
- return assertNever(row.adapter);
15112
+ return assertNever(row2.adapter);
14302
15113
  }
14303
15114
  }
14304
15115
  }
@@ -14316,22 +15127,22 @@ var liveState = store[KEY] ??= {
14316
15127
  var liveCatalog = liveState.catalog;
14317
15128
 
14318
15129
  // src/catalog/load.ts
14319
- var import_zod27 = require("zod");
15130
+ var import_zod29 = require("zod");
14320
15131
  function rowCount() {
14321
15132
  return liveCatalog.list({ lifecycle: ["active", "deprecated", "retired"] }).length;
14322
15133
  }
14323
15134
  function authHeaders(auth) {
14324
15135
  return "bearer" in auth ? { Authorization: `Bearer ${auth.bearer}` } : { "x-api-key": auth.apiKey };
14325
15136
  }
14326
- var EnvelopeSchema = import_zod27.z.object({
14327
- rows: import_zod27.z.array(JsonValueSchema),
14328
- revision: import_zod27.z.string().optional()
15137
+ var EnvelopeSchema = import_zod29.z.object({
15138
+ rows: import_zod29.z.array(JsonValueSchema),
15139
+ revision: import_zod29.z.string().optional()
14329
15140
  });
14330
15141
  function dropReason(path, message) {
14331
15142
  return path.length === 0 ? message : `${path.map((part) => String(part)).join(".")} ${message}`;
14332
15143
  }
14333
15144
  function rowId(raw) {
14334
- const parsed = import_zod27.z.object({ id: import_zod27.z.string().min(1) }).loose().safeParse(raw);
15145
+ const parsed = import_zod29.z.object({ id: import_zod29.z.string().min(1) }).loose().safeParse(raw);
14335
15146
  if (!parsed.success) return "?";
14336
15147
  return parsed.data.id;
14337
15148
  }
@@ -14347,22 +15158,22 @@ function quarantine(rawRows, logger) {
14347
15158
  dropped += 1;
14348
15159
  continue;
14349
15160
  }
14350
- const row = parsed.data;
14351
- const inputSpecRaw = row.providerOptions?.["modelkit"]?.["inputSpec"];
15161
+ const row2 = parsed.data;
15162
+ const inputSpecRaw = row2.providerOptions?.["modelkit"]?.["inputSpec"];
14352
15163
  if (inputSpecRaw !== void 0) {
14353
- const result = validateInputSpec(inputSpecRaw, row);
15164
+ const result = validateInputSpec(inputSpecRaw, row2);
14354
15165
  if (!result.ok) {
14355
15166
  const first = result.issues[0];
14356
15167
  const detail = first ? dropReason(first.path, first.message) : "invalid inputSpec";
14357
15168
  logger.warn(
14358
- `[modelkit] catalog row ${row.id} has an invalid providerOptions.modelkit.inputSpec: ${detail}; calls fail until it is fixed`
15169
+ `[modelkit] catalog row ${row2.id} has an invalid providerOptions.modelkit.inputSpec: ${detail}; calls fail until it is fixed`
14359
15170
  );
14360
15171
  }
14361
15172
  }
14362
- const normalised = normaliseConventions(row);
15173
+ const normalised = normaliseConventions(row2);
14363
15174
  if (normalised.invalidKeys.length > 0) {
14364
15175
  logger.warn(
14365
- `[modelkit] catalog row ${row.id} has an invalid ${normalised.invalidKeys.join(", ")}; read as not set`
15176
+ `[modelkit] catalog row ${row2.id} has an invalid ${normalised.invalidKeys.join(", ")}; read as not set`
14366
15177
  );
14367
15178
  }
14368
15179
  valid.push(normalised.row);
@@ -14376,10 +15187,10 @@ function quarantine(rawRows, logger) {
14376
15187
  if (!firstByIndex.has(issue.index)) firstByIndex.set(issue.index, issue);
14377
15188
  }
14378
15189
  for (const [index, issue] of [...firstByIndex.entries()].sort((a, b) => a[0] - b[0])) {
14379
- const row = kept[index];
14380
- if (!row) continue;
15190
+ const row2 = kept[index];
15191
+ if (!row2) continue;
14381
15192
  logger.warn(
14382
- `[modelkit] catalog row dropped id=${row.id} reason=${String(issue.path[0] ?? "")} ${issue.message}`
15193
+ `[modelkit] catalog row dropped id=${row2.id} reason=${String(issue.path[0] ?? "")} ${issue.message}`
14383
15194
  );
14384
15195
  }
14385
15196
  const dropSet = new Set(firstByIndex.keys());
@@ -14975,8 +15786,10 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
14975
15786
  warnings
14976
15787
  );
14977
15788
  if (aspectRatio !== void 0) merged.aspectRatio = aspectRatio;
15789
+ fillReplicateKlingResolution(model, merged);
14978
15790
  const resolution = resolveVideoResolution(merged.resolution, model, onUnsupported, warnings);
14979
15791
  if (resolution !== void 0) merged.resolution = resolution;
15792
+ if (isReplicateKling(model)) delete merged.mode;
14980
15793
  const duration = resolveDuration(
14981
15794
  merged.durationSeconds,
14982
15795
  c.durations,
@@ -15079,16 +15892,16 @@ function resolveVideoOptions(model, request, onUnsupported = "error") {
15079
15892
  }
15080
15893
  function checkVideoRequired(model, req) {
15081
15894
  const c = model.constraints;
15082
- const present = (input) => input === "references" ? compact(req.referenceImages).length + compact(req.referenceVideos).length + compact(req.referenceAudios).length > 0 : input !== "sourceAudio" && req[input] !== void 0;
15895
+ const present2 = (input) => input === "references" ? compact(req.referenceImages).length + compact(req.referenceVideos).length + compact(req.referenceAudios).length > 0 : input !== "sourceAudio" && req[input] !== void 0;
15083
15896
  for (const input of c.requires ?? []) {
15084
- if (!present(input))
15897
+ if (!present2(input))
15085
15898
  throw new ModelKitError({
15086
15899
  code: "missing_input",
15087
15900
  message: `${model.id} requires ${input}`,
15088
15901
  model: model.id
15089
15902
  });
15090
15903
  }
15091
- if (c.requiresOneOf && !c.requiresOneOf.some(present)) {
15904
+ if (c.requiresOneOf && !c.requiresOneOf.some(present2)) {
15092
15905
  throw new ModelKitError({
15093
15906
  code: "missing_input",
15094
15907
  message: `${model.id} requires one of: ${c.requiresOneOf.join(", ")}`,
@@ -15136,8 +15949,8 @@ function resolveAudioOptions(model, request, onUnsupported = "error") {
15136
15949
  if (references.length > 0) merged.references = references;
15137
15950
  else delete merged.references;
15138
15951
  for (const input of c.requires ?? []) {
15139
- const present = input === "references" ? references.length > 0 : input === "sourceVideo" && merged.sourceVideo !== void 0;
15140
- if (!present)
15952
+ const present2 = input === "references" ? references.length > 0 : input === "sourceVideo" && merged.sourceVideo !== void 0;
15953
+ if (!present2)
15141
15954
  throw new ModelKitError({
15142
15955
  code: "missing_input",
15143
15956
  message: `${model.id} requires ${input}`,
@@ -15191,12 +16004,12 @@ function unsupported3(model, message) {
15191
16004
  model: model.id
15192
16005
  });
15193
16006
  }
15194
- function checkRequired(model, present) {
16007
+ function checkRequired(model, present2) {
15195
16008
  for (const input of model.constraints.requires ?? []) {
15196
- if (present[input] !== true) throw missing2(model, input);
16009
+ if (present2[input] !== true) throw missing2(model, input);
15197
16010
  }
15198
16011
  const oneOf = model.constraints.requiresOneOf;
15199
- if (oneOf !== void 0 && !oneOf.some((input) => present[input] === true)) {
16012
+ if (oneOf !== void 0 && !oneOf.some((input) => present2[input] === true)) {
15200
16013
  throw missing2(model, `one of ${oneOf.join(", ")}`);
15201
16014
  }
15202
16015
  }
@@ -15458,7 +16271,7 @@ function keysFromEnv(env, prefix = "") {
15458
16271
 
15459
16272
  // src/text.ts
15460
16273
  var import_ai4 = require("ai");
15461
- var import_zod28 = require("zod");
16274
+ var import_zod30 = require("zod");
15462
16275
  function mergeTextProviderOptions(catalog, caller) {
15463
16276
  const merged = {};
15464
16277
  const catalogOptions = catalog.providerOptions ?? {};
@@ -15497,8 +16310,8 @@ function passthroughTextModel(model) {
15497
16310
  pricingKind: "token"
15498
16311
  };
15499
16312
  }
15500
- var perplexityCostSchema = import_zod28.z.object({
15501
- perplexity: import_zod28.z.object({ cost: import_zod28.z.object({ totalCost: import_zod28.z.number().finite().nonnegative() }) })
16313
+ var perplexityCostSchema = import_zod30.z.object({
16314
+ perplexity: import_zod30.z.object({ cost: import_zod30.z.object({ totalCost: import_zod30.z.number().finite().nonnegative() }) })
15502
16315
  });
15503
16316
  function reportedCostUsd(metadata) {
15504
16317
  const parsed = perplexityCostSchema.safeParse(metadata);
@@ -15571,7 +16384,7 @@ function createTextSteps(initial, resolve, callerProviderOptions) {
15571
16384
 
15572
16385
  // src/client.ts
15573
16386
  var import_ai5 = require("ai");
15574
- var import_zod29 = require("zod");
16387
+ var import_zod31 = require("zod");
15575
16388
 
15576
16389
  // src/generated-image.ts
15577
16390
  function toGeneratedImage(image) {
@@ -15598,8 +16411,8 @@ function isAnthropicTransport(value) {
15598
16411
  return ANTHROPIC_TRANSPORTS.some((transport) => transport === value);
15599
16412
  }
15600
16413
  function preferredAnthropicTransport(model, routing) {
15601
- const row = model.providerOptions?.["modelkit"]?.["transport"];
15602
- if (isAnthropicTransport(row)) return row;
16414
+ const row2 = model.providerOptions?.["modelkit"]?.["transport"];
16415
+ if (isAnthropicTransport(row2)) return row2;
15603
16416
  return routing.anthropic ?? "direct";
15604
16417
  }
15605
16418
  function resolveAnthropicTransport(model, config, tier, warn) {
@@ -15626,6 +16439,85 @@ function textUsageProvider(model, transport) {
15626
16439
  return transport === "bedrock" ? BEDROCK_USAGE_PROVIDER : textProviderOf(model);
15627
16440
  }
15628
16441
 
16442
+ // src/provider-job.ts
16443
+ var VIDEO_TOOL_JOB = {
16444
+ type: "video-tool",
16445
+ noun: "a video tool",
16446
+ plural: "video tools",
16447
+ methods: (a) => ({
16448
+ submit: a.submitVideoTool?.bind(a),
16449
+ status: a.videoToolStatus?.bind(a),
16450
+ result: a.videoToolResult?.bind(a),
16451
+ cancel: a.cancelVideoTool?.bind(a)
16452
+ })
16453
+ };
16454
+ var MODEL3D_JOB = {
16455
+ type: "model3d",
16456
+ noun: "a 3D model",
16457
+ plural: "3D models",
16458
+ methods: (a) => ({
16459
+ submit: a.submitModel3d?.bind(a),
16460
+ status: a.model3dStatus?.bind(a),
16461
+ result: a.model3dResult?.bind(a),
16462
+ cancel: a.cancelModel3d?.bind(a)
16463
+ })
16464
+ };
16465
+ function providerJobMethods(kind, deps) {
16466
+ function target(modelId, call) {
16467
+ mediaRetryOptions(call);
16468
+ const model = deps.catalog.require(modelId);
16469
+ if (model.type !== kind.type)
16470
+ throw new ModelKitError({
16471
+ code: "unsupported_option",
16472
+ message: `${model.id} is not ${kind.noun}`,
16473
+ model: model.id
16474
+ });
16475
+ const { adapter, ctx } = deps.context(model, call);
16476
+ return { methods: kind.methods(adapter), adapter, ctx };
16477
+ }
16478
+ function missing3(adapter, model) {
16479
+ return new ModelKitError({
16480
+ code: "unsupported_option",
16481
+ message: `${adapter.id} has no ${kind.plural}`,
16482
+ model: model.id
16483
+ });
16484
+ }
16485
+ return {
16486
+ async submit(req, call = {}) {
16487
+ const { webhookUrl, ...rest } = call;
16488
+ const { methods, adapter, ctx } = target(req.model, rest);
16489
+ if (!methods.submit) throw missing3(adapter, ctx.model);
16490
+ const submittedAt = Date.now();
16491
+ const submission = await methods.submit(
16492
+ req,
16493
+ ctx,
16494
+ webhookUrl !== void 0 ? { webhookUrl } : {}
16495
+ );
16496
+ return { ...submission, submittedAt };
16497
+ },
16498
+ async status(sub, call = {}) {
16499
+ const { methods, adapter, ctx } = target(sub.model, call);
16500
+ if (!methods.status) throw missing3(adapter, ctx.model);
16501
+ return methods.status(sub, ctx);
16502
+ },
16503
+ async result(sub, call = {}) {
16504
+ const { webhook, ...rest } = call;
16505
+ const { methods, adapter, ctx } = target(sub.model, rest);
16506
+ if (!methods.result) throw missing3(adapter, ctx.model);
16507
+ const result = await methods.result(sub, ctx, webhook);
16508
+ const base = { ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit };
16509
+ const usage3 = sub.submittedAt === void 0 ? base : deps.timed(base, sub.submittedAt);
16510
+ await deps.emit(usage3);
16511
+ return { ...result, usage: usage3 };
16512
+ },
16513
+ async cancel(sub, call = {}) {
16514
+ const { methods, adapter, ctx } = target(sub.model, call);
16515
+ if (!methods.cancel) throw missing3(adapter, ctx.model);
16516
+ return methods.cancel(sub, ctx);
16517
+ }
16518
+ };
16519
+ }
16520
+
15629
16521
  // src/resolve-call.ts
15630
16522
  var MEDIA_METHODS = {
15631
16523
  text: [],
@@ -15641,7 +16533,10 @@ var MEDIA_METHODS = {
15641
16533
  lipsync: ["lipsync"],
15642
16534
  dubbing: ["dub"],
15643
16535
  transcription: ["transcribe"],
15644
- "video-tool": ["submitVideoTool"]
16536
+ "video-tool": ["submitVideoTool"],
16537
+ // 3D jobs run through submitModel3d, which checks the row type itself; their preflight
16538
+ // is model3dInputRefusal, not resolveOptions.
16539
+ model3d: []
15645
16540
  };
15646
16541
  var METHOD_NOUN = {
15647
16542
  generateImage: "an image model",
@@ -15838,10 +16733,10 @@ function textAbortOptions(sdk, context) {
15838
16733
  if (abortSignal) return { abortSignal };
15839
16734
  return {};
15840
16735
  }
15841
- var catalogId = import_zod29.z.string();
15842
- var exactSize = import_zod29.z.templateLiteral([import_zod29.z.number(), "x", import_zod29.z.number()]);
15843
- var sdkRatio = import_zod29.z.templateLiteral([import_zod29.z.number(), ":", import_zod29.z.number()]);
15844
- var sizeTier = import_zod29.z.enum(["512", "1K", "2K", "4K"]);
16736
+ var catalogId = import_zod31.z.string();
16737
+ var exactSize = import_zod31.z.templateLiteral([import_zod31.z.number(), "x", import_zod31.z.number()]);
16738
+ var sdkRatio = import_zod31.z.templateLiteral([import_zod31.z.number(), ":", import_zod31.z.number()]);
16739
+ var sizeTier = import_zod31.z.enum(["512", "1K", "2K", "4K"]);
15845
16740
  function isCatalogId(model) {
15846
16741
  return catalogId.safeParse(model).success;
15847
16742
  }
@@ -15951,19 +16846,14 @@ function createModelKit(config, adapters) {
15951
16846
  if (call.signal) ctx.signal = call.signal;
15952
16847
  return { adapter, ctx };
15953
16848
  }
15954
- function videoToolTarget(modelId, call) {
15955
- mediaRetryOptions(call);
15956
- const model = catalog.require(modelId);
15957
- assertMethod(model, "submitVideoTool");
15958
- return context(model, call, []);
15959
- }
15960
- function noVideoTools(adapter, model) {
15961
- return new ModelKitError({
15962
- code: "unsupported_option",
15963
- message: `${adapter.id} has no video tools`,
15964
- model: model.id
15965
- });
15966
- }
16849
+ const jobDeps = {
16850
+ catalog,
16851
+ context: (model, call) => context(model, call, []),
16852
+ timed,
16853
+ emit
16854
+ };
16855
+ const videoToolJobs = providerJobMethods(VIDEO_TOOL_JOB, jobDeps);
16856
+ const model3dJobs = providerJobMethods(MODEL3D_JOB, jobDeps);
15967
16857
  function timed(event, startedAt) {
15968
16858
  if (event.latencyMs !== void 0) return event;
15969
16859
  return { ...event, latencyMs: Math.max(0, Date.now() - startedAt) };
@@ -15979,8 +16869,8 @@ function createModelKit(config, adapters) {
15979
16869
  }
15980
16870
  }
15981
16871
  function withRowUnit(event) {
15982
- const row = catalog.get(event.model);
15983
- return row ? { ...event, unit: row.usage.unit } : event;
16872
+ const row2 = catalog.get(event.model);
16873
+ return row2 ? { ...event, unit: row2.usage.unit } : event;
15984
16874
  }
15985
16875
  function textTarget(model, call) {
15986
16876
  if (!isCatalogId(model)) {
@@ -16394,38 +17284,14 @@ function createModelKit(config, adapters) {
16394
17284
  usageProvider: provider
16395
17285
  };
16396
17286
  },
16397
- async submitVideoTool(req, call = {}) {
16398
- const { webhookUrl, ...rest } = call;
16399
- const { adapter, ctx } = videoToolTarget(req.model, rest);
16400
- if (!adapter.submitVideoTool) throw noVideoTools(adapter, ctx.model);
16401
- const submittedAt = Date.now();
16402
- const submission = await adapter.submitVideoTool(
16403
- req,
16404
- ctx,
16405
- webhookUrl !== void 0 ? { webhookUrl } : {}
16406
- );
16407
- return { ...submission, submittedAt };
16408
- },
16409
- async videoToolStatus(sub, call = {}) {
16410
- const { adapter, ctx } = videoToolTarget(sub.model, call);
16411
- if (!adapter.videoToolStatus) throw noVideoTools(adapter, ctx.model);
16412
- return adapter.videoToolStatus(sub, ctx);
16413
- },
16414
- async videoToolResult(sub, call = {}) {
16415
- const { webhook, ...rest } = call;
16416
- const { adapter, ctx } = videoToolTarget(sub.model, rest);
16417
- if (!adapter.videoToolResult) throw noVideoTools(adapter, ctx.model);
16418
- const result = await adapter.videoToolResult(sub, ctx, webhook);
16419
- const base = { ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit };
16420
- const usage3 = sub.submittedAt === void 0 ? base : timed(base, sub.submittedAt);
16421
- await emit(usage3);
16422
- return { ...result, usage: usage3 };
16423
- },
16424
- async cancelVideoTool(sub, call = {}) {
16425
- const { adapter, ctx } = videoToolTarget(sub.model, call);
16426
- if (!adapter.cancelVideoTool) throw noVideoTools(adapter, ctx.model);
16427
- return adapter.cancelVideoTool(sub, ctx);
16428
- },
17287
+ submitVideoTool: videoToolJobs.submit,
17288
+ videoToolStatus: videoToolJobs.status,
17289
+ videoToolResult: videoToolJobs.result,
17290
+ cancelVideoTool: videoToolJobs.cancel,
17291
+ submitModel3d: model3dJobs.submit,
17292
+ model3dStatus: model3dJobs.status,
17293
+ model3dResult: model3dJobs.result,
17294
+ cancelModel3d: model3dJobs.cancel,
16429
17295
  usageProvider(modelId, call = {}) {
16430
17296
  const entry = catalog.require(modelId);
16431
17297
  if (entry.type !== "text") return entry.adapter;
@@ -16573,6 +17439,8 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
16573
17439
  InputSpecSchema,
16574
17440
  JsonObjectSchema,
16575
17441
  JsonValueSchema,
17442
+ MODEL3D_IMAGE_SLOTS,
17443
+ MODEL3D_MODELS,
16576
17444
  MODELS,
16577
17445
  ModelKitError,
16578
17446
  SURFACES,
@@ -16615,6 +17483,14 @@ var describe = (modelId) => createDefaultModelKit().describe(modelId);
16615
17483
  liveState,
16616
17484
  mergeTextProviderOptions,
16617
17485
  missingTierKeys,
17486
+ model3dCall,
17487
+ model3dConstraints,
17488
+ model3dInputRefusal,
17489
+ model3dPricingSku,
17490
+ model3dResolution,
17491
+ model3dSeedFits,
17492
+ model3dSkus,
17493
+ model3dTexture,
16618
17494
  nearestAspectRatio,
16619
17495
  normalizeExposure,
16620
17496
  openaiImageAdapter,