makefx 1.0.7 → 1.1.0

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 +328 -97
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -176,4 +176,4 @@ Run `makefx --help` or `makefx help <command>` for command-specific options.
176
176
  - Media generation guide: https://makefx.app/docs/media-playbooks
177
177
  - Source: https://github.com/krasnoperov/inventory
178
178
 
179
- Version: 1.0.7
179
+ Version: 1.1.0
package/makefx.mjs CHANGED
@@ -844,7 +844,7 @@ function validateProjectConfig(config, configPath) {
844
844
  * makefx spaces inspect-deleted <space_id> Inspect a soft-deleted space
845
845
  * makefx spaces restore <space_id> Restore a soft-deleted space
846
846
  */
847
- var defaultDeps$10 = {
847
+ var defaultDeps$11 = {
848
848
  loadConfig: loadStoredConfig,
849
849
  resolveBaseUrl,
850
850
  saveProjectConfig,
@@ -859,7 +859,7 @@ async function handleSpaces(parsed) {
859
859
  process$1.exitCode = 1;
860
860
  }
861
861
  }
862
- async function executeSpaces(parsed, deps = defaultDeps$10) {
862
+ async function executeSpaces(parsed, deps = defaultDeps$11) {
863
863
  const env = resolveCommandEnvironment(parsed);
864
864
  const showDetails = parsed.options.details === "true";
865
865
  const spaceId = parsed.options.id;
@@ -5386,7 +5386,7 @@ function isMirrorEntry(value) {
5386
5386
  * makefx upload <file> --space <id> --name <name> Upload as new asset
5387
5387
  * makefx upload <file> --space <id> --name <name> --type <type>
5388
5388
  */
5389
- var defaultDeps$9 = {
5389
+ var defaultDeps$10 = {
5390
5390
  loadConfig: loadStoredConfig,
5391
5391
  loadProjectConfig,
5392
5392
  resolveBaseUrl,
@@ -5415,11 +5415,11 @@ async function handleUpload(parsed) {
5415
5415
  await executeUpload(parsed);
5416
5416
  } catch (error) {
5417
5417
  console.error(error instanceof Error ? `Error: ${error.message}` : "Error: Upload failed");
5418
- if (error instanceof UploadUsageError) printUsage$9();
5418
+ if (error instanceof UploadUsageError) printUsage$10();
5419
5419
  process$1.exitCode = 1;
5420
5420
  }
5421
5421
  }
5422
- async function executeUpload(parsed, deps = defaultDeps$9) {
5422
+ async function executeUpload(parsed, deps = defaultDeps$10) {
5423
5423
  const filePath = parsed.positionals[0];
5424
5424
  if (!filePath) throw new UploadUsageError("File path is required");
5425
5425
  rejectRetiredUploadOrganizationOptions(parsed);
@@ -5599,7 +5599,7 @@ function parseCsvOption(value, optionName) {
5599
5599
  if (value === "true") throw new UploadUsageError(`${optionName} requires a value`);
5600
5600
  return value.split(",").map((entry) => entry.trim()).filter(Boolean);
5601
5601
  }
5602
- function printUsage$9() {
5602
+ function printUsage$10() {
5603
5603
  console.log(`
5604
5604
  Usage:
5605
5605
  makefx upload <file> --asset <id> [--space <id>] Upload media to existing asset
@@ -6508,6 +6508,7 @@ var WebSocketClient = class WebSocketClient {
6508
6508
  prompt: params.prompt,
6509
6509
  count: params.count,
6510
6510
  model: params.model,
6511
+ aspectRatio: params.aspectRatio,
6511
6512
  imageSize: params.imageSize,
6512
6513
  musicProvider: params.musicProvider,
6513
6514
  generateAudio: params.generateAudio,
@@ -6831,6 +6832,7 @@ var VIDEO_GENERATION_RESOLUTIONS = [
6831
6832
  "1080p",
6832
6833
  "4k"
6833
6834
  ];
6835
+ var KLING_VIDEO_GENERATION_RESOLUTIONS = ["720p", "1080p"];
6834
6836
  var VIDEO_GENERATION_DURATION_SECONDS = [
6835
6837
  4,
6836
6838
  6,
@@ -6841,7 +6843,32 @@ var VIDEO_GENERATION_TIERS = [
6841
6843
  "fast",
6842
6844
  "lite"
6843
6845
  ];
6844
- var VIDEO_MODEL_SELECTIONS = ["veo-3.1", "omni-flash"];
6846
+ var VIDEO_MODEL_SELECTIONS = [
6847
+ "veo-3.1",
6848
+ "omni-flash",
6849
+ "kling",
6850
+ "fal-seedance"
6851
+ ];
6852
+ var VIDEO_MODEL_SUPPORTED_OPERATIONS = {
6853
+ "veo-3.1": [
6854
+ "generate",
6855
+ "refine",
6856
+ "derive"
6857
+ ],
6858
+ "omni-flash": [
6859
+ "generate",
6860
+ "refine",
6861
+ "derive"
6862
+ ],
6863
+ kling: [
6864
+ "generate",
6865
+ "refine",
6866
+ "derive"
6867
+ ],
6868
+ "fal-seedance": ["generate"]
6869
+ };
6870
+ var KLING_VIDEO_MODEL = "kling-v3";
6871
+ var FAL_VIDEO_MODEL = "fal-ai/bytedance/seedance/v1/pro/text-to-video";
6845
6872
  var GEMINI_OMNI_FLASH_VIDEO_MODEL = "gemini-omni-flash-preview";
6846
6873
  var VIDEO_GENERATION_AUDIO_TOGGLE_MODELS = [];
6847
6874
  var VIDEO_GENERATION_RESOLUTIONS_BY_TIER = {
@@ -6876,7 +6903,10 @@ function getVideoGenerationModelForTier(tier = DEFAULT_VIDEO_GENERATION_TIER) {
6876
6903
  return VIDEO_GENERATION_TIER_MODELS[tier];
6877
6904
  }
6878
6905
  function getVideoGenerationModelForSelection(selection = DEFAULT_VIDEO_MODEL_SELECTION, tier = DEFAULT_VIDEO_GENERATION_TIER) {
6879
- return selection === "omni-flash" ? GEMINI_OMNI_FLASH_VIDEO_MODEL : getVideoGenerationModelForTier(tier);
6906
+ if (selection === "omni-flash") return GEMINI_OMNI_FLASH_VIDEO_MODEL;
6907
+ if (selection === "kling") return KLING_VIDEO_MODEL;
6908
+ if (selection === "fal-seedance") return FAL_VIDEO_MODEL;
6909
+ return getVideoGenerationModelForTier(tier);
6880
6910
  }
6881
6911
  function getVideoGenerationResolutionsForTier(tier = DEFAULT_VIDEO_GENERATION_TIER) {
6882
6912
  return VIDEO_GENERATION_RESOLUTIONS_BY_TIER[tier];
@@ -6884,28 +6914,55 @@ function getVideoGenerationResolutionsForTier(tier = DEFAULT_VIDEO_GENERATION_TI
6884
6914
  function isVideoGenerationResolutionSupportedForTier(resolution, tier = DEFAULT_VIDEO_GENERATION_TIER) {
6885
6915
  return VIDEO_GENERATION_RESOLUTIONS_BY_TIER[tier].includes(resolution);
6886
6916
  }
6917
+ function getVideoGenerationResolutionsForModel(model) {
6918
+ return isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model) ? KLING_VIDEO_GENERATION_RESOLUTIONS : getVideoGenerationResolutionsForTier(getVideoGenerationTierForModel(model));
6919
+ }
6920
+ function isVideoGenerationResolutionSupportedForModel(model, resolution) {
6921
+ return getVideoGenerationResolutionsForModel(model).includes(resolution);
6922
+ }
6887
6923
  function getVideoGenerationTierForModel(model) {
6888
6924
  if (typeof model !== "string") return void 0;
6889
6925
  return VIDEO_GENERATION_TIERS.find((tier) => VIDEO_GENERATION_TIER_MODELS[tier] === model);
6890
6926
  }
6927
+ function getVideoModelSelectionForModel(model) {
6928
+ if (model === "gemini-omni-flash-preview") return "omni-flash";
6929
+ if (model === "kling-v3") return "kling";
6930
+ if (model === "fal-ai/bytedance/seedance/v1/pro/text-to-video") return "fal-seedance";
6931
+ return getVideoGenerationTierForModel(model) ? "veo-3.1" : void 0;
6932
+ }
6891
6933
  function isVeoVideoGenerationModel(model) {
6892
6934
  return typeof model === "string" && getVideoGenerationTierForModel(model) !== void 0;
6893
6935
  }
6894
6936
  function isGeminiOmniVideoGenerationModel(model) {
6895
6937
  return model === GEMINI_OMNI_FLASH_VIDEO_MODEL;
6896
6938
  }
6939
+ function isKlingVideoGenerationModel(model) {
6940
+ return model === KLING_VIDEO_MODEL;
6941
+ }
6942
+ function isFalVideoGenerationModel(model) {
6943
+ return model === FAL_VIDEO_MODEL;
6944
+ }
6897
6945
  function isVideoGenerationModel(model) {
6898
- return isVeoVideoGenerationModel(model) || isGeminiOmniVideoGenerationModel(model);
6946
+ return isVeoVideoGenerationModel(model) || isGeminiOmniVideoGenerationModel(model) || isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model);
6947
+ }
6948
+ function isVideoOperationSupportedByModel(model, operation) {
6949
+ const selection = getVideoModelSelectionForModel(model);
6950
+ return selection !== void 0 && VIDEO_MODEL_SUPPORTED_OPERATIONS[selection].includes(operation);
6899
6951
  }
6900
6952
  function doesVideoGenerationModelSupportAudioToggle(model) {
6901
- return isVeoVideoGenerationModel(model) && VIDEO_GENERATION_AUDIO_TOGGLE_MODELS.includes(model);
6953
+ return isKlingVideoGenerationModel(model) || isVeoVideoGenerationModel(model) && VIDEO_GENERATION_AUDIO_TOGGLE_MODELS.includes(model);
6902
6954
  }
6903
6955
  //#endregion
6904
6956
  //#region src/shared/imageGenerationOptions.ts
6905
- var IMAGE_MODEL_SELECTIONS = ["pro", "flash"];
6957
+ var IMAGE_MODEL_SELECTIONS = [
6958
+ "pro",
6959
+ "flash",
6960
+ "flux"
6961
+ ];
6906
6962
  var IMAGE_MODEL_IDS = {
6907
6963
  pro: "gemini-3-pro-image",
6908
- flash: "gemini-3.1-flash-image"
6964
+ flash: "gemini-3.1-flash-image",
6965
+ flux: "fal-ai/flux/dev"
6909
6966
  };
6910
6967
  IMAGE_MODEL_IDS["pro"];
6911
6968
  var IMAGE_ASPECT_RATIOS = [
@@ -6929,6 +6986,13 @@ var IMAGE_MODEL_CAPABILITIES = {
6929
6986
  pro: {
6930
6987
  selection: "pro",
6931
6988
  modelId: IMAGE_MODEL_IDS.pro,
6989
+ label: "Pro",
6990
+ provider: "gemini",
6991
+ supportedOperations: [
6992
+ "generate",
6993
+ "derive",
6994
+ "refine"
6995
+ ],
6932
6996
  maxReferenceImages: 14,
6933
6997
  supportedImageSizes: [
6934
6998
  "1K",
@@ -6940,6 +7004,13 @@ var IMAGE_MODEL_CAPABILITIES = {
6940
7004
  flash: {
6941
7005
  selection: "flash",
6942
7006
  modelId: IMAGE_MODEL_IDS.flash,
7007
+ label: "Flash",
7008
+ provider: "gemini",
7009
+ supportedOperations: [
7010
+ "generate",
7011
+ "derive",
7012
+ "refine"
7013
+ ],
6943
7014
  maxReferenceImages: 14,
6944
7015
  supportedImageSizes: [
6945
7016
  "1K",
@@ -6947,6 +7018,16 @@ var IMAGE_MODEL_CAPABILITIES = {
6947
7018
  "4K"
6948
7019
  ],
6949
7020
  supportedAspectRatios: IMAGE_ASPECT_RATIOS
7021
+ },
7022
+ flux: {
7023
+ selection: "flux",
7024
+ modelId: IMAGE_MODEL_IDS.flux,
7025
+ label: "FLUX.1 Dev",
7026
+ provider: "fal",
7027
+ supportedOperations: ["generate"],
7028
+ maxReferenceImages: 0,
7029
+ supportedImageSizes: ["1K"],
7030
+ supportedAspectRatios: IMAGE_ASPECT_RATIOS
6950
7031
  }
6951
7032
  };
6952
7033
  function isImageModelSelection(value) {
@@ -6964,7 +7045,9 @@ function normalizeImageSize(value) {
6964
7045
  }
6965
7046
  function getImageModelSelection(value) {
6966
7047
  if (isImageModelSelection(value)) return value;
6967
- return value === IMAGE_MODEL_IDS.flash ? "flash" : "pro";
7048
+ if (value === IMAGE_MODEL_IDS.flash) return "flash";
7049
+ if (value === IMAGE_MODEL_IDS.flux) return "flux";
7050
+ return "pro";
6968
7051
  }
6969
7052
  function getImageModelCapabilities(model) {
6970
7053
  return IMAGE_MODEL_CAPABILITIES[getImageModelSelection(model ?? "pro")];
@@ -6978,6 +7061,9 @@ function isImageAspectRatioSupportedByModel(model, aspectRatio) {
6978
7061
  function getImageModelMaxReferenceImages(model) {
6979
7062
  return getImageModelCapabilities(model).maxReferenceImages;
6980
7063
  }
7064
+ function isImageOperationSupportedByModel(model, operation) {
7065
+ return getImageModelCapabilities(model).supportedOperations.includes(operation);
7066
+ }
6981
7067
  //#endregion
6982
7068
  //#region src/shared/mediaOperationMatrix.ts
6983
7069
  var MEDIA_OPERATION_MATRIX = [
@@ -7139,7 +7225,7 @@ function cliGenerationSupportsRefs(namespace) {
7139
7225
  //#endregion
7140
7226
  //#region src/cli/commands/forge.ts
7141
7227
  var CLI_GENERATION_MEDIA_KIND = getCliGenerationMediaKind("top-level");
7142
- var defaultDeps$8 = {
7228
+ var defaultDeps$9 = {
7143
7229
  loadConfig: loadStoredConfig,
7144
7230
  loadProjectConfig,
7145
7231
  resolveBaseUrl,
@@ -7213,10 +7299,10 @@ async function handleBatch(parsed) {
7213
7299
  }
7214
7300
  async function handleForgeCommand(command, parsed) {
7215
7301
  try {
7216
- await executeForgeCommand(command, parsed, defaultDeps$8);
7302
+ await executeForgeCommand(command, parsed, defaultDeps$9);
7217
7303
  } catch (error) {
7218
7304
  console.error("Error:", error instanceof Error ? error.message : error);
7219
- if (shouldPrintUsageForForgeError(error)) printUsage$8(command);
7305
+ if (shouldPrintUsageForForgeError(error)) printUsage$9(command);
7220
7306
  process$1.exitCode = 1;
7221
7307
  }
7222
7308
  }
@@ -7225,11 +7311,11 @@ function shouldPrintUsageForForgeError(error) {
7225
7311
  const message = error.message;
7226
7312
  return message.startsWith("--") || message.startsWith("Output path is required") || message.startsWith("Output directory is required") || message.startsWith("Pass either prompt text") || message.startsWith("Speech generation requires") || message.startsWith("Dialogue generation requires") || message.startsWith("Prompt is required");
7227
7313
  }
7228
- async function executeForgeCommand(command, parsed, deps = defaultDeps$8, options = {}) {
7314
+ async function executeForgeCommand(command, parsed, deps = defaultDeps$9, options = {}) {
7229
7315
  const mediaKind = options.mediaKind || CLI_GENERATION_MEDIA_KIND;
7230
7316
  if (parsed.options.follow) {
7231
7317
  if (command === "batch") throw new Error("--follow is only supported for single-output generation commands");
7232
- const ctx = await buildContext$5(parsed, deps);
7318
+ const ctx = await buildContext$6(parsed, deps);
7233
7319
  const client = await deps.createClient(ctx.env, ctx.spaceId);
7234
7320
  try {
7235
7321
  await client.connect();
@@ -7239,11 +7325,13 @@ async function executeForgeCommand(command, parsed, deps = defaultDeps$8, option
7239
7325
  }
7240
7326
  }
7241
7327
  const saveBatchManifest = options.saveBatchManifest ?? mediaKind === "image";
7242
- validateImageCommandReferenceCount(command, parsed, mediaKind, parseImageGenerationOptions(parsed, mediaKind).model);
7328
+ const imageOptions = parseImageGenerationOptions(parsed, mediaKind);
7329
+ validateImageModelOperation(command, mediaKind, imageOptions.model);
7330
+ validateImageCommandReferenceCount(command, parsed, mediaKind, imageOptions.model);
7243
7331
  validateVideoAudioOptions(parsed, mediaKind);
7244
- parseVideoGenerationOptions(parsed, mediaKind);
7332
+ validateVideoModelOperation(command, mediaKind, parseVideoGenerationOptions(parsed, mediaKind).model);
7245
7333
  validateVideoFrameReferenceOptions(command, parsed, mediaKind);
7246
- const ctx = await buildContext$5(parsed, deps);
7334
+ const ctx = await buildContext$6(parsed, deps);
7247
7335
  const client = await deps.createClient(ctx.env, ctx.spaceId);
7248
7336
  try {
7249
7337
  await client.connect();
@@ -7257,7 +7345,7 @@ async function executeForgeCommand(command, parsed, deps = defaultDeps$8, option
7257
7345
  client.disconnect();
7258
7346
  }
7259
7347
  }
7260
- async function executeAudioCommand(command, parsed, deps = defaultDeps$8, options = {}) {
7348
+ async function executeAudioCommand(command, parsed, deps = defaultDeps$9, options = {}) {
7261
7349
  const audioProfile = getCliGenerationProfile("audio");
7262
7350
  if (!audioProfile.commands.includes(command)) throw new Error(`Audio generation does not support ${command}`);
7263
7351
  const modeEntry = options.mode ? getMediaOperationEntry(options.mode) : void 0;
@@ -7270,7 +7358,7 @@ async function executeAudioCommand(command, parsed, deps = defaultDeps$8, option
7270
7358
  audioMode: options.mode
7271
7359
  });
7272
7360
  }
7273
- async function executeVideoCommand(command, parsed, deps = defaultDeps$8) {
7361
+ async function executeVideoCommand(command, parsed, deps = defaultDeps$9) {
7274
7362
  const videoProfile = getCliGenerationProfile("video");
7275
7363
  if (!videoProfile.commands.includes(command)) throw new Error(`Video generation does not support ${command}`);
7276
7364
  return executeForgeCommand(command, parsed, deps, {
@@ -7315,6 +7403,9 @@ async function executeGenerate(parsed, ctx, client, deps, mediaKind, followOptio
7315
7403
  const audioModelOptions = parseAudioGenerationOptions(parsed, mediaKind);
7316
7404
  const videoAudioOptions = parseVideoAudioOptions(parsed, mediaKind);
7317
7405
  const videoOptions = parseVideoGenerationOptions(parsed, mediaKind);
7406
+ const effectiveVideoModel = videoOptions.model ?? getVideoGenerationModelForSelection();
7407
+ if (mediaKind === "video" && isKlingVideoGenerationModel(effectiveVideoModel) && videoFrameRefs.length > 1) throw new Error("--model kling supports at most one image reference");
7408
+ if (mediaKind === "video" && isFalVideoGenerationModel(effectiveVideoModel) && videoFrameRefs.length > 0) throw new Error(`--model ${getVideoModelSelectionForModel(effectiveVideoModel) ?? effectiveVideoModel} does not support image references`);
7318
7409
  const collectionPlacement = parseCollectionPlacementOptions(parsed);
7319
7410
  const followCommandOptions = {
7320
7411
  ...followOptions,
@@ -7327,6 +7418,7 @@ async function executeGenerate(parsed, ctx, client, deps, mediaKind, followOptio
7327
7418
  prompt,
7328
7419
  count: 1,
7329
7420
  model: imageOptions.model ?? audioModelOptions.model ?? videoOptions.model,
7421
+ aspectRatio: imageOptions.aspectRatio ?? videoOptions.aspectRatio,
7330
7422
  imageSize: imageOptions.imageSize,
7331
7423
  ...musicProvider ? { musicProvider } : {},
7332
7424
  ...videoAudioOptions,
@@ -7425,6 +7517,7 @@ async function executeRefine(parsed, ctx, client, deps, mediaKind) {
7425
7517
  prompt,
7426
7518
  count: 1,
7427
7519
  model: imageOptions.model ?? videoOptions.model,
7520
+ aspectRatio: imageOptions.aspectRatio ?? videoOptions.aspectRatio,
7428
7521
  imageSize: imageOptions.imageSize,
7429
7522
  ...videoAudioOptions,
7430
7523
  ...videoOptions
@@ -7491,6 +7584,9 @@ async function executeDerive(parsed, ctx, client, deps, mediaKind, followOptions
7491
7584
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
7492
7585
  const videoAudioOptions = parseVideoAudioOptions(parsed, mediaKind);
7493
7586
  const videoOptions = parseVideoGenerationOptions(parsed, mediaKind);
7587
+ const effectiveVideoModel = videoOptions.model ?? getVideoGenerationModelForSelection();
7588
+ if (mediaKind === "video" && isKlingVideoGenerationModel(effectiveVideoModel) && referenceRefs.length > 1) throw new Error("--model kling supports at most one image reference");
7589
+ if (mediaKind === "video" && isFalVideoGenerationModel(effectiveVideoModel) && referenceRefs.length > 0) throw new Error(`--model ${getVideoModelSelectionForModel(effectiveVideoModel) ?? effectiveVideoModel} does not support ${referenceRefs.length} image references`);
7494
7590
  const collectionPlacement = parseCollectionPlacementOptions(parsed);
7495
7591
  const followCommandOptions = {
7496
7592
  ...followOptions,
@@ -7503,6 +7599,7 @@ async function executeDerive(parsed, ctx, client, deps, mediaKind, followOptions
7503
7599
  prompt,
7504
7600
  count: 1,
7505
7601
  model: imageOptions.model ?? videoOptions.model,
7602
+ aspectRatio: imageOptions.aspectRatio ?? videoOptions.aspectRatio,
7506
7603
  imageSize: imageOptions.imageSize,
7507
7604
  ...videoAudioOptions,
7508
7605
  ...videoOptions
@@ -7726,6 +7823,7 @@ async function executeBatch(parsed, ctx, client, deps, mediaKind, saveBatchManif
7726
7823
  prompt,
7727
7824
  count,
7728
7825
  model: imageOptions.model ?? audioModelOptions.model,
7826
+ aspectRatio: imageOptions.aspectRatio,
7729
7827
  imageSize: imageOptions.imageSize,
7730
7828
  ...musicProvider ? { musicProvider } : {}
7731
7829
  });
@@ -7905,7 +8003,7 @@ async function createCollectionAssetItem(input) {
7905
8003
  throw new Error(`Failed to place asset ${input.assetId} in collection ${input.collectionId} (${response.status}): ${errorText || response.statusText}`);
7906
8004
  }
7907
8005
  }
7908
- async function buildContext$5(parsed, deps) {
8006
+ async function buildContext$6(parsed, deps) {
7909
8007
  const projectConfig = await deps.loadProjectConfig();
7910
8008
  const env = resolveCommandEnvironment(parsed, projectConfig);
7911
8009
  const spaceId = resolveCommandSpace(parsed, projectConfig);
@@ -8190,7 +8288,7 @@ function validateVideoAudioOptions(parsed, mediaKind) {
8190
8288
  const videoTier = tierValue === void 0 ? DEFAULT_VIDEO_GENERATION_TIER : normalizeVideoGenerationTier(tierValue);
8191
8289
  if (!videoTier) throw new Error("--tier must be generate, fast, or lite");
8192
8290
  const model = parseVideoModelOption(modelValue, videoTier);
8193
- if (parsed.options.audio !== void 0 && isGeminiOmniVideoGenerationModel(model)) throw new Error("--audio is only supported with --model veo-3.1");
8291
+ if (parsed.options.audio !== void 0 && (isGeminiOmniVideoGenerationModel(model) || isFalVideoGenerationModel(model))) throw new Error("--audio is only supported with --model veo-3.1 or kling");
8194
8292
  if (parsed.options["no-audio"] !== void 0 || parsed.options.noAudio !== void 0) {
8195
8293
  if (!doesVideoGenerationModelSupportAudioToggle(model)) throw new Error(`${model} does not support --no-audio. Use the default audio-enabled output or omit the flag.`);
8196
8294
  }
@@ -8218,7 +8316,9 @@ function parseVideoGenerationOptions(parsed, mediaKind) {
8218
8316
  if (tierValue !== void 0 && !videoTier) throw new Error("--tier must be generate, fast, or lite");
8219
8317
  const model = parseVideoModelOption(modelValue, videoTier);
8220
8318
  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");
8319
+ if ((isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model)) && tierValue !== void 0) throw new Error("--tier is only supported with --model veo-3.1");
8221
8320
  if (videoResolution && videoTier && !isVideoGenerationResolutionSupportedForTier(videoResolution, videoTier)) throw new Error("--resolution 4k is not supported with --tier lite");
8321
+ if (videoResolution && (isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model)) && !isVideoGenerationResolutionSupportedForModel(model, videoResolution)) throw new Error(`--model ${getVideoModelSelectionForModel(model) ?? model} supports only --resolution 720p or 1080p`);
8222
8322
  const aspectRatio = aspectValue === void 0 ? void 0 : normalizeVideoGenerationAspectRatio(aspectValue);
8223
8323
  if (aspectValue !== void 0 && !aspectRatio) throw new Error("--aspect must be 16:9 or 9:16");
8224
8324
  return {
@@ -8245,7 +8345,8 @@ function validateVideoFrameReferenceOptions(command, parsed, mediaKind) {
8245
8345
  if (parsed.options.refs) throw new Error("--first-frame and --last-frame cannot be combined with --refs");
8246
8346
  const tierValue = readOptionalOption(parsed, "tier", "tier") ?? readOptionalOption(parsed, "video-tier", "videoTier");
8247
8347
  const videoTier = tierValue === void 0 ? void 0 : normalizeVideoGenerationTier(tierValue);
8248
- if (isGeminiOmniVideoGenerationModel(parseVideoModelOption(readOptionalOption(parsed, "model", "model"), videoTier))) throw new Error("--first-frame and --last-frame are only supported with --model veo-3.1");
8348
+ const model = parseVideoModelOption(readOptionalOption(parsed, "model", "model"), videoTier);
8349
+ if (isFalVideoGenerationModel(model) || isGeminiOmniVideoGenerationModel(model) || isKlingVideoGenerationModel(model) && Boolean(lastFrame)) throw new Error("--first-frame and --last-frame are only supported with --model veo-3.1");
8249
8350
  }
8250
8351
  function readVideoFrameOption(parsed, kebabName, camelName) {
8251
8352
  const value = parsed.options[kebabName] ?? parsed.options[camelName];
@@ -8299,17 +8400,18 @@ function parseVideoModelOption(value, tier) {
8299
8400
  if (selection) return getVideoGenerationModelForSelection(selection, effectiveTier);
8300
8401
  if (isVideoGenerationModel(normalized)) {
8301
8402
  const modelTier = normalizeVideoGenerationTier(tier) ?? void 0;
8302
- if (modelTier && getVideoGenerationModelForTier(modelTier) !== normalized && !isGeminiOmniVideoGenerationModel(normalized)) throw new Error("--model and --tier select different Veo models");
8403
+ if (modelTier && getVideoGenerationModelForTier(modelTier) !== normalized && !isGeminiOmniVideoGenerationModel(normalized) && !isKlingVideoGenerationModel(normalized) && !isFalVideoGenerationModel(normalized)) throw new Error("--model and --tier select different Veo models");
8303
8404
  return normalized;
8304
8405
  }
8305
- throw new Error("--model must be veo-3.1, omni-flash, or an exact video model ID");
8406
+ throw new Error("--model must be veo-3.1, omni-flash, kling, or an exact video model ID");
8306
8407
  }
8307
8408
  function parseImageModelOption(value) {
8308
8409
  if (!value) return void 0;
8309
8410
  if (isImageModelSelection(value)) return value;
8310
8411
  if (value === IMAGE_MODEL_IDS.pro) return "pro";
8311
8412
  if (value === IMAGE_MODEL_IDS.flash) return "flash";
8312
- throw new Error("--model must be pro or flash");
8413
+ if (value === IMAGE_MODEL_IDS.flux) return "flux";
8414
+ throw new Error("--model must be pro, flash, or flux");
8313
8415
  }
8314
8416
  function parseImageSizeOption(value) {
8315
8417
  if (!value) return void 0;
@@ -8332,9 +8434,23 @@ function validateImageReferenceCount(model, referenceCount) {
8332
8434
  }
8333
8435
  function validateImageCommandReferenceCount(command, parsed, mediaKind, model) {
8334
8436
  if (mediaKind !== "image") return;
8335
- if (command !== "derive" && command !== "batch") return;
8336
- if (!parsed.options.refs) return;
8337
- validateImageReferenceCount(model, parseRefs(parsed.options.refs).length);
8437
+ if (command === "refine") {
8438
+ validateImageReferenceCount(model, 1);
8439
+ return;
8440
+ }
8441
+ if ((command === "derive" || command === "batch") && parsed.options.refs) validateImageReferenceCount(model, parseRefs(parsed.options.refs).length);
8442
+ }
8443
+ function validateImageModelOperation(command, mediaKind, model) {
8444
+ if (mediaKind !== "image") return;
8445
+ const operation = command === "batch" ? "generate" : command;
8446
+ if (isImageOperationSupportedByModel(model, operation)) return;
8447
+ throw new Error(`--model ${model ?? "pro"} does not support ${operation}`);
8448
+ }
8449
+ function validateVideoModelOperation(command, mediaKind, model) {
8450
+ if (mediaKind !== "video" || command === "batch") return;
8451
+ const effectiveModel = model ?? getVideoGenerationModelForSelection();
8452
+ if (isVideoOperationSupportedByModel(effectiveModel, command)) return;
8453
+ throw new Error(`--model ${getVideoModelSelectionForModel(effectiveModel) ?? effectiveModel} does not support video ${command}`);
8338
8454
  }
8339
8455
  function readOptionalOption(parsed, kebabName, camelName) {
8340
8456
  const value = parsed.options[kebabName] ?? parsed.options[camelName];
@@ -8378,11 +8494,15 @@ function cliImageSizeValues() {
8378
8494
  function cliImageAspectValues() {
8379
8495
  return cliOptionValues(getImageModelCapabilities().supportedAspectRatios);
8380
8496
  }
8381
- function printUsage$8(command) {
8497
+ function cliImageModelValues(command) {
8498
+ const operation = command === "batch" ? "generate" : command;
8499
+ return cliOptionValues(IMAGE_MODEL_SELECTIONS.filter((model) => isImageOperationSupportedByModel(model, operation)));
8500
+ }
8501
+ function printUsage$9(command) {
8382
8502
  if (command === "generate") {
8383
8503
  console.log(`
8384
8504
  Usage:
8385
- makefx generate "prompt" --name <name> --type <type> -o <file> [--model pro|flash] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>] [--space <id>]
8505
+ makefx generate "prompt" --name <name> --type <type> -o <file> [--model ${cliImageModelValues(command)}] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>] [--space <id>]
8386
8506
  makefx generate --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
8387
8507
  `);
8388
8508
  return;
@@ -8390,7 +8510,7 @@ Usage:
8390
8510
  if (command === "refine") {
8391
8511
  console.log(`
8392
8512
  Usage:
8393
- makefx refine --variant <variant_id> "prompt" -o <file> [--model pro|flash] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>] [--space <id>]
8513
+ makefx refine --variant <variant_id> "prompt" -o <file> [--model ${cliImageModelValues(command)}] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>] [--space <id>]
8394
8514
  makefx refine --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
8395
8515
  `);
8396
8516
  return;
@@ -8398,13 +8518,13 @@ Usage:
8398
8518
  if (command === "batch") {
8399
8519
  console.log(`
8400
8520
  Usage:
8401
- makefx batch "prompt" --name <name> --type <type> --count <2-8> --output-dir <dir> [--model pro|flash] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>]
8521
+ makefx batch "prompt" --name <name> --type <type> --count <2-8> --output-dir <dir> [--model ${cliImageModelValues(command)}] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>]
8402
8522
  `);
8403
8523
  return;
8404
8524
  }
8405
8525
  console.log(`
8406
8526
  Usage:
8407
- makefx derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--model pro|flash] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>] [--space <id>]
8527
+ makefx derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--model ${cliImageModelValues(command)}] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>] [--space <id>]
8408
8528
  makefx derive --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
8409
8529
  `);
8410
8530
  }
@@ -8419,7 +8539,7 @@ function printBatchResult(result, outputDir, manifestPath, ctx, mediaKind) {
8419
8539
  }
8420
8540
  //#endregion
8421
8541
  //#region src/cli/commands/audio.ts
8422
- var defaultDeps$7 = {
8542
+ var defaultDeps$8 = {
8423
8543
  loadConfig: loadStoredConfig,
8424
8544
  loadProjectConfig,
8425
8545
  resolveBaseUrl,
@@ -8432,11 +8552,11 @@ async function handleAudio(parsed) {
8432
8552
  await executeAudio(parsed);
8433
8553
  } catch (error) {
8434
8554
  console.error("Error:", error instanceof Error ? error.message : error);
8435
- printUsage$7();
8555
+ printUsage$8();
8436
8556
  process$1.exitCode = 1;
8437
8557
  }
8438
8558
  }
8439
- async function executeAudio(parsed, deps = defaultDeps$7) {
8559
+ async function executeAudio(parsed, deps = defaultDeps$8) {
8440
8560
  const invocation = parseAudioInvocation(parsed.positionals);
8441
8561
  if (invocation.command === "voices") return executeAudioVoices({
8442
8562
  ...parsed,
@@ -8509,7 +8629,7 @@ function printVoices(response, print) {
8509
8629
  function formatLabels(labels) {
8510
8630
  return Object.entries(labels).map(([key, value]) => `${key}:${value}`).join(", ");
8511
8631
  }
8512
- function printUsage$7() {
8632
+ function printUsage$8() {
8513
8633
  const modes = AUDIO_FORGE_MEDIA_MODES.join("|");
8514
8634
  console.log(`
8515
8635
  Usage:
@@ -8538,7 +8658,7 @@ async function handleVideo(parsed) {
8538
8658
  });
8539
8659
  } catch (error) {
8540
8660
  console.error("Error:", error instanceof Error ? error.message : error);
8541
- printUsage$6();
8661
+ printUsage$7();
8542
8662
  process$1.exitCode = 1;
8543
8663
  }
8544
8664
  }
@@ -8547,28 +8667,28 @@ function parseVideoCommand(value) {
8547
8667
  if (value && commands.includes(value)) return value;
8548
8668
  throw new Error("Video command is required: generate, refine, or derive");
8549
8669
  }
8550
- function printUsage$6() {
8670
+ function printUsage$7() {
8551
8671
  const aspectValues = VIDEO_GENERATION_ASPECT_RATIOS.join("|");
8552
8672
  const resolutionValues = Array.from(new Set(VIDEO_GENERATION_TIERS.flatMap((tier) => getVideoGenerationResolutionsForTier(tier)))).join("|");
8553
8673
  const durationValues = VIDEO_GENERATION_DURATION_SECONDS.join("|");
8554
8674
  const tierValues = VIDEO_GENERATION_TIERS.join("|");
8555
- const modelValues = VIDEO_MODEL_SELECTIONS.join("|");
8675
+ const modelValues = (operation) => VIDEO_MODEL_SELECTIONS.filter((model) => VIDEO_MODEL_SUPPORTED_OPERATIONS[model].includes(operation)).join("|");
8556
8676
  const resolutionByTier = VIDEO_GENERATION_TIERS.map((tier) => `${tier}: ${getVideoGenerationResolutionsForTier(tier).join(", ")}`).join("; ");
8557
8677
  console.log(`
8558
8678
  Usage:
8559
- makefx video generate "prompt" --name <name> --type <type> -o <file> [--model ${modelValues}] [--first-frame <variant_or_file>] [--last-frame <variant_or_file>] [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
8679
+ makefx video generate "prompt" --name <name> --type <type> -o <file> [--model ${modelValues("generate")}] [--first-frame <variant_or_file>] [--last-frame <variant_or_file>] [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
8560
8680
  makefx video generate --follow <variant_id> -o <file> [--space <id>]
8561
- makefx video refine --variant <variant_id> "prompt" -o <file> [--model ${modelValues}] [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
8681
+ makefx video refine --variant <variant_id> "prompt" -o <file> [--model ${modelValues("refine")}] [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
8562
8682
  makefx video refine --follow <variant_id> -o <file> [--space <id>]
8563
- makefx video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--model ${modelValues}] [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
8683
+ makefx video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--model ${modelValues("derive")}] [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
8564
8684
  makefx video derive --first-frame <variant_or_file> [--last-frame <variant_or_file>] --name <name> --type <type> "prompt" -o <file> [--model veo-3.1] [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
8565
8685
  makefx video derive --follow <variant_id> -o <file> [--space <id>]
8566
8686
 
8567
8687
  Video:
8568
- --model <value> Video model: ${modelValues}
8688
+ --model <value> Generate: ${modelValues("generate")}; refine/derive: ${modelValues("refine")}
8569
8689
  --aspect <ratio> Video aspect ratio: ${aspectValues}
8570
- --resolution <value> Veo-only output resolution (${resolutionByTier})
8571
- --duration <seconds> Veo-only output duration: ${durationValues}
8690
+ --resolution <value> Veo: ${resolutionValues}; Kling/fal Seedance: 720p|1080p (${resolutionByTier})
8691
+ --duration <seconds> Veo/Kling/fal Seedance output duration: ${durationValues}
8572
8692
  --tier <tier> Veo-only model tier: ${tierValues}
8573
8693
  --first-frame <ref> Veo start frame image variant or local image path
8574
8694
  --last-frame <ref> Veo final frame image variant or local image path
@@ -8586,17 +8706,17 @@ Audio:
8586
8706
  }
8587
8707
  //#endregion
8588
8708
  //#region src/cli/commands/init.ts
8589
- var defaultDeps$6 = { saveProjectConfig };
8709
+ var defaultDeps$7 = { saveProjectConfig };
8590
8710
  async function handleInit(parsed) {
8591
8711
  try {
8592
8712
  await executeInit(parsed);
8593
8713
  } catch (error) {
8594
8714
  console.error("Error:", error instanceof Error ? error.message : error);
8595
- printUsage$5();
8715
+ printUsage$6();
8596
8716
  process$1.exitCode = 1;
8597
8717
  }
8598
8718
  }
8599
- async function executeInit(parsed, deps = defaultDeps$6) {
8719
+ async function executeInit(parsed, deps = defaultDeps$7) {
8600
8720
  const environment = resolveCommandEnvironment(parsed);
8601
8721
  const spaceId = resolveCommandSpace(parsed);
8602
8722
  if (!spaceId) throw new Error("--space is required");
@@ -8622,7 +8742,7 @@ async function executeInit(parsed, deps = defaultDeps$6) {
8622
8742
  spaceId
8623
8743
  };
8624
8744
  }
8625
- function printUsage$5() {
8745
+ function printUsage$6() {
8626
8746
  console.log(`
8627
8747
  Usage:
8628
8748
  makefx init --space <id> [--env production|stage|local]
@@ -8631,7 +8751,7 @@ Usage:
8631
8751
  }
8632
8752
  //#endregion
8633
8753
  //#region src/cli/commands/runs.ts
8634
- var defaultDeps$5 = {
8754
+ var defaultDeps$6 = {
8635
8755
  loadProjectConfig,
8636
8756
  listRunManifests,
8637
8757
  readRunManifest,
@@ -8644,11 +8764,11 @@ async function handleRuns(parsed) {
8644
8764
  await executeRuns(parsed);
8645
8765
  } catch (error) {
8646
8766
  console.error("Error:", error instanceof Error ? error.message : error);
8647
- printUsage$4();
8767
+ printUsage$5();
8648
8768
  process$1.exitCode = 1;
8649
8769
  }
8650
8770
  }
8651
- async function executeRuns(parsed, deps = defaultDeps$5) {
8771
+ async function executeRuns(parsed, deps = defaultDeps$6) {
8652
8772
  const projectConfig = await deps.loadProjectConfig();
8653
8773
  if (!projectConfig?.projectRoot) throw new Error("Make Effects project config not found. Run: makefx init --space <id>");
8654
8774
  requireDebugAcknowledgement(parsed);
@@ -8766,7 +8886,7 @@ function formatCreated(value) {
8766
8886
  if (Number.isNaN(date.getTime())) return value;
8767
8887
  return value.replace("T", " ").replace(/\.\d{3}Z$/, "Z").slice(0, 20);
8768
8888
  }
8769
- function printUsage$4() {
8889
+ function printUsage$5() {
8770
8890
  console.log(`
8771
8891
  Usage:
8772
8892
  makefx runs --debug
@@ -8781,7 +8901,7 @@ Local run manifests are debug-only artifacts, not a source of truth.
8781
8901
  }
8782
8902
  //#endregion
8783
8903
  //#region src/cli/commands/assets.ts
8784
- var defaultDeps$4 = {
8904
+ var defaultDeps$5 = {
8785
8905
  loadConfig: loadStoredConfig,
8786
8906
  loadProjectConfig,
8787
8907
  resolveBaseUrl,
@@ -8805,15 +8925,15 @@ async function handleAssets(parsed) {
8805
8925
  await executeAssets(parsed);
8806
8926
  } catch (error) {
8807
8927
  console.error("Error:", error instanceof Error ? error.message : error);
8808
- printUsage$3();
8928
+ printUsage$4();
8809
8929
  process$1.exitCode = 1;
8810
8930
  }
8811
8931
  }
8812
- async function executeAssets(parsed, deps = defaultDeps$4) {
8932
+ async function executeAssets(parsed, deps = defaultDeps$5) {
8813
8933
  const subcommand = parsed.positionals[0] || "list";
8814
8934
  if (subcommand === "search") return searchAssets(parsed, deps);
8815
8935
  if (subcommand === "clone") return cloneAsset(parsed, deps);
8816
- const ctx = await buildContext$4(parsed, deps);
8936
+ const ctx = await buildContext$5(parsed, deps);
8817
8937
  if (subcommand === "list") {
8818
8938
  const assets = await listAssets(ctx, deps);
8819
8939
  if (parsed.options.json === "true") deps.print(JSON.stringify(assets.map(toAssetJson), null, 2));
@@ -8905,7 +9025,7 @@ async function executeAssets(parsed, deps = defaultDeps$4) {
8905
9025
  function normalizeOption$1(value) {
8906
9026
  return !value || value === "true" ? void 0 : value;
8907
9027
  }
8908
- async function buildContext$4(parsed, deps) {
9028
+ async function buildContext$5(parsed, deps) {
8909
9029
  const projectConfig = await deps.loadProjectConfig();
8910
9030
  const env = resolveCommandEnvironment(parsed, projectConfig);
8911
9031
  const spaceId = resolveCommandSpace(parsed, projectConfig);
@@ -9275,7 +9395,7 @@ function formatTimestamp(value) {
9275
9395
  if (Number.isNaN(date.getTime())) return String(value);
9276
9396
  return date.toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "Z").slice(0, 20);
9277
9397
  }
9278
- function printUsage$3() {
9398
+ function printUsage$4() {
9279
9399
  console.log(`
9280
9400
  Usage:
9281
9401
  makefx assets
@@ -9292,7 +9412,7 @@ Usage:
9292
9412
  }
9293
9413
  //#endregion
9294
9414
  //#region src/cli/commands/variants.ts
9295
- var defaultDeps$3 = {
9415
+ var defaultDeps$4 = {
9296
9416
  loadConfig: loadStoredConfig,
9297
9417
  loadProjectConfig,
9298
9418
  resolveBaseUrl,
@@ -9304,12 +9424,12 @@ async function handleVariants(parsed) {
9304
9424
  await executeVariants(parsed);
9305
9425
  } catch (error) {
9306
9426
  console.error("Error:", error instanceof Error ? error.message : error);
9307
- printUsage$2();
9427
+ printUsage$3();
9308
9428
  process$1.exitCode = 1;
9309
9429
  }
9310
9430
  }
9311
- async function executeVariants(parsed, deps = defaultDeps$3) {
9312
- const ctx = await buildContext$3(parsed, deps);
9431
+ async function executeVariants(parsed, deps = defaultDeps$4) {
9432
+ const ctx = await buildContext$4(parsed, deps);
9313
9433
  const subcommand = parsed.positionals[0];
9314
9434
  if (subcommand === "delete") {
9315
9435
  const variantId = requireVariantId(parsed, "delete");
@@ -9357,7 +9477,7 @@ function requireVariantId(parsed, verb) {
9357
9477
  if (!variantId) throw new Error(`Variant ID is required: makefx variants ${verb} <variant-id>`);
9358
9478
  return variantId;
9359
9479
  }
9360
- async function buildContext$3(parsed, deps) {
9480
+ async function buildContext$4(parsed, deps) {
9361
9481
  const projectConfig = await deps.loadProjectConfig();
9362
9482
  const env = resolveCommandEnvironment(parsed, projectConfig);
9363
9483
  const spaceId = resolveCommandSpace(parsed, projectConfig);
@@ -9380,7 +9500,7 @@ async function withVariantClient(ctx, deps, run) {
9380
9500
  client.disconnect();
9381
9501
  }
9382
9502
  }
9383
- function printUsage$2() {
9503
+ function printUsage$3() {
9384
9504
  console.log(`
9385
9505
  Usage:
9386
9506
  makefx variants delete <variant-id>
@@ -9396,6 +9516,84 @@ Options:
9396
9516
  `);
9397
9517
  }
9398
9518
  //#endregion
9519
+ //#region src/cli/commands/recipes.ts
9520
+ var defaultDeps$3 = {
9521
+ loadConfig: loadStoredConfig,
9522
+ loadProjectConfig,
9523
+ resolveBaseUrl,
9524
+ fetch,
9525
+ print: console.log
9526
+ };
9527
+ async function handleRecipes(parsed) {
9528
+ try {
9529
+ await executeRecipes(parsed);
9530
+ } catch (error) {
9531
+ console.error("Error:", error instanceof Error ? error.message : error);
9532
+ printUsage$2();
9533
+ process$1.exitCode = 1;
9534
+ }
9535
+ }
9536
+ async function executeRecipes(parsed, deps = defaultDeps$3) {
9537
+ const subcommand = parsed.positionals[0];
9538
+ if (subcommand !== "run") throw new Error(`Unknown recipes command: ${subcommand ?? "(none)"}`);
9539
+ const sourceVariantId = parsed.positionals[1];
9540
+ if (!sourceVariantId) throw new Error("Variant ID is required: makefx recipes run <variant-id>");
9541
+ const rerun = await runRecipe(await buildContext$3(parsed, deps), deps, sourceVariantId);
9542
+ if (parsed.options.json === "true") deps.print(JSON.stringify(rerun, null, 2));
9543
+ else {
9544
+ deps.print(`Re-ran recipe from variant ${rerun.sourceVariantId}`);
9545
+ deps.print(` Variant: ${rerun.variant.id} (status: ${rerun.variant.status})`);
9546
+ deps.print(` Request: ${rerun.requestId}`);
9547
+ deps.print(`Watch progress with: makefx assets show ${rerun.variant.asset_id}`);
9548
+ }
9549
+ return {
9550
+ type: "run",
9551
+ rerun
9552
+ };
9553
+ }
9554
+ async function buildContext$3(parsed, deps) {
9555
+ const projectConfig = await deps.loadProjectConfig();
9556
+ const env = resolveCommandEnvironment(parsed, projectConfig);
9557
+ const spaceId = resolveCommandSpace(parsed, projectConfig);
9558
+ if (!spaceId) throw new Error("--space is required, or run: makefx init --space <id>");
9559
+ const config = await deps.loadConfig(env);
9560
+ if (!config) throw new Error(`Not logged in to ${env} environment. Run: ${loginCommandForEnvironment(env)}`);
9561
+ if (config.token.expiresAt < Date.now()) throw new Error(`Token expired for ${env} environment. Run: ${loginCommandForEnvironment(env)}`);
9562
+ if (env === "local") process$1.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
9563
+ return {
9564
+ spaceId,
9565
+ baseUrl: deps.resolveBaseUrl(env),
9566
+ accessToken: config.token.accessToken
9567
+ };
9568
+ }
9569
+ async function runRecipe(ctx, deps, sourceVariantId) {
9570
+ const response = await deps.fetch(`${ctx.baseUrl}/api/spaces/${encodeURIComponent(ctx.spaceId)}/variants/${encodeURIComponent(sourceVariantId)}/rerun`, {
9571
+ method: "POST",
9572
+ headers: {
9573
+ Authorization: `Bearer ${ctx.accessToken}`,
9574
+ Accept: "application/json"
9575
+ }
9576
+ });
9577
+ if (!response.ok) {
9578
+ const text = await response.text();
9579
+ throw new Error(`Recipe rerun failed (${response.status}): ${text || response.statusText}`);
9580
+ }
9581
+ return response.json();
9582
+ }
9583
+ function printUsage$2() {
9584
+ console.log(`
9585
+ Usage:
9586
+ makefx recipes run <variant-id>
9587
+ makefx recipes run <variant-id> --json
9588
+
9589
+ Options:
9590
+ --space <id> Target space ID; defaults from the initialized project
9591
+ --json Print machine-readable output
9592
+ --env <env> Environment (production|stage|local)
9593
+ --local Shortcut for --env local
9594
+ `);
9595
+ }
9596
+ //#endregion
9399
9597
  //#region src/cli/commands/collections.ts
9400
9598
  var COLLECTION_KINDS = new Set([
9401
9599
  "cast",
@@ -9941,7 +10139,7 @@ Options:
9941
10139
  }
9942
10140
  //#endregion
9943
10141
  //#region src/cli/index.ts
9944
- var CLI_VERSION = "1.0.7+686298a71cee";
10142
+ var CLI_VERSION = "1.1.0+e479be18b9f5";
9945
10143
  async function main() {
9946
10144
  const argv = process$1.argv.slice(2);
9947
10145
  if (argv[0] === "--") argv.shift();
@@ -9984,14 +10182,19 @@ function imageSizeValues() {
9984
10182
  function imageAspectValues() {
9985
10183
  return optionValues(IMAGE_MODEL_CAPABILITIES["pro"].supportedAspectRatios);
9986
10184
  }
9987
- function imageCapabilityHelp() {
10185
+ function imageModelValues(operation) {
10186
+ return optionValues(IMAGE_MODEL_SELECTIONS.filter((model) => operation === void 0 || isImageOperationSupportedByModel(model, operation)));
10187
+ }
10188
+ function imageCapabilityHelp(operation) {
9988
10189
  const sizeLines = IMAGE_MODEL_SELECTIONS.map((model) => `${model}: ${IMAGE_MODEL_CAPABILITIES[model].supportedImageSizes.join(", ")}`).join("; ");
9989
10190
  const referenceLines = IMAGE_MODEL_SELECTIONS.map((model) => `${model}: ${IMAGE_MODEL_CAPABILITIES[model].maxReferenceImages}`).join("; ");
10191
+ const operationLines = IMAGE_MODEL_SELECTIONS.map((model) => `${model}: ${IMAGE_MODEL_CAPABILITIES[model].supportedOperations.join(", ")}`).join("; ");
9990
10192
  return `Image:
9991
- --model <value> Image model: ${optionValues(IMAGE_MODEL_SELECTIONS)}
10193
+ --model <value> Image model: ${imageModelValues(operation)}
9992
10194
  --size <value> Output size (${sizeLines})
9993
10195
  --aspect <ratio> Aspect ratio: ${imageAspectValues()}
9994
10196
  --refs <refs> Reference limit (${referenceLines})
10197
+ Model operations: ${operationLines}
9995
10198
  --follow <id> Resume/download a variant after a long generation or disconnect
9996
10199
  --collection <id> Place the completed asset in a Space collection`;
9997
10200
  }
@@ -10007,19 +10210,21 @@ function videoDurationValues() {
10007
10210
  function videoTierValues() {
10008
10211
  return optionValues(VIDEO_GENERATION_TIERS);
10009
10212
  }
10010
- function videoModelValues() {
10011
- return optionValues(VIDEO_MODEL_SELECTIONS);
10213
+ function videoModelValues(operation) {
10214
+ return optionValues(VIDEO_MODEL_SELECTIONS.filter((model) => operation === void 0 || VIDEO_MODEL_SUPPORTED_OPERATIONS[model].includes(operation)));
10012
10215
  }
10013
- function videoCapabilityHelp() {
10216
+ function videoCapabilityHelp(operation) {
10014
10217
  const resolutionLines = VIDEO_GENERATION_TIERS.map((tier) => `${tier}: ${getVideoGenerationResolutionsForTier(tier).join(", ")}`).join("; ");
10218
+ const operationLines = VIDEO_MODEL_SELECTIONS.map((model) => `${model}: ${VIDEO_MODEL_SUPPORTED_OPERATIONS[model].join(", ")}`).join("; ");
10015
10219
  return `Video:
10016
- --model <value> Video model: ${videoModelValues()}
10220
+ --model <value> Video model: ${videoModelValues(operation)}
10017
10221
  --aspect <ratio> Video aspect ratio: ${videoAspectValues()}
10018
- --resolution <value> Veo-only output resolution (${resolutionLines})
10019
- --duration <seconds> Veo-only output duration: ${videoDurationValues()}
10222
+ --resolution <value> Veo: ${videoResolutionValues()}; Kling/fal Seedance: 720p|1080p (${resolutionLines})
10223
+ --duration <seconds> Veo/Kling/fal Seedance output duration: ${videoDurationValues()}
10020
10224
  --tier <tier> Veo-only model tier: ${videoTierValues()}
10021
10225
  --first-frame <ref> Veo start frame image variant or local image path
10022
10226
  --last-frame <ref> Veo final frame image variant or local image path
10227
+ Model operations: ${operationLines}
10023
10228
  --follow <id> Resume/download a variant after a long generation or disconnect
10024
10229
  --collection <id> Place the completed asset in a Space collection
10025
10230
 
@@ -10102,6 +10307,10 @@ function printCommandHelp(command, positionals) {
10102
10307
  case "variant":
10103
10308
  printVariantsHelp();
10104
10309
  return;
10310
+ case "recipes":
10311
+ case "recipe":
10312
+ printRecipesHelp();
10313
+ return;
10105
10314
  default:
10106
10315
  console.error(`Unknown command: ${command}`);
10107
10316
  printHelp();
@@ -10128,6 +10337,7 @@ Generate:
10128
10337
  video generate "prompt" --name <name> --type animation -o <file>
10129
10338
 
10130
10339
  Continue:
10340
+ recipes run <variant-id> Re-run a stored recipe as a new sibling variant
10131
10341
  generate --follow <variant_id> -o <file>
10132
10342
  video generate --follow <variant_id> -o <file>
10133
10343
  audio <mode> generate --follow <variant_id> -o <file>
@@ -10281,10 +10491,10 @@ function printForgeHelp(command) {
10281
10491
  if (command === "generate") {
10282
10492
  console.log(`
10283
10493
  Usage:
10284
- makefx generate "prompt" --name <name> --type <type> -o <file> [--model ${optionValues(IMAGE_MODEL_SELECTIONS)}] [--size ${imageSizeValues()}] [--aspect <ratio>] [--collection <id>] [--space <id>]
10494
+ makefx generate "prompt" --name <name> --type <type> -o <file> [--model ${imageModelValues("generate")}] [--size ${imageSizeValues()}] [--aspect <ratio>] [--collection <id>] [--space <id>]
10285
10495
  makefx generate --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
10286
10496
 
10287
- ${imageCapabilityHelp()}
10497
+ ${imageCapabilityHelp("generate")}
10288
10498
 
10289
10499
  If the CLI stops waiting after a job has started, the job keeps running in Make Effects.
10290
10500
  Rerun the printed --follow command to resume the same variant instead of starting a duplicate.
@@ -10294,10 +10504,10 @@ Rerun the printed --follow command to resume the same variant instead of startin
10294
10504
  if (command === "refine") {
10295
10505
  console.log(`
10296
10506
  Usage:
10297
- makefx refine --variant <variant_id> "prompt" -o <file> [--model ${optionValues(IMAGE_MODEL_SELECTIONS)}] [--size ${imageSizeValues()}] [--aspect <ratio>] [--collection <id>] [--space <id>]
10507
+ makefx refine --variant <variant_id> "prompt" -o <file> [--model ${imageModelValues("refine")}] [--size ${imageSizeValues()}] [--aspect <ratio>] [--collection <id>] [--space <id>]
10298
10508
  makefx refine --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
10299
10509
 
10300
- ${imageCapabilityHelp()}
10510
+ ${imageCapabilityHelp("refine")}
10301
10511
 
10302
10512
  If the CLI stops waiting after a job has started, the job keeps running in Make Effects.
10303
10513
  Rerun the printed --follow command to resume the same variant instead of starting a duplicate.
@@ -10307,9 +10517,9 @@ Rerun the printed --follow command to resume the same variant instead of startin
10307
10517
  if (command === "batch") {
10308
10518
  console.log(`
10309
10519
  Usage:
10310
- makefx batch "prompt" --name <name> --type <type> --count <2-8> --output-dir <dir> [--model ${optionValues(IMAGE_MODEL_SELECTIONS)}] [--size ${imageSizeValues()}] [--aspect <ratio>] [--collection <id>]
10520
+ makefx batch "prompt" --name <name> --type <type> --count <2-8> --output-dir <dir> [--model ${imageModelValues("generate")}] [--size ${imageSizeValues()}] [--aspect <ratio>] [--collection <id>]
10311
10521
 
10312
- ${imageCapabilityHelp()}
10522
+ ${imageCapabilityHelp("generate")}
10313
10523
 
10314
10524
  Batch creates several variants. If waiting stops, inspect the Space or download completed variants with:
10315
10525
  makefx assets download <variant_id> -o <file>
@@ -10318,10 +10528,10 @@ Batch creates several variants. If waiting stops, inspect the Space or download
10318
10528
  }
10319
10529
  console.log(`
10320
10530
  Usage:
10321
- makefx derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--model ${optionValues(IMAGE_MODEL_SELECTIONS)}] [--size ${imageSizeValues()}] [--aspect <ratio>] [--collection <id>] [--space <id>]
10531
+ makefx derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--model ${imageModelValues("derive")}] [--size ${imageSizeValues()}] [--aspect <ratio>] [--collection <id>] [--space <id>]
10322
10532
  makefx derive --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
10323
10533
 
10324
- ${imageCapabilityHelp()}
10534
+ ${imageCapabilityHelp("derive")}
10325
10535
 
10326
10536
  If the CLI stops waiting after a job has started, the job keeps running in Make Effects.
10327
10537
  Rerun the printed --follow command to resume the same variant instead of starting a duplicate.
@@ -10433,13 +10643,14 @@ function printVideoHelp(positionals) {
10433
10643
  if (subcommand === "generate") {
10434
10644
  console.log(`
10435
10645
  Usage:
10436
- makefx video generate "prompt" --name <name> --type <type> -o <file> [--model ${videoModelValues()}] [--first-frame <variant_or_file>] [--last-frame <variant_or_file>] [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--collection <id>] [--space <id>]
10646
+ makefx video generate "prompt" --name <name> --type <type> -o <file> [--model ${videoModelValues("generate")}] [--first-frame <variant_or_file>] [--last-frame <variant_or_file>] [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--collection <id>] [--space <id>]
10437
10647
  makefx video generate --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
10438
10648
 
10439
- ${videoCapabilityHelp()}
10649
+ ${videoCapabilityHelp("generate")}
10440
10650
 
10441
10651
  Audio:
10442
- Video defaults to generated audio. Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
10652
+ Veo and Kling default to generated audio. fal Seedance is silent and rejects --audio.
10653
+ Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
10443
10654
 
10444
10655
  Long runs:
10445
10656
  If the CLI stops waiting after a job has started, the job keeps running in Make Effects.
@@ -10450,13 +10661,13 @@ Long runs:
10450
10661
  if (subcommand === "refine") {
10451
10662
  console.log(`
10452
10663
  Usage:
10453
- makefx video refine --variant <variant_id> "prompt" -o <file> [--model ${videoModelValues()}] [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--collection <id>] [--space <id>]
10664
+ makefx video refine --variant <variant_id> "prompt" -o <file> [--model ${videoModelValues("refine")}] [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--collection <id>] [--space <id>]
10454
10665
  makefx video refine --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
10455
10666
 
10456
- ${videoCapabilityHelp()}
10667
+ ${videoCapabilityHelp("refine")}
10457
10668
 
10458
10669
  Audio:
10459
- Video defaults to generated audio. Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
10670
+ Veo and Kling default to generated audio. Current Veo models do not support --no-audio.
10460
10671
 
10461
10672
  Long runs:
10462
10673
  If the CLI stops waiting after a job has started, the job keeps running in Make Effects.
@@ -10467,14 +10678,14 @@ Long runs:
10467
10678
  if (subcommand === "derive") {
10468
10679
  console.log(`
10469
10680
  Usage:
10470
- makefx video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--model ${videoModelValues()}] [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--collection <id>] [--space <id>]
10681
+ makefx video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--model ${videoModelValues("derive")}] [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--collection <id>] [--space <id>]
10471
10682
  makefx video derive --first-frame <variant_or_file> [--last-frame <variant_or_file>] --name <name> --type <type> "prompt" -o <file> [--model veo-3.1] [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--collection <id>] [--space <id>]
10472
10683
  makefx video derive --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
10473
10684
 
10474
- ${videoCapabilityHelp()}
10685
+ ${videoCapabilityHelp("derive")}
10475
10686
 
10476
10687
  Audio:
10477
- Video defaults to generated audio. Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
10688
+ Veo and Kling default to generated audio. Current Veo models do not support --no-audio.
10478
10689
 
10479
10690
  Long runs:
10480
10691
  If the CLI stops waiting after a job has started, the job keeps running in Make Effects.
@@ -10493,7 +10704,8 @@ Usage:
10493
10704
  ${videoCapabilityHelp()}
10494
10705
 
10495
10706
  Audio:
10496
- Video defaults to generated audio. Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
10707
+ Veo and Kling default to generated audio. fal Seedance is silent and generate-only.
10708
+ Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
10497
10709
 
10498
10710
  Long runs:
10499
10711
  If the CLI stops waiting after a job has started, the job keeps running in Make Effects.
@@ -10532,6 +10744,21 @@ Options:
10532
10744
  --local Shortcut for --env local
10533
10745
  `);
10534
10746
  }
10747
+ function printRecipesHelp() {
10748
+ console.log(`
10749
+ Usage:
10750
+ makefx recipes run <variant-id>
10751
+ makefx recipes run <variant-id> --json
10752
+
10753
+ Re-runs the stored generation recipe as a new sibling variant of the same asset.
10754
+
10755
+ Options:
10756
+ --space <id> Target space ID; defaults from the initialized project
10757
+ --json Print machine-readable output
10758
+ --env <env> Environment (production|stage|local)
10759
+ --local Shortcut for --env local
10760
+ `);
10761
+ }
10535
10762
  function printAssetsHelp() {
10536
10763
  console.log(`
10537
10764
  Usage:
@@ -10663,6 +10890,10 @@ async function dispatchCommand(command, parsed) {
10663
10890
  case "variant":
10664
10891
  await handleVariants(parsed);
10665
10892
  break;
10893
+ case "recipes":
10894
+ case "recipe":
10895
+ await handleRecipes(parsed);
10896
+ break;
10666
10897
  default:
10667
10898
  console.error(`Unknown command: ${command}`);
10668
10899
  printHelp();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makefx",
3
- "version": "1.0.7",
3
+ "version": "1.1.0",
4
4
  "description": "Command-line interface for AI-assisted game asset production with Make Effects.",
5
5
  "license": "MIT",
6
6
  "type": "module",