makefx 1.6.7 → 1.6.8

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/makefx.mjs +427 -35
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -61,4 +61,4 @@ IDs, or runs. Retired commands and aliases are not redirected.
61
61
 
62
62
  Run `makefx --help` or `makefx <noun> --help` for current options.
63
63
 
64
- Version: 1.6.7
64
+ Version: 1.6.8
package/makefx.mjs CHANGED
@@ -4442,7 +4442,7 @@ require_websocket_server();
4442
4442
  var wrapper_default = import_websocket.default;
4443
4443
  //#endregion
4444
4444
  //#region src/cli/version.ts
4445
- var CLI_VERSION = "1.6.7+0439271d1461";
4445
+ var CLI_VERSION = "1.6.8+06570e7d00c2";
4446
4446
  var CLI_VERSION_HEADER = "X-MakeFX-CLI-Version";
4447
4447
  function cliVersionHeaders() {
4448
4448
  return {
@@ -5200,6 +5200,10 @@ var WebSocketClient = class WebSocketClient {
5200
5200
  videoTier: params.videoTier,
5201
5201
  seedanceDuration: params.seedanceDuration,
5202
5202
  seedanceBitrateMode: params.seedanceBitrateMode,
5203
+ wan3Duration: params.wan3Duration,
5204
+ wan3Seed: params.wan3Seed,
5205
+ wan3PromptExpansion: params.wan3PromptExpansion,
5206
+ wan3Thinking: params.wan3Thinking,
5203
5207
  provider: params.provider,
5204
5208
  avatarResolution: params.avatarResolution,
5205
5209
  avatarMode: params.avatarMode,
@@ -6078,7 +6082,7 @@ var SEEDANCE_25_DURATIONS = [
6078
6082
  30
6079
6083
  ];
6080
6084
  var SEEDANCE_2_BITRATE_MODES = ["standard", "high"];
6081
- var MB = 1024 * 1024;
6085
+ var MB$1 = 1024 * 1024;
6082
6086
  var IMAGE_REFERENCE_RULE = {
6083
6087
  mediaKind: "image",
6084
6088
  minCount: 0,
@@ -6089,7 +6093,7 @@ var IMAGE_REFERENCE_RULE = {
6089
6093
  "image/png",
6090
6094
  "image/webp"
6091
6095
  ],
6092
- maxBytesPerFile: 30 * MB
6096
+ maxBytesPerFile: 30 * MB$1
6093
6097
  };
6094
6098
  var VIDEO_REFERENCE_RULE = {
6095
6099
  mediaKind: "video",
@@ -6097,8 +6101,8 @@ var VIDEO_REFERENCE_RULE = {
6097
6101
  maxCount: 3,
6098
6102
  promptLabel: "@VideoN",
6099
6103
  acceptedMimeTypes: ["video/mp4", "video/quicktime"],
6100
- maxBytesPerFile: 50 * MB,
6101
- combinedMaxBytes: 50 * MB,
6104
+ maxBytesPerFile: 50 * MB$1,
6105
+ combinedMaxBytes: 50 * MB$1,
6102
6106
  combinedDurationSeconds: {
6103
6107
  min: 2,
6104
6108
  max: 15
@@ -6118,7 +6122,7 @@ var AUDIO_REFERENCE_RULE = {
6118
6122
  "audio/wav",
6119
6123
  "audio/x-wav"
6120
6124
  ],
6121
- maxBytesPerFile: 15 * MB,
6125
+ maxBytesPerFile: 15 * MB$1,
6122
6126
  combinedDurationSeconds: { max: 15 }
6123
6127
  };
6124
6128
  function profile(mode, tier, endpointId) {
@@ -6187,7 +6191,7 @@ var SEEDANCE_25_IMAGE_REFERENCE_RULE = {
6187
6191
  "image/webp",
6188
6192
  "image/gif"
6189
6193
  ],
6190
- maxBytesPerFile: 30 * MB
6194
+ maxBytesPerFile: 30 * MB$1
6191
6195
  };
6192
6196
  var SEEDANCE_25_FRAME_IMAGE_REFERENCE_RULE = {
6193
6197
  ...SEEDANCE_25_IMAGE_REFERENCE_RULE,
@@ -6205,7 +6209,7 @@ var SEEDANCE_25_VIDEO_REFERENCE_RULE = {
6205
6209
  maxCount: 10,
6206
6210
  promptLabel: "@VideoN",
6207
6211
  acceptedMimeTypes: ["video/mp4", "video/quicktime"],
6208
- maxBytesPerFile: 50 * MB,
6212
+ maxBytesPerFile: 50 * MB$1,
6209
6213
  combinedDurationSeconds: { max: 30.2 },
6210
6214
  perFileDurationSeconds: {
6211
6215
  min: 1.8,
@@ -6230,7 +6234,7 @@ var SEEDANCE_25_AUDIO_REFERENCE_RULE = {
6230
6234
  "audio/wav",
6231
6235
  "audio/x-wav"
6232
6236
  ],
6233
- maxBytesPerFile: 15 * MB,
6237
+ maxBytesPerFile: 15 * MB$1,
6234
6238
  combinedDurationSeconds: { max: 30.2 },
6235
6239
  perFileDurationSeconds: {
6236
6240
  min: 1.8,
@@ -6371,6 +6375,158 @@ function getSeedance2CapabilityByEndpoint(endpointId) {
6371
6375
  return SEEDANCE_2_SELECTIONS.map((selection) => SEEDANCE_2_CAPABILITIES[selection]).find((capability) => capability.endpointId === endpointId);
6372
6376
  }
6373
6377
  //#endregion
6378
+ //#region src/shared/wan3Capabilities.ts
6379
+ var WAN_3_ASPECT_RATIOS = [
6380
+ "adaptive",
6381
+ "16:9",
6382
+ "4:3",
6383
+ "1:1",
6384
+ "3:4",
6385
+ "9:16"
6386
+ ];
6387
+ var WAN_3_RESOLUTIONS = [
6388
+ "480p",
6389
+ "720p",
6390
+ "1080p"
6391
+ ];
6392
+ var WAN_3_DURATIONS = [
6393
+ "auto",
6394
+ 2,
6395
+ 3,
6396
+ 4,
6397
+ 5,
6398
+ 6,
6399
+ 7,
6400
+ 8,
6401
+ 9,
6402
+ 10,
6403
+ 11,
6404
+ 12,
6405
+ 13,
6406
+ 14,
6407
+ 15,
6408
+ 16,
6409
+ 17,
6410
+ 18,
6411
+ 19,
6412
+ 20,
6413
+ 21,
6414
+ 22,
6415
+ 23,
6416
+ 24,
6417
+ 25,
6418
+ 26,
6419
+ 27,
6420
+ 28,
6421
+ 29,
6422
+ 30
6423
+ ];
6424
+ var MB = 1024 * 1024;
6425
+ var IMAGE_RULE = {
6426
+ mediaKind: "image",
6427
+ minCount: 0,
6428
+ maxCount: 10,
6429
+ promptLabel: "@ImageN",
6430
+ acceptedMimeTypes: [
6431
+ "image/jpeg",
6432
+ "image/png",
6433
+ "image/webp"
6434
+ ],
6435
+ maxBytesPerFile: 30 * MB
6436
+ };
6437
+ var FRAME_RULE = {
6438
+ ...IMAGE_RULE,
6439
+ minCount: 1,
6440
+ maxCount: 2
6441
+ };
6442
+ var VIDEO_RULE = {
6443
+ mediaKind: "video",
6444
+ minCount: 0,
6445
+ maxCount: 5,
6446
+ promptLabel: "@VideoN",
6447
+ acceptedMimeTypes: ["video/mp4", "video/quicktime"],
6448
+ maxBytesPerFile: 50 * MB,
6449
+ combinedDurationSeconds: { max: 15 }
6450
+ };
6451
+ var AUDIO_RULE = {
6452
+ mediaKind: "audio",
6453
+ minCount: 0,
6454
+ maxCount: 5,
6455
+ promptLabel: "@AudioN",
6456
+ acceptedMimeTypes: [
6457
+ "audio/mpeg",
6458
+ "audio/wav",
6459
+ "audio/x-wav"
6460
+ ],
6461
+ maxBytesPerFile: 15 * MB,
6462
+ combinedDurationSeconds: { max: 15 }
6463
+ };
6464
+ function capability(mode, endpointId) {
6465
+ const selection = `wan-3-${mode}`;
6466
+ const references = mode === "frame" ? [FRAME_RULE] : mode === "reference" ? [
6467
+ IMAGE_RULE,
6468
+ VIDEO_RULE,
6469
+ AUDIO_RULE
6470
+ ] : [];
6471
+ return {
6472
+ selection,
6473
+ generatorId: `video/${selection}`,
6474
+ endpointId,
6475
+ label: `WAN 3.0 ${mode === "text" ? "Text" : mode === "frame" ? "Frames" : "References"}`,
6476
+ mode,
6477
+ resolutions: WAN_3_RESOLUTIONS,
6478
+ aspectRatios: WAN_3_ASPECT_RATIOS,
6479
+ durations: WAN_3_DURATIONS,
6480
+ defaultResolution: "1080p",
6481
+ defaultAspectRatio: "adaptive",
6482
+ defaultDuration: 5,
6483
+ references,
6484
+ maxReferenceFiles: mode === "frame" ? 2 : mode === "reference" ? 20 : 0
6485
+ };
6486
+ }
6487
+ var WAN_3_CAPABILITIES = [
6488
+ capability("text", "alibaba/wan-3.0/text-to-video"),
6489
+ capability("frame", "alibaba/wan-3.0/image-to-video"),
6490
+ capability("reference", "alibaba/wan-3.0/reference-to-video")
6491
+ ];
6492
+ var WAN_3_SELECTIONS = WAN_3_CAPABILITIES.map((item) => item.selection);
6493
+ WAN_3_CAPABILITIES.map((item) => item.endpointId);
6494
+ function getWan3CapabilityBySelection(value) {
6495
+ return WAN_3_CAPABILITIES.find((item) => item.selection === value);
6496
+ }
6497
+ function getWan3CapabilityByEndpoint(value) {
6498
+ return WAN_3_CAPABILITIES.find((item) => item.endpointId === value);
6499
+ }
6500
+ function isWan3Duration(value) {
6501
+ return WAN_3_DURATIONS.includes(value);
6502
+ }
6503
+ function countWan3References(references) {
6504
+ return references.reduce((counts, reference) => {
6505
+ if (reference.mediaKind in counts) counts[reference.mediaKind] += 1;
6506
+ return counts;
6507
+ }, {
6508
+ image: 0,
6509
+ video: 0,
6510
+ audio: 0
6511
+ });
6512
+ }
6513
+ function getWan3ReferenceError(capability_, references) {
6514
+ const counts = countWan3References(references);
6515
+ const unsupported = references.find((reference) => !capability_.references.some((rule) => rule.mediaKind === reference.mediaKind));
6516
+ if (unsupported) return `${capability_.label} does not accept ${unsupported.mediaKind} references`;
6517
+ if (references.length > capability_.maxReferenceFiles) return `${capability_.label} accepts at most ${capability_.maxReferenceFiles} references`;
6518
+ if (capability_.mode === "reference" && references.length === 0) return "WAN 3.0 reference-to-video requires at least one image, video, or audio reference";
6519
+ for (const rule of capability_.references) {
6520
+ const count = counts[rule.mediaKind];
6521
+ if (count < rule.minCount || count > rule.maxCount) return `${capability_.label} requires ${rule.minCount}-${rule.maxCount} ${rule.mediaKind} references`;
6522
+ if (rule.combinedDurationSeconds) {
6523
+ if (references.filter((reference) => reference.mediaKind === rule.mediaKind).reduce((total, reference) => total + (reference.durationMs ?? 0), 0) / 1e3 > rule.combinedDurationSeconds.max) return `${capability_.label} accepts at most ${rule.combinedDurationSeconds.max}s of ${rule.mediaKind} references combined`;
6524
+ }
6525
+ }
6526
+ if (capability_.mode === "text" && references.length > 0) return "WAN 3.0 text-to-video does not accept references";
6527
+ return null;
6528
+ }
6529
+ //#endregion
6374
6530
  //#region src/shared/videoGenerationOptions.ts
6375
6531
  var VIDEO_GENERATION_ASPECT_RATIOS = ["16:9", "9:16"];
6376
6532
  var VIDEO_GENERATION_RESOLUTIONS = [
@@ -6408,13 +6564,17 @@ var VIDEO_MODEL_SELECTIONS = [
6408
6564
  "veo-3.1",
6409
6565
  "omni-flash",
6410
6566
  "kling",
6411
- "fal-seedance"
6567
+ "fal-seedance",
6568
+ ...WAN_3_SELECTIONS
6412
6569
  ];
6413
6570
  var VIDEO_MODEL_LABELS = {
6414
6571
  "veo-3.1": "Veo 3.1",
6415
6572
  "omni-flash": "Omni Flash",
6416
6573
  kling: "Kling 3.0",
6417
- "fal-seedance": "fal.ai Seedance v1 (text-to-video)"
6574
+ "fal-seedance": "fal.ai Seedance v1 (text-to-video)",
6575
+ "wan-3-text": "WAN 3.0 Text",
6576
+ "wan-3-frame": "WAN 3.0 Frames",
6577
+ "wan-3-reference": "WAN 3.0 References"
6418
6578
  };
6419
6579
  var VIDEO_MODEL_SUPPORTED_OPERATIONS = {
6420
6580
  "veo-3.1": [
@@ -6432,7 +6592,10 @@ var VIDEO_MODEL_SUPPORTED_OPERATIONS = {
6432
6592
  "refine",
6433
6593
  "derive"
6434
6594
  ],
6435
- "fal-seedance": ["generate"]
6595
+ "fal-seedance": ["generate"],
6596
+ "wan-3-text": ["generate"],
6597
+ "wan-3-frame": ["derive"],
6598
+ "wan-3-reference": ["derive", "refine"]
6436
6599
  };
6437
6600
  var KLING_VIDEO_MODEL = "kling-v3";
6438
6601
  var FAL_VIDEO_MODEL = "fal-ai/bytedance/seedance/v1/pro/text-to-video";
@@ -6490,6 +6653,8 @@ function getVideoGenerationModelForSelection(selection = DEFAULT_VIDEO_MODEL_SEL
6490
6653
  if (selection === "omni-flash") return GEMINI_OMNI_FLASH_VIDEO_MODEL;
6491
6654
  if (selection === "kling") return KLING_VIDEO_MODEL;
6492
6655
  if (selection === "fal-seedance") return FAL_VIDEO_MODEL;
6656
+ const wan3 = getWan3CapabilityBySelection(selection);
6657
+ if (wan3) return wan3.endpointId;
6493
6658
  return getVideoGenerationModelForTier(tier);
6494
6659
  }
6495
6660
  function resolveVideoGenerationModel(model, tier = DEFAULT_VIDEO_GENERATION_TIER) {
@@ -6505,6 +6670,8 @@ function isVideoGenerationResolutionSupportedForTier(resolution, tier = DEFAULT_
6505
6670
  return VIDEO_GENERATION_RESOLUTIONS_BY_TIER[tier].includes(resolution);
6506
6671
  }
6507
6672
  function getVideoGenerationResolutionsForModel(model) {
6673
+ const wan3 = getWan3CapabilityByEndpoint(model);
6674
+ if (wan3) return [...wan3.resolutions];
6508
6675
  if (isKlingVideoGenerationModel(model) || isFalSeedanceV1VideoGenerationModel(model)) return KLING_VIDEO_GENERATION_RESOLUTIONS;
6509
6676
  const seedanceCapability = getSeedance2CapabilityByEndpoint(model);
6510
6677
  if (seedanceCapability) return [...seedanceCapability.resolutions];
@@ -6521,6 +6688,8 @@ function getVideoModelSelectionForModel(model) {
6521
6688
  if (model === "gemini-omni-flash-preview") return "omni-flash";
6522
6689
  if (model === "kling-v3") return "kling";
6523
6690
  if (model === "fal-ai/bytedance/seedance/v1/pro/text-to-video") return "fal-seedance";
6691
+ const wan3 = getWan3CapabilityByEndpoint(model);
6692
+ if (wan3) return wan3.selection;
6524
6693
  return getVideoGenerationTierForModel(model) ? "veo-3.1" : void 0;
6525
6694
  }
6526
6695
  function isVeoVideoGenerationModel(model) {
@@ -6533,7 +6702,7 @@ function isKlingVideoGenerationModel(model) {
6533
6702
  return model === KLING_VIDEO_MODEL;
6534
6703
  }
6535
6704
  function isFalVideoGenerationModel(model) {
6536
- return isFalSeedanceV1VideoGenerationModel(model) || isFalSeedance2VideoGenerationModel(model);
6705
+ return isFalSeedanceV1VideoGenerationModel(model) || isFalSeedance2VideoGenerationModel(model) || isFalWan3VideoGenerationModel(model);
6537
6706
  }
6538
6707
  function isFalSeedanceV1VideoGenerationModel(model) {
6539
6708
  return model === FAL_VIDEO_MODEL;
@@ -6541,10 +6710,15 @@ function isFalSeedanceV1VideoGenerationModel(model) {
6541
6710
  function isFalSeedance2VideoGenerationModel(model) {
6542
6711
  return typeof model === "string" && getSeedance2CapabilityByEndpoint(model) !== void 0;
6543
6712
  }
6713
+ function isFalWan3VideoGenerationModel(model) {
6714
+ return getWan3CapabilityByEndpoint(model) !== void 0;
6715
+ }
6544
6716
  function isVideoGenerationModel(model) {
6545
6717
  return isVeoVideoGenerationModel(model) || isGeminiOmniVideoGenerationModel(model) || isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model);
6546
6718
  }
6547
6719
  function getVideoGenerationMaxReferenceImages(model) {
6720
+ const wan3 = getWan3CapabilityByEndpoint(model);
6721
+ if (wan3) return wan3.references.find((reference) => reference.mediaKind === "image")?.maxCount ?? 0;
6548
6722
  if (isFalSeedanceV1VideoGenerationModel(model)) return 0;
6549
6723
  if (isFalSeedance2VideoGenerationModel(model)) return getSeedance2CapabilityByEndpoint(model)?.references.find((reference) => reference.mediaKind === "image")?.maxCount ?? 0;
6550
6724
  if (isKlingVideoGenerationModel(model)) return 1;
@@ -6557,7 +6731,7 @@ function isVideoOperationSupportedByModel(model, operation) {
6557
6731
  return selection !== void 0 && VIDEO_MODEL_SUPPORTED_OPERATIONS[selection].includes(operation);
6558
6732
  }
6559
6733
  function doesVideoGenerationModelSupportAudioToggle(model) {
6560
- return isKlingVideoGenerationModel(model) || isVeoVideoGenerationModel(model) && VIDEO_GENERATION_AUDIO_TOGGLE_MODELS.includes(model);
6734
+ return isFalWan3VideoGenerationModel(model) || isKlingVideoGenerationModel(model) || isVeoVideoGenerationModel(model) && VIDEO_GENERATION_AUDIO_TOGGLE_MODELS.includes(model);
6561
6735
  }
6562
6736
  //#endregion
6563
6737
  //#region src/shared/generationRouting.ts
@@ -7075,6 +7249,9 @@ var CLI_GENERATION_MEDIA_OPTIONS = {
7075
7249
  "mode",
7076
7250
  "guidance-scale",
7077
7251
  "audio-guidance-scale",
7252
+ "seed",
7253
+ "prompt-expansion",
7254
+ "thinking",
7078
7255
  "provider"
7079
7256
  ]
7080
7257
  };
@@ -7131,23 +7308,28 @@ async function executeGenerate(parsed, ctx, client, deps, mediaKind, followOptio
7131
7308
  const musicProvider = parseMusicProviderOption(parsed, mediaKind, assetType);
7132
7309
  const effectiveVideoModel = videoOptions.model ?? getVideoGenerationModelForSelection();
7133
7310
  const seedanceCapability = mediaKind === "video" ? getSeedance2CapabilityByEndpoint(effectiveVideoModel) : void 0;
7311
+ const wan3Capability = mediaKind === "video" ? getWan3CapabilityByEndpoint(effectiveVideoModel) : void 0;
7134
7312
  const videoFrameRefs = parseVideoFrameReferenceOptions(parsed, "generate", mediaKind).refs;
7135
7313
  const seedanceRefs = parseSeedanceReferenceOptions(parsed);
7314
+ const seedanceReferenceCount = seedanceRefs.imageRefs.length + seedanceRefs.videoRefs.length + seedanceRefs.audioRefs.length;
7136
7315
  const plainRefs = parseOptionalRefs(parsed, "refs");
7137
7316
  validateSeedanceReferenceOptions(seedanceRefs, effectiveVideoModel, "generate");
7138
7317
  if (seedanceCapability?.mode === "frame" && videoFrameRefs.length === 0) throw new Error(`--model ${seedanceCapability.selection} requires --first-frame`);
7139
7318
  if (seedanceCapability?.mode === "text" && videoFrameRefs.length > 0) throw new Error(`--model ${seedanceCapability.selection} does not accept references`);
7140
7319
  if (seedanceCapability?.mode === "reference" && videoFrameRefs.length > 0) throw new Error(`--model ${seedanceCapability.selection} uses --image-refs, --video-refs, and --audio-refs`);
7141
7320
  if (seedanceCapability && plainRefs.length > 0) throw new Error(`--model ${seedanceCapability.selection} uses --image-refs, --video-refs, and --audio-refs instead of --refs`);
7321
+ if (wan3Capability?.mode === "frame" && videoFrameRefs.length === 0) throw new Error(`--model ${wan3Capability.selection} requires --first-frame`);
7322
+ if (wan3Capability?.mode === "text" && (videoFrameRefs.length > 0 || seedanceReferenceCount > 0)) throw new Error(`--model ${wan3Capability.selection} does not accept references`);
7323
+ if (wan3Capability?.mode === "reference" && videoFrameRefs.length > 0) throw new Error(`--model ${wan3Capability.selection} uses --image-refs, --video-refs, and --audio-refs`);
7324
+ if (wan3Capability && plainRefs.length > 0) throw new Error(`--model ${wan3Capability.selection} uses typed frame or grouped reference options instead of --refs`);
7142
7325
  if (mediaKind === "video" && isKlingVideoGenerationModel(effectiveVideoModel) && videoFrameRefs.length + plainRefs.length > 1) throw new Error("--model kling supports at most one image reference");
7143
- if (mediaKind === "video" && isFalVideoGenerationModel(effectiveVideoModel) && !isFalSeedance2VideoGenerationModel(effectiveVideoModel) && (videoFrameRefs.length > 0 || plainRefs.length > 0)) throw new Error(`--model ${getVideoModelSelectionForModel(effectiveVideoModel) ?? effectiveVideoModel} does not support image references`);
7144
- const seedanceReferenceCount = seedanceRefs.imageRefs.length + seedanceRefs.videoRefs.length + seedanceRefs.audioRefs.length;
7326
+ if (mediaKind === "video" && isFalVideoGenerationModel(effectiveVideoModel) && !isFalSeedance2VideoGenerationModel(effectiveVideoModel) && !isFalWan3VideoGenerationModel(effectiveVideoModel) && (videoFrameRefs.length > 0 || plainRefs.length > 0)) throw new Error(`--model ${getVideoModelSelectionForModel(effectiveVideoModel) ?? effectiveVideoModel} does not support image references`);
7145
7327
  const state = videoFrameRefs.length > 0 || seedanceReferenceCount > 0 || plainRefs.length > 0 ? await requestSpaceState(client) : void 0;
7146
7328
  const referenceDeps = {
7147
7329
  ...deps,
7148
7330
  waitForReferenceVariant: (variant) => waitForReferenceVariant(client, variant)
7149
7331
  };
7150
- const resolvedSeedanceRefs = state && seedanceReferenceCount > 0 ? isAvatarModelId(effectiveVideoModel) ? await resolveAvatarReferenceIds(seedanceRefs, ctx, referenceDeps, state) : await resolveSeedanceReferenceIds(seedanceRefs, seedanceCapability, ctx, referenceDeps, state) : {
7332
+ const resolvedSeedanceRefs = state && seedanceReferenceCount > 0 ? isAvatarModelId(effectiveVideoModel) ? await resolveAvatarReferenceIds(seedanceRefs, ctx, referenceDeps, state) : wan3Capability ? await resolveWan3ReferenceIds(seedanceRefs, ctx, referenceDeps, state) : await resolveSeedanceReferenceIds(seedanceRefs, seedanceCapability, ctx, referenceDeps, state) : {
7151
7333
  refs: [],
7152
7334
  ids: []
7153
7335
  };
@@ -7326,11 +7508,26 @@ function validateSeedanceReferenceOptions(options, model, command) {
7326
7508
  return;
7327
7509
  }
7328
7510
  const capability = getSeedance2CapabilityByEndpoint(model);
7511
+ const wan3Capability = getWan3CapabilityByEndpoint(model);
7329
7512
  const total = options.imageRefs.length + options.videoRefs.length + options.audioRefs.length;
7330
- if (!capability) {
7331
- if (total > 0) throw new Error("--image-refs, --video-refs, and --audio-refs require a Seedance 2 reference model");
7513
+ if (!capability && !wan3Capability) {
7514
+ if (total > 0) throw new Error("--image-refs, --video-refs, and --audio-refs require a Seedance 2 or WAN 3.0 reference model");
7515
+ return;
7516
+ }
7517
+ if (wan3Capability) {
7518
+ if (wan3Capability.mode !== "reference") {
7519
+ if (total > 0) throw new Error(`--model ${wan3Capability.selection} does not accept grouped references`);
7520
+ return;
7521
+ }
7522
+ const error = getWan3ReferenceError(wan3Capability, [
7523
+ ...options.imageRefs.map(() => ({ mediaKind: "image" })),
7524
+ ...options.videoRefs.map(() => ({ mediaKind: "video" })),
7525
+ ...options.audioRefs.map(() => ({ mediaKind: "audio" }))
7526
+ ]);
7527
+ if (error) throw new Error(error);
7332
7528
  return;
7333
7529
  }
7530
+ if (!capability) return;
7334
7531
  if (capability.mode !== "reference") {
7335
7532
  if (total > 0) throw new Error(`--model ${capability.selection} does not accept grouped references`);
7336
7533
  return;
@@ -7373,6 +7570,26 @@ async function resolveSeedanceReferenceIds(options, capability, ctx, deps, state
7373
7570
  ]
7374
7571
  };
7375
7572
  }
7573
+ async function resolveWan3ReferenceIds(options, ctx, deps, state) {
7574
+ const resolve = (refs, kind) => resolveReferenceVariantIds(refs, ctx, deps, state.variants, "video", state.assets, kind);
7575
+ const [imageIds, videoIds, audioIds] = await Promise.all([
7576
+ resolve(options.imageRefs, "image"),
7577
+ resolve(options.videoRefs, "video"),
7578
+ resolve(options.audioRefs, "audio")
7579
+ ]);
7580
+ return {
7581
+ refs: [
7582
+ ...options.imageRefs,
7583
+ ...options.videoRefs,
7584
+ ...options.audioRefs
7585
+ ],
7586
+ ids: [
7587
+ ...imageIds,
7588
+ ...videoIds,
7589
+ ...audioIds
7590
+ ]
7591
+ };
7592
+ }
7376
7593
  async function preflightLocalSeedanceReferences(options, deps, state, capability = SEEDANCE_2_CAPABILITIES["seedance-2-reference"]) {
7377
7594
  if (!deps.inspectLocalReference) return;
7378
7595
  const inspections = {
@@ -7718,9 +7935,12 @@ function parseVideoGenerationOptions(parsed, mediaKind) {
7718
7935
  const modeValue = readOptionalOption(parsed, "mode");
7719
7936
  const guidanceScaleValue = readOptionalOption(parsed, "guidance-scale");
7720
7937
  const audioGuidanceScaleValue = readOptionalOption(parsed, "audio-guidance-scale");
7938
+ const seedValue = mediaKind === "video" ? readOptionalOption(parsed, "seed") : void 0;
7939
+ const promptExpansionValue = mediaKind === "video" ? parsed.options["prompt-expansion"] : void 0;
7940
+ const thinkingValue = mediaKind === "video" ? parsed.options.thinking : void 0;
7721
7941
  const modelValue = mediaKind === "video" ? readOptionalOption(parsed, "model") : void 0;
7722
7942
  const aspectValue = mediaKind === "video" ? readOptionalOption(parsed, "aspect") : void 0;
7723
- if (mediaKind !== "video" && resolutionValue === void 0 && durationValue === void 0 && tierValue === void 0 && aspectValue === void 0 && bitrateValue === void 0 && modeValue === void 0 && guidanceScaleValue === void 0 && audioGuidanceScaleValue === void 0) return {};
7943
+ if (mediaKind !== "video" && resolutionValue === void 0 && durationValue === void 0 && tierValue === void 0 && aspectValue === void 0 && bitrateValue === void 0 && modeValue === void 0 && guidanceScaleValue === void 0 && audioGuidanceScaleValue === void 0 && seedValue === void 0 && promptExpansionValue === void 0 && thinkingValue === void 0) return {};
7724
7944
  if (mediaKind !== "video") throw new Error("Video model controls are only supported for video generation");
7725
7945
  const videoResolution = resolutionValue === void 0 ? void 0 : normalizeVideoGenerationResolution(resolutionValue);
7726
7946
  if (resolutionValue !== void 0 && !videoResolution) throw new Error("--resolution must be 480p, 720p, 1080p, or 4k");
@@ -7729,7 +7949,7 @@ function parseVideoGenerationOptions(parsed, mediaKind) {
7729
7949
  const model = parseVideoModelOption(modelValue, videoTier, parsed);
7730
7950
  if (isAvatarModelId(model)) {
7731
7951
  if (parsed.options.refs !== void 0 || parsed.options["first-frame"] !== void 0 || parsed.options["last-frame"] !== void 0) throw new Error("Avatar models accept only --image-refs and --audio-refs");
7732
- if (aspectValue !== void 0 || durationValue !== void 0 || tierValue !== void 0 || bitrateValue !== void 0 || parsed.options.audio !== void 0 || parsed.options["no-audio"] !== void 0) throw new Error("Avatar models do not accept --aspect, --duration, --tier, --bitrate, --audio, or --no-audio");
7952
+ if (aspectValue !== void 0 || durationValue !== void 0 || tierValue !== void 0 || bitrateValue !== void 0 || parsed.options.audio !== void 0 || parsed.options["no-audio"] !== void 0 || seedValue !== void 0 || promptExpansionValue !== void 0 || thinkingValue !== void 0) throw new Error("Avatar models do not accept --aspect, --duration, --tier, --bitrate, --audio, or --no-audio");
7733
7953
  if (model === "kling-avatar-v2") {
7734
7954
  if (parsed.options.provider !== void 0) throw new Error("Kling Avatar V2 does not accept --provider");
7735
7955
  if (resolutionValue !== void 0 || guidanceScaleValue !== void 0 || audioGuidanceScaleValue !== void 0) throw new Error("Aurora controls are not supported by --model kling-avatar-v2");
@@ -7759,26 +7979,39 @@ function parseVideoGenerationOptions(parsed, mediaKind) {
7759
7979
  if (modeValue !== void 0) throw new Error("--mode is only supported by --model kling-avatar-v2");
7760
7980
  if (guidanceScaleValue !== void 0 || audioGuidanceScaleValue !== void 0) throw new Error("--guidance-scale and --audio-guidance-scale require --model creatify-aurora");
7761
7981
  const seedanceCapability = getSeedance2CapabilityByEndpoint(model);
7982
+ const wan3Capability = getWan3CapabilityByEndpoint(model);
7762
7983
  const seedanceDuration = durationValue === void 0 ? void 0 : seedanceCapability ? normalizeSeedanceDuration(durationValue, model) : void 0;
7984
+ const wan3Duration = durationValue === void 0 ? void 0 : wan3Capability ? durationValue === "auto" ? "auto" : Number(durationValue) : void 0;
7763
7985
  const videoDurationSeconds = durationValue === void 0 || durationValue === "auto" ? void 0 : normalizeVideoGenerationDurationSeconds(durationValue);
7764
7986
  if (seedanceCapability && durationValue !== void 0 && seedanceDuration === void 0) {
7765
7987
  const numericDurations = seedanceCapability.durations.filter((value) => typeof value === "number");
7766
7988
  throw new Error(`--duration must be auto or an integer from ${numericDurations[0]} to ${numericDurations.at(-1)}`);
7767
7989
  }
7768
- if (!seedanceCapability && durationValue === "auto") throw new Error("--duration auto is only supported by Seedance 2");
7990
+ if (wan3Capability && durationValue !== void 0 && !isWan3Duration(wan3Duration)) throw new Error("--duration must be auto or an integer from 2 to 30 for WAN 3.0");
7991
+ if (!seedanceCapability && !wan3Capability && durationValue === "auto") throw new Error("--duration auto is only supported by Seedance 2 and WAN 3.0");
7769
7992
  if (isGeminiOmniVideoGenerationModel(model) && (resolutionValue !== void 0 || durationValue !== void 0 || tierValue !== void 0)) throw new Error("--resolution, --duration, and --tier are only supported with --model veo-3.1");
7770
7993
  if ((isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model)) && tierValue !== void 0) throw new Error("--tier is only supported with --model veo-3.1");
7771
7994
  if (videoResolution && videoTier && !isVideoGenerationResolutionSupportedForTier(videoResolution, videoTier)) throw new Error("--resolution 4k is not supported with --tier lite");
7772
7995
  if (videoResolution && (isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model)) && !isVideoGenerationResolutionSupportedForModel(model, videoResolution)) throw new Error(`--model ${getVideoModelSelectionForModel(model) ?? model} does not support --resolution ${videoResolution}`);
7773
- if (!seedanceCapability && videoDurationSeconds && ![
7996
+ if (!seedanceCapability && !wan3Capability && videoDurationSeconds && ![
7774
7997
  4,
7775
7998
  6,
7776
7999
  8
7777
8000
  ].includes(videoDurationSeconds)) throw new Error("--duration must be 4, 6, or 8 for this model");
7778
- const aspectRatio = aspectValue === void 0 ? void 0 : seedanceCapability ? seedanceCapability.aspectRatios.includes(aspectValue) ? aspectValue : void 0 : normalizeVideoGenerationAspectRatio(aspectValue);
7779
- if (aspectValue !== void 0 && !aspectRatio) throw new Error(seedanceCapability ? `--aspect must be one of: ${seedanceCapability.aspectRatios.join(", ")}` : "--aspect must be 16:9 or 9:16");
8001
+ const aspectRatio = aspectValue === void 0 ? void 0 : seedanceCapability ? seedanceCapability.aspectRatios.includes(aspectValue) ? aspectValue : void 0 : wan3Capability ? wan3Capability.aspectRatios.includes(aspectValue) ? aspectValue : void 0 : normalizeVideoGenerationAspectRatio(aspectValue);
8002
+ if (aspectValue !== void 0 && !aspectRatio) throw new Error(seedanceCapability ? `--aspect must be one of: ${seedanceCapability.aspectRatios.join(", ")}` : wan3Capability ? `--aspect must be one of: ${wan3Capability.aspectRatios.join(", ")}` : "--aspect must be 16:9 or 9:16");
7780
8003
  const seedanceBitrateMode = bitrateValue;
7781
8004
  if (bitrateValue !== void 0 && (!seedanceCapability || !seedanceCapability.bitrateModes.includes(seedanceBitrateMode))) throw new Error(seedanceCapability ? `${seedanceCapability.familyLabel} does not accept --bitrate` : "--bitrate standard|high is only supported by Seedance 2");
8005
+ const wan3Seed = seedValue === void 0 ? void 0 : Number(seedValue);
8006
+ if (seedValue !== void 0 && (!wan3Capability || !Number.isSafeInteger(wan3Seed) || wan3Seed < 0 || wan3Seed > 2147483647)) throw new Error(wan3Capability ? "--seed must be an integer from 0 to 2147483647" : "--seed is only supported by WAN 3.0 for video generation");
8007
+ const parseWanBoolean = (value, option) => {
8008
+ if (value === void 0) return void 0;
8009
+ if (!wan3Capability) throw new Error(`${option} is only supported by WAN 3.0`);
8010
+ if (value !== "true" && value !== "false") throw new Error(`${option} must be true or false`);
8011
+ return value === "true";
8012
+ };
8013
+ const wan3PromptExpansion = parseWanBoolean(promptExpansionValue, "--prompt-expansion");
8014
+ const wan3Thinking = parseWanBoolean(thinkingValue, "--thinking");
7782
8015
  return {
7783
8016
  model,
7784
8017
  ...aspectRatio ? { aspectRatio } : {},
@@ -7786,7 +8019,11 @@ function parseVideoGenerationOptions(parsed, mediaKind) {
7786
8019
  ...videoDurationSeconds ? { videoDurationSeconds } : {},
7787
8020
  ...videoTier ? { videoTier } : {},
7788
8021
  ...seedanceCapability && seedanceDuration !== void 0 ? { seedanceDuration } : {},
7789
- ...seedanceBitrateMode ? { seedanceBitrateMode } : {}
8022
+ ...seedanceBitrateMode ? { seedanceBitrateMode } : {},
8023
+ ...wan3Capability && wan3Duration !== void 0 ? { wan3Duration } : {},
8024
+ ...wan3Seed !== void 0 ? { wan3Seed } : {},
8025
+ ...wan3PromptExpansion !== void 0 ? { wan3PromptExpansion } : {},
8026
+ ...wan3Thinking !== void 0 ? { wan3Thinking } : {}
7790
8027
  };
7791
8028
  }
7792
8029
  function parseGenerationProviderOption(parsed, mediaKind, videoModel) {
@@ -7810,12 +8047,13 @@ function validateVideoFrameReferenceOptions(command, parsed, mediaKind) {
7810
8047
  if (mediaKind !== "video") throw new Error("--first-frame and --last-frame are only supported for video generation");
7811
8048
  if (lastFrame && !firstFrame) throw new Error("--last-frame requires --first-frame");
7812
8049
  if (parsed.options.refs) throw new Error("--first-frame and --last-frame cannot be combined with --refs");
7813
- if (parsed.options["image-refs"] || parsed.options["video-refs"] || parsed.options["audio-refs"]) throw new Error("Seedance 2 cannot combine authoritative --first-frame/--last-frame inputs with extended --image-refs/--video-refs/--audio-refs; choose frame mode or reference mode");
8050
+ if (parsed.options["image-refs"] || parsed.options["video-refs"] || parsed.options["audio-refs"]) throw new Error("Frame mode cannot combine --first-frame/--last-frame with grouped --image-refs/--video-refs/--audio-refs");
7814
8051
  const tierValue = readOptionalOption(parsed, "tier");
7815
8052
  const videoTier = tierValue === void 0 ? void 0 : normalizeVideoGenerationTier(tierValue);
7816
8053
  const model = parseVideoModelOption(readOptionalOption(parsed, "model"), videoTier, parsed);
8054
+ const wan3Capability = getWan3CapabilityByEndpoint(model);
7817
8055
  if (isFalSeedance2VideoGenerationModel(model) && !firstFrame) throw new Error("Seedance frame mode requires --first-frame");
7818
- if (!isFalSeedance2VideoGenerationModel(model) && (isFalVideoGenerationModel(model) || isGeminiOmniVideoGenerationModel(model) || isKlingVideoGenerationModel(model) && Boolean(lastFrame))) throw new Error("--first-frame and --last-frame require a frame-capable video model");
8056
+ if (!(isFalSeedance2VideoGenerationModel(model) || wan3Capability?.mode === "frame") && (isFalVideoGenerationModel(model) || isGeminiOmniVideoGenerationModel(model) || isKlingVideoGenerationModel(model) && Boolean(lastFrame))) throw new Error("--first-frame and --last-frame require a frame-capable video model");
7819
8057
  }
7820
8058
  function readVideoFrameOption(parsed, name) {
7821
8059
  const value = parsed.options[name];
@@ -7882,9 +8120,14 @@ function parseVideoModelOption(value, tier, parsed) {
7882
8120
  const hasReferences = Boolean(parsed?.options.refs || parsed?.options["image-refs"] || parsed?.options["video-refs"] || parsed?.options["audio-refs"]);
7883
8121
  return SEEDANCE_2_CAPABILITIES[`${normalized}-${hasFrames ? "frame" : hasReferences ? "reference" : "text"}`].endpointId;
7884
8122
  }
8123
+ if (normalized === "wan-3") {
8124
+ const hasFrames = Boolean(parsed?.options["first-frame"] || parsed?.options["last-frame"]);
8125
+ const hasReferences = Boolean(parsed?.options["image-refs"] || parsed?.options["video-refs"] || parsed?.options["audio-refs"]);
8126
+ return getWan3CapabilityBySelection(`wan-3-${hasFrames ? "frame" : hasReferences ? "reference" : "text"}`).endpointId;
8127
+ }
7885
8128
  const selection = normalizeVideoModelSelection(normalized === "seedance-1" ? "fal-seedance" : normalized);
7886
8129
  if (selection) return getVideoGenerationModelForSelection(selection, effectiveTier);
7887
- throw new Error("--model must be veo-3.1, omni-flash, kling, seedance-1, seedance-2, seedance-2-fast, seedance-2.5, kling-avatar-v2, or creatify-aurora");
8130
+ throw new Error("--model must be veo-3.1, omni-flash, kling, seedance-1, seedance-2, seedance-2-fast, seedance-2.5, wan-3, kling-avatar-v2, or creatify-aurora");
7888
8131
  }
7889
8132
  function parseImageModelOption(value) {
7890
8133
  if (!value) return void 0;
@@ -8066,6 +8309,8 @@ function parseWaitSeconds$1(value) {
8066
8309
  function buildRegenerationBody(mediaKind, parsed, referenceVariantIds, audioMode, sourceRecipe) {
8067
8310
  const prompt = parsed.positionals[1] ?? parsed.options.prompt;
8068
8311
  const model = parsed.options.model;
8312
+ const storedRecipe = parseStoredRecipe$2(sourceRecipe);
8313
+ const isWan3 = mediaKind === "video" && (model !== void 0 ? model === "wan-3" : Boolean(getWan3CapabilityByEndpoint(storedRecipe?.model)));
8069
8314
  const audioModel = mediaKind === "audio" && (audioMode === "speech" || audioMode === "dialogue") ? normalizeElevenLabsSpeechModelId(model) : void 0;
8070
8315
  const params = {};
8071
8316
  let duration;
@@ -8085,11 +8330,23 @@ function buildRegenerationBody(mediaKind, parsed, referenceVariantIds, audioMode
8085
8330
  } else if (mediaKind === "video") {
8086
8331
  if (parsed.options.aspect) params.aspectRatio = parsed.options.aspect;
8087
8332
  if (parsed.options.resolution) params.videoResolution = parsed.options.resolution;
8088
- if (parsed.options.duration) duration = parseInteger(parsed.options.duration, "--duration");
8333
+ if (parsed.options.duration) if (isWan3) {
8334
+ const wan3Duration = parsed.options.duration === "auto" ? "auto" : parseInteger(parsed.options.duration, "--duration");
8335
+ if (!isWan3Duration(wan3Duration)) throw new Error("--duration must be auto or an integer from 2 to 30 for WAN 3.0");
8336
+ params.wan3Duration = wan3Duration;
8337
+ } else duration = parseInteger(parsed.options.duration, "--duration");
8089
8338
  if (parsed.options.tier) params.videoTier = parsed.options.tier;
8090
8339
  if (parsed.options.bitrate) params.seedanceBitrateMode = parsed.options.bitrate;
8091
8340
  if (parsed.options.audio === "true") params.generateAudio = true;
8092
8341
  if (parsed.options["no-audio"] === "true") params.generateAudio = false;
8342
+ if ((parsed.options.seed !== void 0 || parsed.options["prompt-expansion"] !== void 0 || parsed.options.thinking !== void 0) && !isWan3) throw new Error("--seed, --prompt-expansion, and --thinking require --model wan-3 or a stored WAN 3.0 recipe");
8343
+ if (parsed.options.seed !== void 0) {
8344
+ const seed = parseInteger(parsed.options.seed, "--seed");
8345
+ if (seed < 0 || seed > 2147483647) throw new Error("--seed must be an integer from 0 to 2147483647 for WAN 3.0");
8346
+ params.wan3Seed = seed;
8347
+ }
8348
+ if (parsed.options["prompt-expansion"] !== void 0) params.wan3PromptExpansion = parseBooleanOption(parsed.options["prompt-expansion"], "--prompt-expansion");
8349
+ if (parsed.options.thinking !== void 0) params.wan3Thinking = parseBooleanOption(parsed.options.thinking, "--thinking");
8093
8350
  } else {
8094
8351
  if (!audioMode) throw new Error("Audio regeneration mode is required");
8095
8352
  validateAudioModel(audioMode, audioModel ?? model);
@@ -8112,6 +8369,7 @@ function buildRegenerationBody(mediaKind, parsed, referenceVariantIds, audioMode
8112
8369
  }
8113
8370
  function resolveVideoRegenerationModel(model, parsed, sourceRecipe) {
8114
8371
  const tier = parsed.options.tier ?? "generate";
8372
+ if (model === "wan-3") return getWan3CapabilityBySelection("wan-3-reference").endpointId;
8115
8373
  if (model === "seedance-2" || model === "seedance-2-fast" || model === "seedance-2.5") {
8116
8374
  const referencesWereOverridden = [
8117
8375
  "image-refs",
@@ -8131,7 +8389,7 @@ function resolveVideoRegenerationModel(model, parsed, sourceRecipe) {
8131
8389
  }, referencesWereOverridden).endpointId;
8132
8390
  }
8133
8391
  const selection = normalizeVideoModelSelection(model === "seedance-1" ? "fal-seedance" : model);
8134
- if (!selection) throw new Error("Unsupported video model. Expected veo-3.1, omni-flash, kling, seedance-1, seedance-2, seedance-2-fast, or seedance-2.5");
8392
+ if (!selection) throw new Error("Unsupported video model. Expected veo-3.1, omni-flash, kling, seedance-1, seedance-2, seedance-2-fast, seedance-2.5, or wan-3");
8135
8393
  return getVideoGenerationModelForSelection(selection, tier);
8136
8394
  }
8137
8395
  function parseStoredRecipe$2(recipe) {
@@ -8175,6 +8433,11 @@ function parseInteger(value, option) {
8175
8433
  if (!Number.isInteger(parsed)) throw new Error(`${option} must be an integer`);
8176
8434
  return parsed;
8177
8435
  }
8436
+ function parseBooleanOption(value, option) {
8437
+ if (value === "true") return true;
8438
+ if (value === "false") return false;
8439
+ throw new Error(`${option} must be true or false`);
8440
+ }
8178
8441
  //#endregion
8179
8442
  //#region src/cli/commands/audio.ts
8180
8443
  var defaultDeps$10 = {
@@ -9359,6 +9622,124 @@ function seedanceVideoGenerator(capability) {
9359
9622
  ]
9360
9623
  };
9361
9624
  }
9625
+ function wan3VideoGenerator(capability) {
9626
+ const fixedGenerator = fixedInput("generator_id", capability.generatorId, "Selects this exact WAN 3.0 mode.");
9627
+ const parameters = [
9628
+ input("aspect_ratio", "string", false, "Output aspect ratio; adaptive lets WAN choose.", {
9629
+ allowedValues: capability.aspectRatios,
9630
+ defaultValue: capability.defaultAspectRatio
9631
+ }),
9632
+ input("resolution", "string", false, "Output resolution.", {
9633
+ allowedValues: capability.resolutions,
9634
+ defaultValue: capability.defaultResolution
9635
+ }),
9636
+ input("duration", "string_or_integer", false, "Output duration from 2 to 30 seconds, or auto.", {
9637
+ allowedValues: capability.durations,
9638
+ defaultValue: capability.defaultDuration
9639
+ }),
9640
+ input("generate_audio", "boolean", false, "Generate synchronized native audio.", {
9641
+ allowedValues: [true, false],
9642
+ defaultValue: true
9643
+ }),
9644
+ input("seed", "integer", false, "Optional deterministic provider seed.", {
9645
+ minimum: 0,
9646
+ maximum: 2147483647
9647
+ }),
9648
+ input("prompt_expansion", "boolean", false, "Allow WAN to expand the prompt for quality.", {
9649
+ allowedValues: [true, false],
9650
+ defaultValue: true
9651
+ }),
9652
+ input("thinking", "boolean", false, "Enable enhanced composition and motion reasoning.", {
9653
+ allowedValues: [true, false],
9654
+ defaultValue: false
9655
+ })
9656
+ ];
9657
+ const common = [
9658
+ SPACE_INPUT,
9659
+ fixedGenerator,
9660
+ NAME_INPUT,
9661
+ input("asset_type", "string", true, "Asset classification stored in the Space."),
9662
+ PROMPT_INPUT,
9663
+ ...parameters
9664
+ ];
9665
+ const max = (kind) => capability.references.find((rule) => rule.mediaKind === kind)?.maxCount ?? 0;
9666
+ const referenceInputs = [
9667
+ input("image_reference_variant_refs", "string_array", false, `Ordered completed images addressed as Image 1 through Image ${max("image")}.`, {
9668
+ minItems: 1,
9669
+ maxItems: max("image")
9670
+ }),
9671
+ input("video_reference_variant_refs", "string_array", false, `Ordered completed videos addressed as Video 1 through Video ${max("video")}; 15 seconds combined maximum.`, {
9672
+ minItems: 1,
9673
+ maxItems: max("video")
9674
+ }),
9675
+ input("audio_reference_variant_refs", "string_array", false, `Ordered completed audio clips addressed as Audio 1 through Audio ${max("audio")}; 15 seconds combined maximum.`, {
9676
+ minItems: 1,
9677
+ maxItems: max("audio")
9678
+ })
9679
+ ];
9680
+ const modeInputs = capability.mode === "frame" ? [input("start_frame_variant_ref", "string", true, "Required authoritative first frame."), input("end_frame_variant_ref", "string", false, "Optional authoritative final frame.")] : capability.mode === "reference" ? referenceInputs : [];
9681
+ const operations = [{
9682
+ operation: capability.mode === "text" ? "generate" : "derive",
9683
+ tool: "generate_video",
9684
+ description: capability.mode === "text" ? "Create a native-audio video from text." : capability.mode === "frame" ? "Animate a start frame and optional end frame." : "Direct one video from up to 20 ordered image, video, and audio references.",
9685
+ inputs: [...common, ...modeInputs]
9686
+ }];
9687
+ if (capability.mode === "reference") operations.push({
9688
+ operation: "refine",
9689
+ tool: "edit_video",
9690
+ description: "Refine a completed video as Video 1 with up to 19 additional references.",
9691
+ referenceLimits: {
9692
+ maxAdditionalCount: 19,
9693
+ implicitSourceCount: 1,
9694
+ maxAdditionalByKind: {
9695
+ image: 10,
9696
+ video: 4,
9697
+ audio: 5
9698
+ }
9699
+ },
9700
+ inputs: [
9701
+ SPACE_INPUT,
9702
+ fixedGenerator,
9703
+ input("asset_ref", "string", true, "Target video asset reference."),
9704
+ input("source_variant_ref", "string", true, "Completed target video used as Video 1."),
9705
+ PROMPT_INPUT,
9706
+ ...parameters,
9707
+ ...referenceInputs.map((item) => item.name === "video_reference_variant_refs" ? {
9708
+ ...item,
9709
+ maxItems: 4,
9710
+ description: "Up to 4 additional videos; the source video is Video 1."
9711
+ } : item)
9712
+ ]
9713
+ });
9714
+ return {
9715
+ id: capability.generatorId,
9716
+ label: capability.label,
9717
+ mediaKind: "video",
9718
+ modelIds: [capability.endpointId],
9719
+ defaultModelId: capability.endpointId,
9720
+ operations,
9721
+ referenceRules: {
9722
+ mediaKind: capability.mode === "frame" ? "image" : null,
9723
+ completedOnly: capability.mode !== "text",
9724
+ maxCount: capability.maxReferenceFiles,
9725
+ maxTotalCount: capability.maxReferenceFiles,
9726
+ modalities: capability.references.map((rule) => ({
9727
+ mediaKind: rule.mediaKind,
9728
+ minCount: rule.minCount,
9729
+ maxCount: rule.maxCount,
9730
+ promptLabel: rule.promptLabel,
9731
+ acceptedMimeTypes: rule.acceptedMimeTypes,
9732
+ maxBytesPerFile: rule.maxBytesPerFile,
9733
+ ...rule.combinedDurationSeconds ? { combinedDurationSeconds: rule.combinedDurationSeconds } : {}
9734
+ }))
9735
+ },
9736
+ notes: [
9737
+ "WAN 3.0 generates native synchronized audio and supports 480p, 720p, and 1080p.",
9738
+ "Safety checking remains enabled by MakeFX and is not a user-controlled option.",
9739
+ capability.mode === "reference" ? "Reference mode accepts up to 10 images, 5 videos, and 5 audio clips (20 total)." : capability.mode === "frame" ? "Frame mode accepts exactly one start frame and one optional end frame." : "Text mode rejects all media references."
9740
+ ]
9741
+ };
9742
+ }
9362
9743
  function avatarVideoGenerator(model) {
9363
9744
  const capability = getAvatarModelCapabilities(model);
9364
9745
  const parameters = capability.model === "kling-avatar-v2" ? [input("mode", "string", false, "Generation quality.", {
@@ -9479,8 +9860,9 @@ function getGeneratorCatalog(overrides = {}) {
9479
9860
  const lyria = overrides.lyria ?? "lyria-3-clip-preview";
9480
9861
  return [
9481
9862
  ...Object.values(IMAGE_MODEL_CAPABILITIES).map(imageGenerator),
9482
- ...VIDEO_MODEL_SELECTIONS.map(videoGenerator),
9863
+ ...VIDEO_MODEL_SELECTIONS.filter((selection) => !getWan3CapabilityBySelection(selection)).map(videoGenerator),
9483
9864
  ...SEEDANCE_2_SELECTIONS.map((selection) => seedanceVideoGenerator(SEEDANCE_2_CAPABILITIES[selection])),
9865
+ ...WAN_3_CAPABILITIES.map(wan3VideoGenerator),
9484
9866
  ...AVATAR_MODEL_IDS.map(avatarVideoGenerator),
9485
9867
  audioGenerator({
9486
9868
  id: "audio/elevenlabs-speech",
@@ -9562,9 +9944,15 @@ var DRAFT_RECIPE_INPUT_KEYS = {
9562
9944
  video_tier: "videoTier",
9563
9945
  duration: "seedanceDuration",
9564
9946
  bitrate_mode: "seedanceBitrateMode",
9947
+ prompt_expansion: "wan3PromptExpansion",
9948
+ thinking: "wan3Thinking",
9565
9949
  provider: "provider"
9566
9950
  };
9567
9951
  function draftRecipeInputKey(inputName, generatorId) {
9952
+ if (generatorId.startsWith("video/wan-3-")) {
9953
+ if (inputName === "duration") return "wan3Duration";
9954
+ if (inputName === "seed") return "wan3Seed";
9955
+ }
9568
9956
  if ((generatorId === "video/p-video-avatar" || generatorId === "video/creatify-aurora") && inputName === "resolution") return "avatarResolution";
9569
9957
  if (generatorId === "video/kling-avatar-v2" && inputName === "mode") return "avatarMode";
9570
9958
  if (generatorId === "video/creatify-aurora" && inputName === "guidance_scale") return "avatarGuidanceScale";
@@ -11998,17 +12386,21 @@ var HELP = {
11998
12386
  makefx image generate "prompt" --name <name> --type <type> -o <file> [--model pro|flash|flux|gpt-image-2|seedream-5-pro|seedream-5-lite] [--provider <provider>] [--refs <variant-ref-or-file,...>] [--aspect <ratio>] [--size 1K|2K|3K|4K] [--quality low|medium|high] [--seed <integer>] [--collection <id>] [--space <id>]
11999
12387
  makefx image regenerate <variant-ref> ["prompt"] [--model pro|flash|flux|gpt-image-2|seedream-5-pro|seedream-5-lite] [--provider <provider>] [--aspect <ratio>] [--size <size>] [--quality low|medium|high] [--seed <integer|random>] [--refs <refs>] [--no-activate] [--wait]`,
12000
12388
  video: `Usage:
12001
- makefx video generate "prompt" --name <name> --type <type> -o <file> [--model veo-3.1|omni-flash|kling|seedance-1|seedance-2|seedance-2-fast|seedance-2.5|kling-avatar-v2|creatify-aurora] [--provider fal|elevenlabs|pika]
12389
+ makefx video generate "prompt" --name <name> --type <type> -o <file> [--model veo-3.1|omni-flash|kling|seedance-1|seedance-2|seedance-2-fast|seedance-2.5|wan-3|kling-avatar-v2|creatify-aurora] [--provider fal|elevenlabs|pika]
12002
12390
  [--refs <variant-ref-or-file,...>] [--first-frame <ref>] [--last-frame <ref>] [--image-refs <refs>] [--video-refs <refs>] [--audio-refs <refs>]
12003
12391
  [--aspect <ratio>] [--resolution 480p|720p|1080p|4k] [--duration <seconds|auto>] [--tier generate|fast|lite] [--bitrate standard|high]
12004
12392
  [--audio | --no-audio] [--collection <id>] [--space <id>]
12393
+ makefx video generate "prompt" --model wan-3 --name <name> --type <type> -o <file>
12394
+ [--first-frame <ref> [--last-frame <ref>] | --image-refs <refs> --video-refs <refs> --audio-refs <refs>]
12395
+ [--aspect adaptive|16:9|4:3|1:1|3:4|9:16] [--resolution 480p|720p|1080p] [--duration 2..30|auto]
12396
+ [--audio | --no-audio] [--seed 0..2147483647] [--prompt-expansion true|false] [--thinking true|false]
12005
12397
  makefx video generate ["prompt"] --model kling-avatar-v2 --image-refs <portrait-ref> --audio-refs <audio-ref>
12006
12398
  --name <name> --type <type> -o <file> [--mode standard|pro] [--collection <id>] [--space <id>]
12007
12399
  makefx video generate ["prompt"] --model creatify-aurora --image-refs <portrait-ref> --audio-refs <audio-ref>
12008
12400
  --name <name> --type <type> -o <file> [--resolution 480p|720p] [--guidance-scale 0..5] [--audio-guidance-scale 0..5] [--collection <id>] [--space <id>]
12009
- makefx video regenerate <variant-ref> ["prompt"] [--model <model>] [--provider fal|elevenlabs|pika] [--aspect <ratio>] [--resolution <value>] [--duration <seconds>] [--tier <tier>] [--bitrate standard|high] [--audio | --no-audio] [--image-refs <refs>] [--video-refs <refs>] [--audio-refs <refs>] [--no-activate] [--wait]
12401
+ makefx video regenerate <variant-ref> ["prompt"] [--model <model>] [--provider fal|elevenlabs|pika] [--aspect <ratio>] [--resolution <value>] [--duration <seconds|auto>] [--tier <tier>] [--bitrate standard|high] [--audio | --no-audio] [--seed 0..2147483647] [--prompt-expansion true|false] [--thinking true|false] [--image-refs <refs>] [--video-refs <refs>] [--audio-refs <refs>] [--no-activate] [--wait]
12010
12402
 
12011
- Seedance mode is inferred: first/last frame selects frame mode, image/video/audio refs select reference mode, and no references selects text mode.`,
12403
+ Seedance and WAN mode are inferred: first/last frame selects frame mode, image/video/audio refs select reference mode, and no references selects text mode.`,
12012
12404
  audio: `Usage:
12013
12405
  makefx audio voices [--json]
12014
12406
  makefx audio align <variant-ref> "transcript" [--space <id>] [--json]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makefx",
3
- "version": "1.6.7",
3
+ "version": "1.6.8",
4
4
  "description": "Command-line interface for AI-assisted game asset production with Make Effects.",
5
5
  "license": "MIT",
6
6
  "type": "module",