makefx 1.1.0 → 1.2.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 +89 -180
  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.1.0
179
+ Version: 1.2.0
package/makefx.mjs CHANGED
@@ -5916,6 +5916,9 @@ var ServerConfirmationTimeoutError = class extends Error {
5916
5916
  this.name = "ServerConfirmationTimeoutError";
5917
5917
  }
5918
5918
  };
5919
+ function booleanFromSqlite(value) {
5920
+ return value === true || value === 1;
5921
+ }
5919
5922
  function collectionItemMatchesInput(item, input) {
5920
5923
  if (item.subject_type !== input.subjectType) return false;
5921
5924
  if (input.subjectType === "asset" && item.asset_id !== input.assetId) return false;
@@ -5935,7 +5938,6 @@ var WebSocketClient = class WebSocketClient {
5935
5938
  chatHandlers = /* @__PURE__ */ new Map();
5936
5939
  generateHandlers = /* @__PURE__ */ new Map();
5937
5940
  batchHandlers = /* @__PURE__ */ new Map();
5938
- estimateHandlers = /* @__PURE__ */ new Map();
5939
5941
  batchVariantToRequestId = /* @__PURE__ */ new Map();
5940
5942
  variantCompletionHandlers = /* @__PURE__ */ new Map();
5941
5943
  describeHandlers = /* @__PURE__ */ new Map();
@@ -6131,16 +6133,6 @@ var WebSocketClient = class WebSocketClient {
6131
6133
  }
6132
6134
  break;
6133
6135
  }
6134
- case "generation:estimate": {
6135
- const estimateMsg = message;
6136
- const handler = this.estimateHandlers.get(estimateMsg.requestId);
6137
- if (handler) {
6138
- this.estimateHandlers.delete(estimateMsg.requestId);
6139
- clearTimeout(handler.timeout);
6140
- handler.resolve(estimateMsg);
6141
- }
6142
- break;
6143
- }
6144
6136
  case "variant:updated": {
6145
6137
  const variant = message.variant;
6146
6138
  const batchRequestId = this.batchVariantToRequestId.get(variant.id);
@@ -6296,13 +6288,6 @@ var WebSocketClient = class WebSocketClient {
6296
6288
  return true;
6297
6289
  }
6298
6290
  failRequestHandler(requestId, error) {
6299
- const estimateHandler = this.estimateHandlers.get(requestId);
6300
- if (estimateHandler) {
6301
- this.estimateHandlers.delete(requestId);
6302
- clearTimeout(estimateHandler.timeout);
6303
- estimateHandler.reject(error);
6304
- return true;
6305
- }
6306
6291
  const generateHandler = this.generateHandlers.get(requestId);
6307
6292
  if (generateHandler) {
6308
6293
  this.generateHandlers.delete(requestId);
@@ -6395,11 +6380,15 @@ var WebSocketClient = class WebSocketClient {
6395
6380
  }
6396
6381
  /** Star or unstar a variant. Resolves with the updated variant. */
6397
6382
  async starVariant(variantId, starred) {
6398
- return (await this.awaitServerMessage({
6383
+ const result = await this.awaitServerMessage({
6399
6384
  type: "variant:star",
6400
6385
  variantId,
6401
6386
  starred
6402
- }, (msg) => msg.type === "variant:updated" && msg.variant.id === variantId && msg.variant.starred === starred)).variant;
6387
+ }, (msg) => msg.type === "variant:updated" && msg.variant.id === variantId && booleanFromSqlite(msg.variant.starred) === starred);
6388
+ return {
6389
+ ...result.variant,
6390
+ starred: booleanFromSqlite(result.variant.starred)
6391
+ };
6403
6392
  }
6404
6393
  /** Rate a variant (approved/rejected). Resolves with the updated variant. */
6405
6394
  async rateVariant(variantId, rating) {
@@ -6484,47 +6473,6 @@ var WebSocketClient = class WebSocketClient {
6484
6473
  }, 12e4);
6485
6474
  });
6486
6475
  }
6487
- async sendGenerationEstimateRequest(params) {
6488
- const requestId = crypto.randomUUID();
6489
- return new Promise((resolve, reject) => {
6490
- const timeout = setTimeout(() => {
6491
- if (this.estimateHandlers.has(requestId)) {
6492
- this.estimateHandlers.delete(requestId);
6493
- reject(/* @__PURE__ */ new Error("Generation estimate request timed out"));
6494
- }
6495
- }, 3e4);
6496
- this.estimateHandlers.set(requestId, {
6497
- resolve,
6498
- reject,
6499
- timeout
6500
- });
6501
- const message = {
6502
- type: "generation:estimate",
6503
- requestId,
6504
- operation: params.operation,
6505
- assetId: params.assetId,
6506
- assetType: params.assetType,
6507
- mediaKind: params.mediaKind,
6508
- prompt: params.prompt,
6509
- count: params.count,
6510
- model: params.model,
6511
- aspectRatio: params.aspectRatio,
6512
- imageSize: params.imageSize,
6513
- musicProvider: params.musicProvider,
6514
- generateAudio: params.generateAudio,
6515
- videoResolution: params.videoResolution,
6516
- videoDurationSeconds: params.videoDurationSeconds,
6517
- videoTier: params.videoTier
6518
- };
6519
- try {
6520
- this.send(message);
6521
- } catch (err) {
6522
- this.estimateHandlers.delete(requestId);
6523
- clearTimeout(timeout);
6524
- reject(err);
6525
- }
6526
- });
6527
- }
6528
6476
  /**
6529
6477
  * Send a generate request and wait for result
6530
6478
  */
@@ -6832,12 +6780,27 @@ var VIDEO_GENERATION_RESOLUTIONS = [
6832
6780
  "1080p",
6833
6781
  "4k"
6834
6782
  ];
6783
+ var ALL_VIDEO_GENERATION_RESOLUTIONS = ["480p", ...VIDEO_GENERATION_RESOLUTIONS];
6835
6784
  var KLING_VIDEO_GENERATION_RESOLUTIONS = ["720p", "1080p"];
6836
6785
  var VIDEO_GENERATION_DURATION_SECONDS = [
6837
6786
  4,
6838
6787
  6,
6839
6788
  8
6840
6789
  ];
6790
+ var SEEDANCE_2_DURATION_SECONDS = [
6791
+ 4,
6792
+ 5,
6793
+ 6,
6794
+ 7,
6795
+ 8,
6796
+ 9,
6797
+ 10,
6798
+ 11,
6799
+ 12,
6800
+ 13,
6801
+ 14,
6802
+ 15
6803
+ ];
6841
6804
  var VIDEO_GENERATION_TIERS = [
6842
6805
  "generate",
6843
6806
  "fast",
@@ -6847,7 +6810,9 @@ var VIDEO_MODEL_SELECTIONS = [
6847
6810
  "veo-3.1",
6848
6811
  "omni-flash",
6849
6812
  "kling",
6850
- "fal-seedance"
6813
+ "fal-seedance",
6814
+ "seedance-2",
6815
+ "seedance-2-fast"
6851
6816
  ];
6852
6817
  var VIDEO_MODEL_SUPPORTED_OPERATIONS = {
6853
6818
  "veo-3.1": [
@@ -6865,10 +6830,14 @@ var VIDEO_MODEL_SUPPORTED_OPERATIONS = {
6865
6830
  "refine",
6866
6831
  "derive"
6867
6832
  ],
6868
- "fal-seedance": ["generate"]
6833
+ "fal-seedance": ["generate"],
6834
+ "seedance-2": ["generate", "derive"],
6835
+ "seedance-2-fast": ["generate", "derive"]
6869
6836
  };
6870
6837
  var KLING_VIDEO_MODEL = "kling-v3";
6871
6838
  var FAL_VIDEO_MODEL = "fal-ai/bytedance/seedance/v1/pro/text-to-video";
6839
+ var FAL_SEEDANCE_2_MODEL = "bytedance/seedance-2.0/image-to-video";
6840
+ var FAL_SEEDANCE_2_FAST_MODEL = "bytedance/seedance-2.0/fast/image-to-video";
6872
6841
  var GEMINI_OMNI_FLASH_VIDEO_MODEL = "gemini-omni-flash-preview";
6873
6842
  var VIDEO_GENERATION_AUDIO_TOGGLE_MODELS = [];
6874
6843
  var VIDEO_GENERATION_RESOLUTIONS_BY_TIER = {
@@ -6887,11 +6856,11 @@ var VIDEO_GENERATION_TIER_MODELS = {
6887
6856
  lite: "veo-3.1-lite-generate-preview"
6888
6857
  };
6889
6858
  function normalizeVideoGenerationResolution(value) {
6890
- return VIDEO_GENERATION_RESOLUTIONS.includes(value) ? value : void 0;
6859
+ return ALL_VIDEO_GENERATION_RESOLUTIONS.includes(value) ? value : void 0;
6891
6860
  }
6892
6861
  function normalizeVideoGenerationDurationSeconds(value) {
6893
6862
  const numeric = typeof value === "string" ? Number(value) : value;
6894
- return VIDEO_GENERATION_DURATION_SECONDS.includes(numeric) ? numeric : void 0;
6863
+ return SEEDANCE_2_DURATION_SECONDS.includes(numeric) ? numeric : void 0;
6895
6864
  }
6896
6865
  function normalizeVideoGenerationTier(value) {
6897
6866
  return VIDEO_GENERATION_TIERS.includes(value) ? value : void 0;
@@ -6906,6 +6875,8 @@ function getVideoGenerationModelForSelection(selection = DEFAULT_VIDEO_MODEL_SEL
6906
6875
  if (selection === "omni-flash") return GEMINI_OMNI_FLASH_VIDEO_MODEL;
6907
6876
  if (selection === "kling") return KLING_VIDEO_MODEL;
6908
6877
  if (selection === "fal-seedance") return FAL_VIDEO_MODEL;
6878
+ if (selection === "seedance-2") return FAL_SEEDANCE_2_MODEL;
6879
+ if (selection === "seedance-2-fast") return FAL_SEEDANCE_2_FAST_MODEL;
6909
6880
  return getVideoGenerationModelForTier(tier);
6910
6881
  }
6911
6882
  function getVideoGenerationResolutionsForTier(tier = DEFAULT_VIDEO_GENERATION_TIER) {
@@ -6915,7 +6886,14 @@ function isVideoGenerationResolutionSupportedForTier(resolution, tier = DEFAULT_
6915
6886
  return VIDEO_GENERATION_RESOLUTIONS_BY_TIER[tier].includes(resolution);
6916
6887
  }
6917
6888
  function getVideoGenerationResolutionsForModel(model) {
6918
- return isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model) ? KLING_VIDEO_GENERATION_RESOLUTIONS : getVideoGenerationResolutionsForTier(getVideoGenerationTierForModel(model));
6889
+ if (isKlingVideoGenerationModel(model) || isFalSeedanceV1VideoGenerationModel(model)) return KLING_VIDEO_GENERATION_RESOLUTIONS;
6890
+ if (model === "bytedance/seedance-2.0/fast/image-to-video") return ["480p", "720p"];
6891
+ if (isFalSeedance2VideoGenerationModel(model)) return [
6892
+ "480p",
6893
+ "720p",
6894
+ "1080p"
6895
+ ];
6896
+ return getVideoGenerationResolutionsForTier(getVideoGenerationTierForModel(model));
6919
6897
  }
6920
6898
  function isVideoGenerationResolutionSupportedForModel(model, resolution) {
6921
6899
  return getVideoGenerationResolutionsForModel(model).includes(resolution);
@@ -6928,6 +6906,8 @@ function getVideoModelSelectionForModel(model) {
6928
6906
  if (model === "gemini-omni-flash-preview") return "omni-flash";
6929
6907
  if (model === "kling-v3") return "kling";
6930
6908
  if (model === "fal-ai/bytedance/seedance/v1/pro/text-to-video") return "fal-seedance";
6909
+ if (model === "bytedance/seedance-2.0/image-to-video") return "seedance-2";
6910
+ if (model === "bytedance/seedance-2.0/fast/image-to-video") return "seedance-2-fast";
6931
6911
  return getVideoGenerationTierForModel(model) ? "veo-3.1" : void 0;
6932
6912
  }
6933
6913
  function isVeoVideoGenerationModel(model) {
@@ -6940,8 +6920,14 @@ function isKlingVideoGenerationModel(model) {
6940
6920
  return model === KLING_VIDEO_MODEL;
6941
6921
  }
6942
6922
  function isFalVideoGenerationModel(model) {
6923
+ return isFalSeedanceV1VideoGenerationModel(model) || isFalSeedance2VideoGenerationModel(model);
6924
+ }
6925
+ function isFalSeedanceV1VideoGenerationModel(model) {
6943
6926
  return model === FAL_VIDEO_MODEL;
6944
6927
  }
6928
+ function isFalSeedance2VideoGenerationModel(model) {
6929
+ return model === "bytedance/seedance-2.0/image-to-video" || model === "bytedance/seedance-2.0/fast/image-to-video";
6930
+ }
6945
6931
  function isVideoGenerationModel(model) {
6946
6932
  return isVeoVideoGenerationModel(model) || isGeminiOmniVideoGenerationModel(model) || isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model);
6947
6933
  }
@@ -7022,7 +7008,7 @@ var IMAGE_MODEL_CAPABILITIES = {
7022
7008
  flux: {
7023
7009
  selection: "flux",
7024
7010
  modelId: IMAGE_MODEL_IDS.flux,
7025
- label: "FLUX.1 Dev",
7011
+ label: "fal.ai FLUX.1 Dev",
7026
7012
  provider: "fal",
7027
7013
  supportedOperations: ["generate"],
7028
7014
  maxReferenceImages: 0,
@@ -7248,43 +7234,6 @@ var defaultDeps$9 = {
7248
7234
  }
7249
7235
  }
7250
7236
  };
7251
- var ESTIMATE_METER_LABELS = {
7252
- gemini_images: "Gemini image",
7253
- gemini_videos: "Veo video unit",
7254
- gemini_audio: "Lyria generation",
7255
- elevenlabs_audio: "ElevenLabs unit"
7256
- };
7257
- function formatEstimatedUsd(microUsd) {
7258
- if (!Number.isFinite(microUsd) || microUsd <= 0) return "$0.00";
7259
- if (microUsd < 1e4) return "<$0.01";
7260
- return `$${(microUsd / 1e6).toFixed(2)}`;
7261
- }
7262
- function formatEstimateQuantity(quantity, singular) {
7263
- const normalized = Number.isFinite(quantity) ? quantity : 0;
7264
- const suffix = normalized === 1 ? singular : `${singular}s`;
7265
- return `${normalized.toLocaleString()} ${suffix}`;
7266
- }
7267
- async function printPreflightEstimate(client, params) {
7268
- let result;
7269
- try {
7270
- result = await client.sendGenerationEstimateRequest(params);
7271
- } catch (error) {
7272
- console.warn(`Preflight estimate unavailable: ${error instanceof Error ? error.message : String(error)}`);
7273
- return;
7274
- }
7275
- if (!result.success || !result.estimate) {
7276
- console.warn(`Preflight estimate unavailable: ${result.error || "unknown error"}`);
7277
- return;
7278
- }
7279
- const estimate = result.estimate;
7280
- const meterLabel = ESTIMATE_METER_LABELS[estimate.meterEventName] ?? estimate.meterEventName;
7281
- const quotaLine = estimate.quota?.limit === null || estimate.quota?.limit === void 0 ? void 0 : `${estimate.quota.used.toLocaleString()} used / ${estimate.quota.limit.toLocaleString()} limit`;
7282
- console.log("Preflight estimate:");
7283
- console.log(` Usage: ${formatEstimateQuantity(estimate.quotaQuantity, meterLabel)}, ${formatEstimateQuantity(estimate.platformWorkflowRuns, "workflow")}`);
7284
- console.log(` Estimated provider cost: ${formatEstimatedUsd(estimate.providerCostMicroUsd)}${estimate.billingMode === "byok" ? " (BYOK)" : ""}`);
7285
- if (quotaLine) console.log(` Quota: ${quotaLine}`);
7286
- if (!estimate.allowed) throw new Error(estimate.denyMessage || "Preflight check denied this generation request");
7287
- }
7288
7237
  async function handleGenerate(parsed) {
7289
7238
  await handleForgeCommand("generate", parsed);
7290
7239
  }
@@ -7405,25 +7354,12 @@ async function executeGenerate(parsed, ctx, client, deps, mediaKind, followOptio
7405
7354
  const videoOptions = parseVideoGenerationOptions(parsed, mediaKind);
7406
7355
  const effectiveVideoModel = videoOptions.model ?? getVideoGenerationModelForSelection();
7407
7356
  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`);
7357
+ if (mediaKind === "video" && isFalVideoGenerationModel(effectiveVideoModel) && !isFalSeedance2VideoGenerationModel(effectiveVideoModel) && videoFrameRefs.length > 0) throw new Error(`--model ${getVideoModelSelectionForModel(effectiveVideoModel) ?? effectiveVideoModel} does not support image references`);
7409
7358
  const collectionPlacement = parseCollectionPlacementOptions(parsed);
7410
7359
  const followCommandOptions = {
7411
7360
  ...followOptions,
7412
7361
  ...collectionPlacement
7413
7362
  };
7414
- await printPreflightEstimate(client, {
7415
- operation: "generate",
7416
- assetType,
7417
- mediaKind,
7418
- prompt,
7419
- count: 1,
7420
- model: imageOptions.model ?? audioModelOptions.model ?? videoOptions.model,
7421
- aspectRatio: imageOptions.aspectRatio ?? videoOptions.aspectRatio,
7422
- imageSize: imageOptions.imageSize,
7423
- ...musicProvider ? { musicProvider } : {},
7424
- ...videoAudioOptions,
7425
- ...videoOptions
7426
- });
7427
7363
  console.log(`Generating "${name}" in space ${ctx.spaceId}...`);
7428
7364
  const audioVoiceOptions = mediaKind === "audio" ? parseAudioVoiceOptions(parsed) : {};
7429
7365
  let startedVariantId;
@@ -7509,19 +7445,6 @@ async function executeRefine(parsed, ctx, client, deps, mediaKind) {
7509
7445
  const videoOptions = parseVideoGenerationOptions(parsed, mediaKind);
7510
7446
  const collectionPlacement = parseCollectionPlacementOptions(parsed);
7511
7447
  const followCommandOptions = { ...collectionPlacement };
7512
- await printPreflightEstimate(client, {
7513
- operation: "refine",
7514
- assetId: sourceVariant.asset_id,
7515
- assetType: sourceAsset?.type || void 0,
7516
- mediaKind,
7517
- prompt,
7518
- count: 1,
7519
- model: imageOptions.model ?? videoOptions.model,
7520
- aspectRatio: imageOptions.aspectRatio ?? videoOptions.aspectRatio,
7521
- imageSize: imageOptions.imageSize,
7522
- ...videoAudioOptions,
7523
- ...videoOptions
7524
- });
7525
7448
  console.log(`Refining variant ${sourceVariantId}...`);
7526
7449
  let startedVariantId;
7527
7450
  let result;
@@ -7586,24 +7509,12 @@ async function executeDerive(parsed, ctx, client, deps, mediaKind, followOptions
7586
7509
  const videoOptions = parseVideoGenerationOptions(parsed, mediaKind);
7587
7510
  const effectiveVideoModel = videoOptions.model ?? getVideoGenerationModelForSelection();
7588
7511
  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`);
7512
+ if (mediaKind === "video" && isFalVideoGenerationModel(effectiveVideoModel) && !isFalSeedance2VideoGenerationModel(effectiveVideoModel) && referenceRefs.length > 0) throw new Error(`--model ${getVideoModelSelectionForModel(effectiveVideoModel) ?? effectiveVideoModel} does not support ${referenceRefs.length} image references`);
7590
7513
  const collectionPlacement = parseCollectionPlacementOptions(parsed);
7591
7514
  const followCommandOptions = {
7592
7515
  ...followOptions,
7593
7516
  ...collectionPlacement
7594
7517
  };
7595
- await printPreflightEstimate(client, {
7596
- operation: "derive",
7597
- assetType,
7598
- mediaKind,
7599
- prompt,
7600
- count: 1,
7601
- model: imageOptions.model ?? videoOptions.model,
7602
- aspectRatio: imageOptions.aspectRatio ?? videoOptions.aspectRatio,
7603
- imageSize: imageOptions.imageSize,
7604
- ...videoAudioOptions,
7605
- ...videoOptions
7606
- });
7607
7518
  console.log(`Deriving "${name}" from ${referenceVariantIds.length} reference(s)...`);
7608
7519
  let startedVariantId;
7609
7520
  let result;
@@ -7816,17 +7727,6 @@ async function executeBatch(parsed, ctx, client, deps, mediaKind, saveBatchManif
7816
7727
  const startedAt = (/* @__PURE__ */ new Date()).toISOString();
7817
7728
  const runId = deps.createRunId();
7818
7729
  const collectionPlacement = parseCollectionPlacementOptions(parsed);
7819
- await printPreflightEstimate(client, {
7820
- operation: "batch",
7821
- assetType,
7822
- mediaKind,
7823
- prompt,
7824
- count,
7825
- model: imageOptions.model ?? audioModelOptions.model,
7826
- aspectRatio: imageOptions.aspectRatio,
7827
- imageSize: imageOptions.imageSize,
7828
- ...musicProvider ? { musicProvider } : {}
7829
- });
7830
7730
  console.log(`Batch generating ${count} ${mediaKind === "image" ? "image" : mediaKind === "video" ? "video" : "audio file"}(s) for "${name}"...`);
7831
7731
  const audioVoiceOptions = mediaKind === "audio" ? parseAudioVoiceOptions(parsed) : {};
7832
7732
  let startedBatch;
@@ -8309,16 +8209,21 @@ function parseVideoGenerationOptions(parsed, mediaKind) {
8309
8209
  if (mediaKind !== "video" && resolutionValue === void 0 && durationValue === void 0 && tierValue === void 0 && aspectValue === void 0) return {};
8310
8210
  if (mediaKind !== "video") throw new Error("--resolution, --duration, and --tier are only supported for video generation");
8311
8211
  const videoResolution = resolutionValue === void 0 ? void 0 : normalizeVideoGenerationResolution(resolutionValue);
8312
- if (resolutionValue !== void 0 && !videoResolution) throw new Error("--resolution must be 720p, 1080p, or 4k");
8212
+ if (resolutionValue !== void 0 && !videoResolution) throw new Error("--resolution must be 480p, 720p, 1080p, or 4k");
8313
8213
  const videoDurationSeconds = durationValue === void 0 ? void 0 : normalizeVideoGenerationDurationSeconds(durationValue);
8314
- if (durationValue !== void 0 && !videoDurationSeconds) throw new Error("--duration must be 4, 6, or 8");
8214
+ if (durationValue !== void 0 && !videoDurationSeconds) throw new Error("--duration must be an integer from 4 to 15");
8315
8215
  const videoTier = tierValue === void 0 ? void 0 : normalizeVideoGenerationTier(tierValue);
8316
8216
  if (tierValue !== void 0 && !videoTier) throw new Error("--tier must be generate, fast, or lite");
8317
8217
  const model = parseVideoModelOption(modelValue, videoTier);
8318
8218
  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
8219
  if ((isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model)) && tierValue !== void 0) throw new Error("--tier is only supported with --model veo-3.1");
8320
8220
  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`);
8221
+ if (videoResolution && (isKlingVideoGenerationModel(model) || isFalVideoGenerationModel(model)) && !isVideoGenerationResolutionSupportedForModel(model, videoResolution)) throw new Error(`--model ${getVideoModelSelectionForModel(model) ?? model} does not support --resolution ${videoResolution}`);
8222
+ if (!isFalSeedance2VideoGenerationModel(model) && videoDurationSeconds && ![
8223
+ 4,
8224
+ 6,
8225
+ 8
8226
+ ].includes(videoDurationSeconds)) throw new Error("--duration must be 4, 6, or 8 for this model");
8322
8227
  const aspectRatio = aspectValue === void 0 ? void 0 : normalizeVideoGenerationAspectRatio(aspectValue);
8323
8228
  if (aspectValue !== void 0 && !aspectRatio) throw new Error("--aspect must be 16:9 or 9:16");
8324
8229
  return {
@@ -8346,7 +8251,8 @@ function validateVideoFrameReferenceOptions(command, parsed, mediaKind) {
8346
8251
  const tierValue = readOptionalOption(parsed, "tier", "tier") ?? readOptionalOption(parsed, "video-tier", "videoTier");
8347
8252
  const videoTier = tierValue === void 0 ? void 0 : normalizeVideoGenerationTier(tierValue);
8348
8253
  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");
8254
+ if (isFalSeedance2VideoGenerationModel(model) && !firstFrame) throw new Error("--model seedance-2 requires --first-frame");
8255
+ if (!isFalSeedance2VideoGenerationModel(model) && (isFalVideoGenerationModel(model) || isGeminiOmniVideoGenerationModel(model) || isKlingVideoGenerationModel(model) && Boolean(lastFrame))) throw new Error("--first-frame and --last-frame are only supported with --model veo-3.1 or seedance-2");
8350
8256
  }
8351
8257
  function readVideoFrameOption(parsed, kebabName, camelName) {
8352
8258
  const value = parsed.options[kebabName] ?? parsed.options[camelName];
@@ -8669,8 +8575,8 @@ function parseVideoCommand(value) {
8669
8575
  }
8670
8576
  function printUsage$7() {
8671
8577
  const aspectValues = VIDEO_GENERATION_ASPECT_RATIOS.join("|");
8672
- const resolutionValues = Array.from(new Set(VIDEO_GENERATION_TIERS.flatMap((tier) => getVideoGenerationResolutionsForTier(tier)))).join("|");
8673
- const durationValues = VIDEO_GENERATION_DURATION_SECONDS.join("|");
8578
+ const resolutionValues = Array.from(new Set(["480p", ...VIDEO_GENERATION_TIERS.flatMap((tier) => getVideoGenerationResolutionsForTier(tier))])).join("|");
8579
+ const durationValues = Array.from(new Set([...VIDEO_GENERATION_DURATION_SECONDS, ...SEEDANCE_2_DURATION_SECONDS])).join("|");
8674
8580
  const tierValues = VIDEO_GENERATION_TIERS.join("|");
8675
8581
  const modelValues = (operation) => VIDEO_MODEL_SELECTIONS.filter((model) => VIDEO_MODEL_SUPPORTED_OPERATIONS[model].includes(operation)).join("|");
8676
8582
  const resolutionByTier = VIDEO_GENERATION_TIERS.map((tier) => `${tier}: ${getVideoGenerationResolutionsForTier(tier).join(", ")}`).join("; ");
@@ -8681,21 +8587,22 @@ Usage:
8681
8587
  makefx video refine --variant <variant_id> "prompt" -o <file> [--model ${modelValues("refine")}] [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
8682
8588
  makefx video refine --follow <variant_id> -o <file> [--space <id>]
8683
8589
  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>]
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>]
8590
+ makefx video derive --first-frame <variant_or_file> [--last-frame <variant_or_file>] --name <name> --type <type> "prompt" -o <file> [--model veo-3.1|seedance-2|seedance-2-fast] [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
8685
8591
  makefx video derive --follow <variant_id> -o <file> [--space <id>]
8686
8592
 
8687
8593
  Video:
8688
8594
  --model <value> Generate: ${modelValues("generate")}; refine/derive: ${modelValues("refine")}
8689
8595
  --aspect <ratio> Video aspect ratio: ${aspectValues}
8690
- --resolution <value> Veo: ${resolutionValues}; Kling/fal Seedance: 720p|1080p (${resolutionByTier})
8691
- --duration <seconds> Veo/Kling/fal Seedance output duration: ${durationValues}
8596
+ --resolution <value> Supported: ${resolutionValues}; Veo: 720p|1080p|4k; Kling: 720p|1080p; Seedance 2: standard 480p|720p|1080p, fast 480p|720p (${resolutionByTier})
8597
+ --duration <seconds> Veo/Kling: ${VIDEO_GENERATION_DURATION_SECONDS.join("|")}; Seedance 2: ${SEEDANCE_2_DURATION_SECONDS.join("|")}
8692
8598
  --tier <tier> Veo-only model tier: ${tierValues}
8693
- --first-frame <ref> Veo start frame image variant or local image path
8694
- --last-frame <ref> Veo final frame image variant or local image path
8599
+ --first-frame <ref> Veo or Seedance 2 start frame image variant or local image path
8600
+ --last-frame <ref> Veo or Seedance 2 final frame image variant or local image path
8695
8601
 
8696
- Veo 3.1 frames:
8602
+ Frame inputs:
8697
8603
  --first-frame resolves to the first referenceVariantId and becomes the Veo top-level image input.
8698
- --last-frame resolves to the second referenceVariantId and becomes Veo config.lastFrame.
8604
+ --last-frame resolves to the second referenceVariantId and becomes Veo config.lastFrame or Seedance 2 end_image_url.
8605
+ Seedance 2 requires --first-frame and supports an optional --last-frame.
8699
8606
  Use both flags together for first/last-frame generation; --last-frame requires --first-frame.
8700
8607
  Do not combine frame flags with --refs. Use --refs when you want generic Veo reference images instead of first/last-frame inputs.
8701
8608
 
@@ -9910,6 +9817,7 @@ function printUsageSummary(summary, print) {
9910
9817
  print(` Storage: ${formatBytes(summary.totals.storageBytes)}`);
9911
9818
  print(` Workflow runs: ${summary.totals.workflowRuns}`);
9912
9819
  print(` Delivery: ${formatBytes(summary.totals.deliveryBytes)}`);
9820
+ print(` Provider spend: $${summary.providerSpend.amountUsd.toFixed(6)} (${summary.providerSpend.entries} recorded entr${summary.providerSpend.entries === 1 ? "y" : "ies"}, ${summary.providerSpend.unpricedEntries} unpriced)`);
9913
9821
  if (summary.byMediaKind.length > 0) {
9914
9822
  print("\nBy media kind:");
9915
9823
  print("Media".padEnd(10) + "Storage".padEnd(14) + "Workflows".padEnd(12) + "Delivery".padEnd(14) + "Events");
@@ -10139,7 +10047,7 @@ Options:
10139
10047
  }
10140
10048
  //#endregion
10141
10049
  //#region src/cli/index.ts
10142
- var CLI_VERSION = "1.1.0+e479be18b9f5";
10050
+ var CLI_VERSION = "1.2.0+10cb109b7379";
10143
10051
  async function main() {
10144
10052
  const argv = process$1.argv.slice(2);
10145
10053
  if (argv[0] === "--") argv.shift();
@@ -10199,13 +10107,13 @@ function imageCapabilityHelp(operation) {
10199
10107
  --collection <id> Place the completed asset in a Space collection`;
10200
10108
  }
10201
10109
  function videoResolutionValues() {
10202
- return optionValues(uniqueValues(VIDEO_GENERATION_TIERS.flatMap((tier) => getVideoGenerationResolutionsForTier(tier))));
10110
+ return optionValues(uniqueValues(["480p", ...VIDEO_GENERATION_TIERS.flatMap((tier) => getVideoGenerationResolutionsForTier(tier))]));
10203
10111
  }
10204
10112
  function videoAspectValues() {
10205
10113
  return optionValues(VIDEO_GENERATION_ASPECT_RATIOS);
10206
10114
  }
10207
10115
  function videoDurationValues() {
10208
- return optionValues(VIDEO_GENERATION_DURATION_SECONDS);
10116
+ return optionValues(uniqueValues([...VIDEO_GENERATION_DURATION_SECONDS, ...SEEDANCE_2_DURATION_SECONDS]));
10209
10117
  }
10210
10118
  function videoTierValues() {
10211
10119
  return optionValues(VIDEO_GENERATION_TIERS);
@@ -10219,18 +10127,19 @@ function videoCapabilityHelp(operation) {
10219
10127
  return `Video:
10220
10128
  --model <value> Video model: ${videoModelValues(operation)}
10221
10129
  --aspect <ratio> Video aspect ratio: ${videoAspectValues()}
10222
- --resolution <value> Veo: ${videoResolutionValues()}; Kling/fal Seedance: 720p|1080p (${resolutionLines})
10223
- --duration <seconds> Veo/Kling/fal Seedance output duration: ${videoDurationValues()}
10130
+ --resolution <value> Supported: ${videoResolutionValues()}; Veo: 720p|1080p|4k; Kling: 720p|1080p; Seedance 2: standard 480p|720p|1080p, fast 480p|720p (${resolutionLines})
10131
+ --duration <seconds> Veo/Kling: ${optionValues(VIDEO_GENERATION_DURATION_SECONDS)}; Seedance 2: ${optionValues(SEEDANCE_2_DURATION_SECONDS)}
10224
10132
  --tier <tier> Veo-only model tier: ${videoTierValues()}
10225
- --first-frame <ref> Veo start frame image variant or local image path
10226
- --last-frame <ref> Veo final frame image variant or local image path
10133
+ --first-frame <ref> Veo or Seedance 2 start frame image variant or local image path
10134
+ --last-frame <ref> Veo or Seedance 2 final frame image variant or local image path
10227
10135
  Model operations: ${operationLines}
10228
10136
  --follow <id> Resume/download a variant after a long generation or disconnect
10229
10137
  --collection <id> Place the completed asset in a Space collection
10230
10138
 
10231
- Veo 3.1 frames:
10139
+ Frame inputs:
10232
10140
  --first-frame resolves to the first referenceVariantId and becomes the Veo top-level image input.
10233
- --last-frame resolves to the second referenceVariantId and becomes Veo config.lastFrame.
10141
+ --last-frame resolves to the second referenceVariantId and becomes Veo config.lastFrame or Seedance 2 end_image_url.
10142
+ Seedance 2 requires --first-frame and supports an optional --last-frame.
10234
10143
  Use both flags together for first/last-frame generation; --last-frame requires --first-frame.
10235
10144
  Do not combine frame flags with --refs. Use --refs when you want generic Veo reference images instead of first/last-frame inputs.`;
10236
10145
  }
@@ -10679,7 +10588,7 @@ Long runs:
10679
10588
  console.log(`
10680
10589
  Usage:
10681
10590
  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>]
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>]
10591
+ makefx video derive --first-frame <variant_or_file> [--last-frame <variant_or_file>] --name <name> --type <type> "prompt" -o <file> [--model veo-3.1|seedance-2|seedance-2-fast] [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--collection <id>] [--space <id>]
10683
10592
  makefx video derive --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
10684
10593
 
10685
10594
  ${videoCapabilityHelp("derive")}
@@ -10699,12 +10608,12 @@ Usage:
10699
10608
  makefx video generate --follow <variant_id> -o <file> [--collection <id>] [--space <id>]
10700
10609
  makefx video refine --variant <variant_id> "prompt" -o <file> [--model ${videoModelValues()}] [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--collection <id>] [--space <id>]
10701
10610
  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>]
10702
- 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>]
10611
+ makefx video derive --first-frame <variant_or_file> [--last-frame <variant_or_file>] --name <name> --type <type> "prompt" -o <file> [--model veo-3.1|seedance-2|seedance-2-fast] [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--collection <id>] [--space <id>]
10703
10612
 
10704
10613
  ${videoCapabilityHelp()}
10705
10614
 
10706
10615
  Audio:
10707
- Veo and Kling default to generated audio. fal Seedance is silent and generate-only.
10616
+ Veo and Kling default to generated audio. Seedance v1 is silent and generate-only; Seedance 2 is silent and supports generate and derive.
10708
10617
  Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
10709
10618
 
10710
10619
  Long runs:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makefx",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Command-line interface for AI-assisted game asset production with Make Effects.",
5
5
  "license": "MIT",
6
6
  "type": "module",