makefx 0.1.1 → 0.1.3

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 +233 -172
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -174,4 +174,4 @@ Run `makefx --help` or `makefx help <command>` for command-specific options.
174
174
  - Media generation guide: https://makefx.app/docs/media-playbooks
175
175
  - Source: https://github.com/krasnoperov/inventory
176
176
 
177
- Version: 0.1.1
177
+ Version: 0.1.3
package/makefx.mjs CHANGED
@@ -808,65 +808,91 @@ function validateProjectConfig(config, configPath) {
808
808
  * makefx spaces --id <space_id> Show details for a specific space
809
809
  * makefx spaces create <name> Create a new space
810
810
  */
811
+ var defaultDeps$9 = {
812
+ loadConfig: loadStoredConfig,
813
+ resolveBaseUrl,
814
+ saveProjectConfig,
815
+ fetch,
816
+ print: console.log
817
+ };
811
818
  async function handleSpaces(parsed) {
819
+ try {
820
+ await executeSpaces(parsed);
821
+ } catch (error) {
822
+ console.error("Error:", error instanceof Error ? error.message : error);
823
+ process$1.exitCode = 1;
824
+ }
825
+ }
826
+ async function executeSpaces(parsed, deps = defaultDeps$9) {
812
827
  const env = resolveCommandEnvironment(parsed);
813
828
  const showDetails = parsed.options.details === "true";
814
829
  const spaceId = parsed.options.id;
815
830
  const subcommand = parsed.positionals[0];
816
831
  const jsonOutput = parsed.options.json === "true";
817
- const config = await loadStoredConfig(env);
818
- if (!config) {
819
- console.error(`Not logged in to ${env} environment.`);
820
- console.error(`Run: ${loginCommandForEnvironment(env)}`);
821
- process$1.exitCode = 1;
822
- return;
823
- }
824
- if (config.token.expiresAt < Date.now()) {
825
- console.error(`Token expired for ${env} environment.`);
826
- console.error(`Run: ${loginCommandForEnvironment(env)}`);
827
- process$1.exitCode = 1;
828
- return;
829
- }
830
- const baseUrl = resolveBaseUrl(env);
831
- const accessToken = config.token.accessToken;
832
+ const config = await deps.loadConfig(env);
833
+ if (!config) throw new Error(`Not logged in to ${env} environment. Run: ${loginCommandForEnvironment(env)}`);
834
+ if (config.token.expiresAt < Date.now()) throw new Error(`Token expired for ${env} environment. Run: ${loginCommandForEnvironment(env)}`);
832
835
  if (env === "local") process$1.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
833
- try {
834
- if (subcommand === "create") {
835
- const spaceName = parsed.positionals.slice(1).join(" ") || parsed.options.name;
836
- if (!spaceName) {
837
- console.error("Error: Space name is required");
838
- console.error("Usage: makefx spaces create <name>");
839
- console.error(" makefx spaces create --name \"My Space\"");
840
- process$1.exitCode = 1;
841
- return;
842
- }
843
- const space = await createSpace(baseUrl, accessToken, spaceName);
844
- const project = parsed.options.init === "true" ? {
845
- configPath: await saveProjectConfig({
846
- environment: env,
847
- spaceId: space.id
848
- }),
836
+ const ctx = {
837
+ env,
838
+ baseUrl: deps.resolveBaseUrl(env),
839
+ accessToken: config.token.accessToken
840
+ };
841
+ if (subcommand === "create") {
842
+ const spaceName = parsed.positionals.slice(1).join(" ") || parsed.options.name;
843
+ if (!spaceName) throw new Error("Space name is required. Usage: makefx spaces create <name>");
844
+ const space = await createSpace(ctx, deps, spaceName);
845
+ const project = parsed.options.init === "true" ? {
846
+ configPath: await deps.saveProjectConfig({
849
847
  environment: env,
850
848
  spaceId: space.id
851
- } : void 0;
852
- if (jsonOutput) console.log(JSON.stringify({
853
- space,
854
- project
855
- }, null, 2));
856
- else printCreatedSpace(space, env, project?.configPath);
857
- } else if (spaceId) await showSpaceDetails(baseUrl, accessToken, spaceId);
858
- else if (showDetails) await listSpacesWithDetails(baseUrl, accessToken);
859
- else await listSpaces(baseUrl, accessToken);
860
- } catch (error) {
861
- console.error("Error:", error instanceof Error ? error.message : error);
862
- process$1.exitCode = 1;
849
+ }),
850
+ environment: env,
851
+ spaceId: space.id
852
+ } : void 0;
853
+ if (jsonOutput) deps.print(JSON.stringify({
854
+ space,
855
+ project
856
+ }, null, 2));
857
+ else printCreatedSpace(space, ctx.env, project?.configPath, deps.print);
858
+ return {
859
+ type: "create",
860
+ space,
861
+ project
862
+ };
863
863
  }
864
+ if (spaceId) {
865
+ const details = await getSpaceDetails(ctx, deps, spaceId);
866
+ if (jsonOutput) deps.print(JSON.stringify(details, null, 2));
867
+ else printSpaceDetails(details, deps.print);
868
+ return {
869
+ type: "show",
870
+ space: details.space,
871
+ assets: details.assets
872
+ };
873
+ }
874
+ if (showDetails) {
875
+ const spaces = await listSpaceSummaries(ctx, deps);
876
+ if (jsonOutput) deps.print(JSON.stringify(spaces, null, 2));
877
+ else printSpaceSummaries(spaces, deps.print);
878
+ return {
879
+ type: "details",
880
+ spaces
881
+ };
882
+ }
883
+ const spaces = await fetchSpaces(ctx, deps);
884
+ if (jsonOutput) deps.print(JSON.stringify(spaces, null, 2));
885
+ else printSpaces(spaces, deps.print);
886
+ return {
887
+ type: "list",
888
+ spaces
889
+ };
864
890
  }
865
- async function createSpace(baseUrl, accessToken, name) {
866
- const response = await fetch(`${baseUrl}/api/spaces`, {
891
+ async function createSpace(ctx, deps, name) {
892
+ const response = await deps.fetch(`${ctx.baseUrl}/api/spaces`, {
867
893
  method: "POST",
868
894
  headers: {
869
- "Authorization": `Bearer ${accessToken}`,
895
+ "Authorization": `Bearer ${ctx.accessToken}`,
870
896
  "Content-Type": "application/json"
871
897
  },
872
898
  body: JSON.stringify({ name })
@@ -877,83 +903,82 @@ async function createSpace(baseUrl, accessToken, name) {
877
903
  }
878
904
  return (await response.json()).space;
879
905
  }
880
- function printCreatedSpace(space, env, configPath) {
906
+ function printCreatedSpace(space, env, configPath, print) {
881
907
  const envFlag = env === "production" ? "" : env === "local" ? " --local" : ` --env ${env}`;
882
- console.log(`\nSpace created successfully!\n`);
883
- console.log(` ID: ${space.id}`);
884
- console.log(` Name: ${space.name}`);
885
- console.log(` Role: ${space.role}`);
886
- if (configPath) console.log(` Config: ${configPath}`);
887
- console.log(`\nTo bind this directory:`);
888
- console.log(` makefx init --space ${space.id}${envFlag}`);
889
- console.log(`\nTo listen for events:`);
890
- console.log(` makefx listen --space ${space.id}${envFlag}`);
891
- }
892
- async function listSpaces(baseUrl, accessToken) {
893
- const response = await fetch(`${baseUrl}/api/spaces`, { headers: {
894
- "Authorization": `Bearer ${accessToken}`,
908
+ print(`\nSpace created successfully!\n`);
909
+ print(` ID: ${space.id}`);
910
+ print(` Name: ${space.name}`);
911
+ print(` Role: ${space.role}`);
912
+ if (configPath) print(` Config: ${configPath}`);
913
+ print(`\nTo bind this directory:`);
914
+ print(` makefx init --space ${space.id}${envFlag}`);
915
+ print(`\nTo listen for events:`);
916
+ print(` makefx listen --space ${space.id}${envFlag}`);
917
+ }
918
+ async function fetchSpaces(ctx, deps) {
919
+ const response = await deps.fetch(`${ctx.baseUrl}/api/spaces`, { headers: {
920
+ "Authorization": `Bearer ${ctx.accessToken}`,
895
921
  "Content-Type": "application/json"
896
922
  } });
897
923
  if (!response.ok) throw new Error(`Failed to fetch spaces: ${response.status}`);
898
- const spaces = (await response.json()).spaces;
924
+ return (await response.json()).spaces;
925
+ }
926
+ function printSpaces(spaces, print) {
899
927
  if (spaces.length === 0) {
900
- console.log("No spaces found.");
928
+ print("No spaces found.");
901
929
  return;
902
930
  }
903
- console.log(`\nFound ${spaces.length} space(s):\n`);
904
- console.log("ID".padEnd(38) + "Name".padEnd(30) + "Role");
905
- console.log("-".repeat(80));
906
- for (const space of spaces) console.log(space.id.padEnd(38) + truncatePad(space.name, 30) + space.role);
907
- console.log(`\nFor details: makefx spaces --details`);
908
- console.log(`For a specific space: makefx spaces --id <space_id>`);
931
+ print(`\nFound ${spaces.length} space(s):\n`);
932
+ print("ID".padEnd(38) + "Name".padEnd(30) + "Role");
933
+ print("-".repeat(80));
934
+ for (const space of spaces) print(space.id.padEnd(38) + truncatePad(space.name, 30) + space.role);
935
+ print(`\nFor details: makefx spaces --details`);
936
+ print(`For a specific space: makefx spaces --id <space_id>`);
909
937
  }
910
- async function listSpacesWithDetails(baseUrl, accessToken) {
911
- const response = await fetch(`${baseUrl}/api/spaces`, { headers: {
912
- "Authorization": `Bearer ${accessToken}`,
913
- "Content-Type": "application/json"
914
- } });
915
- if (!response.ok) throw new Error(`Failed to fetch spaces: ${response.status}`);
916
- const spaces = (await response.json()).spaces;
917
- if (spaces.length === 0) {
918
- console.log("No spaces found.");
938
+ async function listSpaceSummaries(ctx, deps) {
939
+ const spaces = await fetchSpaces(ctx, deps);
940
+ const summaries = [];
941
+ for (const space of spaces) {
942
+ const assets = await fetchSpaceAssets(ctx, deps, space.id);
943
+ summaries.push({
944
+ space,
945
+ assetCount: assets.length,
946
+ assetSummary: summarizeAssets(assets)
947
+ });
948
+ }
949
+ return summaries;
950
+ }
951
+ function printSpaceSummaries(summaries, print) {
952
+ if (summaries.length === 0) {
953
+ print("No spaces found.");
919
954
  return;
920
955
  }
921
- console.log(`\nFetching details for ${spaces.length} space(s)...\n`);
922
- for (const space of spaces) {
923
- const assetsResponse = await fetch(`${baseUrl}/api/spaces/${space.id}/assets`, { headers: {
924
- "Authorization": `Bearer ${accessToken}`,
925
- "Content-Type": "application/json"
926
- } });
927
- let assetCount = 0;
928
- let assetSummary = "";
929
- if (assetsResponse.ok) {
930
- const assets = (await assetsResponse.json()).assets;
931
- assetCount = assets.length;
932
- if (assets.length > 0) {
933
- const byType = /* @__PURE__ */ new Map();
934
- for (const asset of assets) {
935
- const type = asset.type || "unknown";
936
- byType.set(type, (byType.get(type) || 0) + 1);
937
- }
938
- const typeParts = [];
939
- for (const [type, count] of byType) typeParts.push(`${count} ${type}`);
940
- assetSummary = typeParts.join(", ");
941
- const firstNames = assets.slice(0, 3).map((a) => a.name);
942
- if (assets.length > 3) firstNames.push(`+${assets.length - 3} more`);
943
- assetSummary += ` (${firstNames.join(", ")})`;
944
- }
945
- }
946
- console.log(`━━━ ${space.name} ━━━`);
947
- console.log(` ID: ${space.id}`);
948
- console.log(` Role: ${space.role}`);
949
- console.log(` Assets: ${assetCount}`);
950
- if (assetSummary) console.log(` Content: ${assetSummary}`);
951
- console.log("");
956
+ print(`\nFetching details for ${summaries.length} space(s)...\n`);
957
+ for (const summary of summaries) {
958
+ print(`━━━ ${summary.space.name} ━━━`);
959
+ print(` ID: ${summary.space.id}`);
960
+ print(` Role: ${summary.space.role}`);
961
+ print(` Assets: ${summary.assetCount}`);
962
+ if (summary.assetSummary) print(` Content: ${summary.assetSummary}`);
963
+ print("");
952
964
  }
953
965
  }
954
- async function showSpaceDetails(baseUrl, accessToken, spaceId) {
955
- const spaceResponse = await fetch(`${baseUrl}/api/spaces/${spaceId}`, { headers: {
956
- "Authorization": `Bearer ${accessToken}`,
966
+ function summarizeAssets(assets) {
967
+ if (assets.length === 0) return "";
968
+ const byType = /* @__PURE__ */ new Map();
969
+ for (const asset of assets) {
970
+ const type = asset.type || "unknown";
971
+ byType.set(type, (byType.get(type) || 0) + 1);
972
+ }
973
+ const typeParts = [];
974
+ for (const [type, count] of byType) typeParts.push(`${count} ${type}`);
975
+ const firstNames = assets.slice(0, 3).map((a) => a.name);
976
+ if (assets.length > 3) firstNames.push(`+${assets.length - 3} more`);
977
+ return `${typeParts.join(", ")} (${firstNames.join(", ")})`;
978
+ }
979
+ async function getSpaceDetails(ctx, deps, spaceId) {
980
+ const spaceResponse = await deps.fetch(`${ctx.baseUrl}/api/spaces/${spaceId}`, { headers: {
981
+ "Authorization": `Bearer ${ctx.accessToken}`,
957
982
  "Content-Type": "application/json"
958
983
  } });
959
984
  if (!spaceResponse.ok) {
@@ -961,18 +986,28 @@ async function showSpaceDetails(baseUrl, accessToken, spaceId) {
961
986
  if (spaceResponse.status === 404) throw new Error(`Space not found: ${spaceId}`);
962
987
  throw new Error(`Failed to fetch space: ${spaceResponse.status}`);
963
988
  }
964
- const space = (await spaceResponse.json()).space;
965
- const assetsResponse = await fetch(`${baseUrl}/api/spaces/${spaceId}/assets`, { headers: {
966
- "Authorization": `Bearer ${accessToken}`,
989
+ const spaceData = await spaceResponse.json();
990
+ const assets = await fetchSpaceAssets(ctx, deps, spaceId);
991
+ return {
992
+ space: spaceData.space,
993
+ assets
994
+ };
995
+ }
996
+ async function fetchSpaceAssets(ctx, deps, spaceId) {
997
+ const assetsResponse = await deps.fetch(`${ctx.baseUrl}/api/spaces/${spaceId}/assets`, { headers: {
998
+ "Authorization": `Bearer ${ctx.accessToken}`,
967
999
  "Content-Type": "application/json"
968
1000
  } });
969
- let assets = [];
970
- if (assetsResponse.ok) assets = (await assetsResponse.json()).assets;
971
- console.log(`\n━━━ ${space.name} ━━━`);
972
- console.log(`ID: ${space.id}`);
973
- console.log(`Assets: ${assets.length}\n`);
1001
+ if (assetsResponse.ok) return (await assetsResponse.json()).assets;
1002
+ throw new Error(`Failed to fetch assets for space ${spaceId}: ${assetsResponse.status}`);
1003
+ }
1004
+ function printSpaceDetails(details, print) {
1005
+ const { space, assets } = details;
1006
+ print(`\n━━━ ${space.name} ━━━`);
1007
+ print(`ID: ${space.id}`);
1008
+ print(`Assets: ${assets.length}\n`);
974
1009
  if (assets.length === 0) {
975
- console.log("(No assets in this space)");
1010
+ print("(No assets in this space)");
976
1011
  return;
977
1012
  }
978
1013
  const byType = /* @__PURE__ */ new Map();
@@ -982,16 +1017,15 @@ async function showSpaceDetails(baseUrl, accessToken, spaceId) {
982
1017
  byType.get(type).push(asset);
983
1018
  }
984
1019
  for (const [type, typeAssets] of byType) {
985
- console.log(`${type.charAt(0).toUpperCase() + type.slice(1)}s (${typeAssets.length}):`);
1020
+ print(`${type.charAt(0).toUpperCase() + type.slice(1)}s (${typeAssets.length}):`);
986
1021
  for (const asset of typeAssets) {
987
- const hasImage = asset.active_variant_id ? "✓" : "○";
988
- console.log(` ${hasImage} ${asset.name}`);
989
- console.log(` ID: ${asset.id}`);
1022
+ print(` ${asset.active_variant_id ? "✓" : "○"} ${asset.name}`);
1023
+ print(` ID: ${asset.id}`);
990
1024
  }
991
- console.log("");
1025
+ print("");
992
1026
  }
993
- console.log(`\nTo start a chat session with this space:`);
994
- console.log(` makefx chat send "What's in this space?" --space ${spaceId} --state ./test/${space.name.toLowerCase().replace(/\s+/g, "-")}.json`);
1027
+ print(`\nTo start a chat session with this space:`);
1028
+ print(` makefx chat send "What's in this space?" --space ${space.id} --state ./test/${space.name.toLowerCase().replace(/\s+/g, "-")}.json`);
995
1029
  }
996
1030
  function truncatePad(str, width) {
997
1031
  if (str.length > width - 2) return str.slice(0, width - 3) + ".. ";
@@ -21263,6 +21297,7 @@ var VIDEO_GENERATION_TIERS = [
21263
21297
  "fast",
21264
21298
  "lite"
21265
21299
  ];
21300
+ var VIDEO_GENERATION_AUDIO_TOGGLE_MODELS = [];
21266
21301
  var VIDEO_GENERATION_RESOLUTIONS_BY_TIER = {
21267
21302
  generate: VIDEO_GENERATION_RESOLUTIONS,
21268
21303
  fast: VIDEO_GENERATION_RESOLUTIONS,
@@ -21272,6 +21307,11 @@ var DEFAULT_VIDEO_GENERATION_TIER = "generate";
21272
21307
  function normalizeVideoGenerationAspectRatio(value) {
21273
21308
  return VIDEO_GENERATION_ASPECT_RATIOS.includes(value) ? value : void 0;
21274
21309
  }
21310
+ var VIDEO_GENERATION_TIER_MODELS = {
21311
+ generate: "veo-3.1-generate-preview",
21312
+ fast: "veo-3.1-fast-generate-preview",
21313
+ lite: "veo-3.1-lite-generate-preview"
21314
+ };
21275
21315
  function normalizeVideoGenerationResolution(value) {
21276
21316
  return VIDEO_GENERATION_RESOLUTIONS.includes(value) ? value : void 0;
21277
21317
  }
@@ -21282,12 +21322,18 @@ function normalizeVideoGenerationDurationSeconds(value) {
21282
21322
  function normalizeVideoGenerationTier(value) {
21283
21323
  return VIDEO_GENERATION_TIERS.includes(value) ? value : void 0;
21284
21324
  }
21325
+ function getVideoGenerationModelForTier(tier = DEFAULT_VIDEO_GENERATION_TIER) {
21326
+ return VIDEO_GENERATION_TIER_MODELS[tier];
21327
+ }
21285
21328
  function getVideoGenerationResolutionsForTier(tier = DEFAULT_VIDEO_GENERATION_TIER) {
21286
21329
  return VIDEO_GENERATION_RESOLUTIONS_BY_TIER[tier];
21287
21330
  }
21288
21331
  function isVideoGenerationResolutionSupportedForTier(resolution, tier = DEFAULT_VIDEO_GENERATION_TIER) {
21289
21332
  return VIDEO_GENERATION_RESOLUTIONS_BY_TIER[tier].includes(resolution);
21290
21333
  }
21334
+ function doesVideoGenerationModelSupportAudioToggle(model) {
21335
+ return VIDEO_GENERATION_AUDIO_TOGGLE_MODELS.includes(model);
21336
+ }
21291
21337
  //#endregion
21292
21338
  //#region src/shared/imageGenerationOptions.ts
21293
21339
  var IMAGE_MODEL_SELECTIONS = ["pro", "flash"];
@@ -21594,9 +21640,9 @@ async function executeForgeCommand(command, parsed, deps = defaultDeps$6, option
21594
21640
  try {
21595
21641
  await client.connect();
21596
21642
  switch (command) {
21597
- case "generate": return await executeGenerate(parsed, ctx, client, deps, mediaKind);
21643
+ case "generate": return await executeGenerate(parsed, ctx, client, deps, mediaKind, { audioMode: options.audioMode });
21598
21644
  case "refine": return await executeRefine(parsed, ctx, client, deps, mediaKind);
21599
- case "derive": return await executeDerive(parsed, ctx, client, deps, mediaKind);
21645
+ case "derive": return await executeDerive(parsed, ctx, client, deps, mediaKind, { audioMode: options.audioMode });
21600
21646
  case "batch": return await executeBatch(parsed, ctx, client, deps, mediaKind, saveBatchManifest);
21601
21647
  }
21602
21648
  } finally {
@@ -21612,7 +21658,8 @@ async function executeAudioCommand(command, parsed, deps = defaultDeps$6, option
21612
21658
  if (parsed.options.input && command !== "generate") throw new Error("Audio --input is only supported with generate");
21613
21659
  return executeForgeCommand(command, await prepareAudioParsedArgs(parsed, options.mode), deps, {
21614
21660
  mediaKind: audioProfile.mediaKind,
21615
- saveBatchManifest: audioProfile.savesBatchManifest
21661
+ saveBatchManifest: audioProfile.savesBatchManifest,
21662
+ audioMode: options.mode
21616
21663
  });
21617
21664
  }
21618
21665
  async function executeVideoCommand(command, parsed, deps = defaultDeps$6) {
@@ -21635,12 +21682,17 @@ async function prepareAudioParsedArgs(parsed, mode) {
21635
21682
  const input = await readFile(options.input, "utf8");
21636
21683
  positionals.push(input);
21637
21684
  }
21685
+ if (!options.follow) validateAudioModeRequiredVoiceOptions(options, effectiveMode);
21638
21686
  return {
21639
21687
  options,
21640
21688
  positionals
21641
21689
  };
21642
21690
  }
21643
- async function executeGenerate(parsed, ctx, client, deps, mediaKind) {
21691
+ function validateAudioModeRequiredVoiceOptions(options, mode) {
21692
+ if (mode === "speech" && !normalizeCliOption(options.voice)) throw new Error("Speech generation requires --voice <voice_id>. Run: makefx audio voices");
21693
+ if (mode === "dialogue" && !normalizeCliOption(options["dialogue-voices"] ?? options.dialogueVoices)) throw new Error("Dialogue generation requires --dialogue-voices <voice_id,voice_id>. Run: makefx audio voices");
21694
+ }
21695
+ async function executeGenerate(parsed, ctx, client, deps, mediaKind, followOptions = {}) {
21644
21696
  const prompt = getPrompt(parsed, "generate");
21645
21697
  const outputPath = getOutputPath$1(parsed);
21646
21698
  const name = requireOption(parsed, "name");
@@ -21671,7 +21723,7 @@ async function executeGenerate(parsed, ctx, client, deps, mediaKind) {
21671
21723
  ...musicProvider ? { musicProvider } : {},
21672
21724
  ...videoAudioOptions,
21673
21725
  ...videoOptions,
21674
- onStarted: (started) => printFollowHint(started, ctx, outputPath, "generate", mediaKind)
21726
+ onStarted: (started) => printFollowHint(started, ctx, outputPath, "generate", mediaKind, followOptions)
21675
21727
  });
21676
21728
  const productionRecord = await placeProductionRecordFromScene({
21677
21729
  command: "generate",
@@ -21773,7 +21825,7 @@ async function executeRefine(parsed, ctx, client, deps, mediaKind) {
21773
21825
  printResult(result, outputPath, ctx, manifestPath, productionRecord);
21774
21826
  return result;
21775
21827
  }
21776
- async function executeDerive(parsed, ctx, client, deps, mediaKind) {
21828
+ async function executeDerive(parsed, ctx, client, deps, mediaKind, followOptions = {}) {
21777
21829
  const prompt = getPrompt(parsed, "derive");
21778
21830
  const outputPath = getOutputPath$1(parsed);
21779
21831
  const name = requireOption(parsed, "name");
@@ -21804,7 +21856,7 @@ async function executeDerive(parsed, ctx, client, deps, mediaKind) {
21804
21856
  mediaKind,
21805
21857
  ...videoAudioOptions,
21806
21858
  ...videoOptions,
21807
- onStarted: (started) => printFollowHint(started, ctx, outputPath, "derive", mediaKind)
21859
+ onStarted: (started) => printFollowHint(started, ctx, outputPath, "derive", mediaKind, followOptions)
21808
21860
  });
21809
21861
  const productionRecord = await placeProductionRecordFromScene({
21810
21862
  command: "derive",
@@ -22227,16 +22279,17 @@ function printResult(result, outputPath, ctx, manifestPath, productionRecord) {
22227
22279
  if (productionRecord) console.log(` Production: ${productionRecord.production_id} (${productionRecord.id})`);
22228
22280
  console.log(` Web: ${ctx.baseUrl}/spaces/${ctx.spaceId}/assets/${variant.asset_id}`);
22229
22281
  }
22230
- function printFollowHint(started, ctx, outputPath, command, mediaKind) {
22282
+ function printFollowHint(started, ctx, outputPath, command, mediaKind, options = {}) {
22231
22283
  console.log(` Started variant: ${started.jobId}`);
22232
- console.log(` Follow: ${formatFollowCommand(started.jobId, outputPath, ctx, command, mediaKind)}`);
22284
+ console.log(` Follow: ${formatFollowCommand(started.jobId, outputPath, ctx, command, mediaKind, options)}`);
22233
22285
  }
22234
- function formatFollowCommand(variantId, outputPath, ctx, command, mediaKind) {
22286
+ function formatFollowCommand(variantId, outputPath, ctx, command, mediaKind, options = {}) {
22235
22287
  const baseCommand = mediaKind === "audio" ? [
22236
22288
  "makefx",
22237
22289
  "audio",
22290
+ options.audioMode,
22238
22291
  "generate"
22239
- ] : mediaKind === "video" ? [
22292
+ ].filter((part) => Boolean(part)) : mediaKind === "video" ? [
22240
22293
  "makefx",
22241
22294
  "video",
22242
22295
  command
@@ -22300,12 +22353,20 @@ function validateVideoAudioOptions(parsed, mediaKind) {
22300
22353
  if (!(parsed.options.audio !== void 0 || parsed.options["no-audio"] !== void 0 || parsed.options.noAudio !== void 0)) return;
22301
22354
  if (mediaKind !== "video") throw new Error("--audio and --no-audio are only supported for video generation");
22302
22355
  if (parsed.options.audio !== void 0 && (parsed.options["no-audio"] !== void 0 || parsed.options.noAudio !== void 0)) throw new Error("Pass either --audio or --no-audio, not both");
22356
+ if (parsed.options["no-audio"] !== void 0 || parsed.options.noAudio !== void 0) {
22357
+ const tierValue = readOptionalOption(parsed, "tier", "tier") ?? readOptionalOption(parsed, "video-tier", "videoTier");
22358
+ const videoTier = tierValue === void 0 ? DEFAULT_VIDEO_GENERATION_TIER : normalizeVideoGenerationTier(tierValue);
22359
+ if (!videoTier) throw new Error("--tier must be generate, fast, or lite");
22360
+ const model = getVideoGenerationModelForTier(videoTier);
22361
+ if (!doesVideoGenerationModelSupportAudioToggle(model)) throw new Error(`${model} does not support --no-audio. Use the default audio-enabled output or omit the flag.`);
22362
+ }
22303
22363
  }
22304
22364
  function parseVideoAudioOptions(parsed, mediaKind) {
22305
- if (mediaKind !== "video") return {};
22306
- if (parsed.options.audio !== void 0) return { generateAudio: true };
22307
- if (parsed.options["no-audio"] !== void 0 || parsed.options.noAudio !== void 0) return { generateAudio: false };
22308
- return { generateAudio: false };
22365
+ if (mediaKind === "video") {
22366
+ if (parsed.options.audio !== void 0) return { generateAudio: true };
22367
+ if (parsed.options["no-audio"] !== void 0 || parsed.options.noAudio !== void 0) return { generateAudio: false };
22368
+ }
22369
+ return {};
22309
22370
  }
22310
22371
  function parseVideoGenerationOptions(parsed, mediaKind) {
22311
22372
  const resolutionValue = readOptionalOption(parsed, "resolution", "resolution") ?? readOptionalOption(parsed, "video-resolution", "videoResolution");
@@ -22620,9 +22681,9 @@ Usage:
22620
22681
  makefx audio <${modes}> batch "prompt" --name <name> --count <2-8> --output-dir <dir> [--space <id>]
22621
22682
  makefx audio music generate "prompt" --provider lyria --name <name> -o <file> [--space <id>]
22622
22683
 
22623
- Voice selection:
22684
+ Voice selection (run 'makefx audio voices' to list voice IDs):
22624
22685
  makefx audio speech generate "text" --voice <voice_id> --name <name> -o <file>
22625
- makefx audio dialogue generate --input script.txt --voice <fallback_id> --dialogue-voices <voice_id,voice_id> --name <name> -o <file>
22686
+ makefx audio dialogue generate --input script.txt --dialogue-voices <voice_id,voice_id> --name <name> -o <file>
22626
22687
 
22627
22688
  Low-level compatibility:
22628
22689
  makefx audio generate "prompt" --name <name> --type <type> -o <file> [--space <id>]
@@ -22656,11 +22717,11 @@ function printUsage$5() {
22656
22717
  const resolutionByTier = VIDEO_GENERATION_TIERS.map((tier) => `${tier}: ${getVideoGenerationResolutionsForTier(tier).join(", ")}`).join("; ");
22657
22718
  console.log(`
22658
22719
  Usage:
22659
- makefx video generate "prompt" --name <name> --type <type> -o <file> [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio|--no-audio] [--space <id>]
22720
+ makefx video generate "prompt" --name <name> --type <type> -o <file> [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
22660
22721
  makefx video generate --follow <variant_id> -o <file> [--space <id>]
22661
- makefx video refine --variant <variant_id> "prompt" -o <file> [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio|--no-audio] [--space <id>]
22722
+ makefx video refine --variant <variant_id> "prompt" -o <file> [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
22662
22723
  makefx video refine --follow <variant_id> -o <file> [--space <id>]
22663
- makefx video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio|--no-audio] [--space <id>]
22724
+ makefx video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--aspect ${aspectValues}] [--resolution ${resolutionValues}] [--duration ${durationValues}] [--tier ${tierValues}] [--audio] [--space <id>]
22664
22725
  makefx video derive --follow <variant_id> -o <file> [--space <id>]
22665
22726
 
22666
22727
  Video:
@@ -22670,8 +22731,8 @@ Video:
22670
22731
  --tier <tier> Veo model tier: ${tierValues}
22671
22732
 
22672
22733
  Audio:
22673
- --audio Request native synchronized Veo audio
22674
- --no-audio Request a silent video (default)
22734
+ --audio Request native synchronized Veo audio (default)
22735
+ --no-audio Not supported by current Veo models; rejected before a job is created.
22675
22736
 
22676
22737
  Production metadata:
22677
22738
  --scene-label <label> --timeline-start-ms <ms> --duration-ms <ms>
@@ -23565,9 +23626,11 @@ Options:
23565
23626
  }
23566
23627
  //#endregion
23567
23628
  //#region src/cli/index.ts
23568
- var CLI_VERSION = "0.1.1+fe5390f9d193";
23629
+ var CLI_VERSION = "0.1.3+21fbf493922f";
23569
23630
  async function main() {
23570
- const [, , command, ...args] = process$1.argv;
23631
+ const argv = process$1.argv.slice(2);
23632
+ if (argv[0] === "--") argv.shift();
23633
+ const [command, ...args] = argv;
23571
23634
  if (command === "--version" || command === "version") {
23572
23635
  console.log(CLI_VERSION);
23573
23636
  return;
@@ -23760,8 +23823,9 @@ Billing (Polar.sh):
23760
23823
 
23761
23824
  Spaces:
23762
23825
  spaces List all spaces
23763
- spaces --details List spaces with asset summaries
23764
- spaces --id <id> Show details for a specific space
23826
+ spaces --json List all spaces as JSON
23827
+ spaces --details [--json] List spaces with asset summaries
23828
+ spaces --id <id> [--json] Show details for a specific space
23765
23829
  spaces create <name> Create a new space
23766
23830
 
23767
23831
  Listen:
@@ -23787,10 +23851,10 @@ Audio:
23787
23851
  audio sfx generate "prompt" --name <name> -o <file>
23788
23852
 
23789
23853
  Video:
23790
- video generate "prompt" --name <name> --type <type> -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio|--no-audio]
23854
+ video generate "prompt" --name <name> --type <type> -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio]
23791
23855
  video generate --follow <variant_id> -o <file>
23792
- video refine --variant <variant_id> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio|--no-audio]
23793
- video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio|--no-audio]
23856
+ video refine --variant <variant_id> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio]
23857
+ video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio]
23794
23858
 
23795
23859
  Options:
23796
23860
  --env <environment> Target environment (production|stage|local), default: production
@@ -23866,8 +23930,9 @@ function printSpacesHelp() {
23866
23930
  console.log(`
23867
23931
  Usage:
23868
23932
  makefx spaces
23869
- makefx spaces --details
23870
- makefx spaces --id <space_id>
23933
+ makefx spaces --json
23934
+ makefx spaces --details [--json]
23935
+ makefx spaces --id <space_id> [--json]
23871
23936
  makefx spaces create <name>
23872
23937
  makefx spaces create --name "My Space" [--init] [--json]
23873
23938
  `);
@@ -24038,14 +24103,13 @@ function printVideoHelp(positionals) {
24038
24103
  if (subcommand === "generate") {
24039
24104
  console.log(`
24040
24105
  Usage:
24041
- makefx video generate "prompt" --name <name> --type <type> -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio|--no-audio] [--space <id>]
24106
+ makefx video generate "prompt" --name <name> --type <type> -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--space <id>]
24042
24107
  makefx video generate --follow <variant_id> -o <file> [--space <id>]
24043
24108
 
24044
24109
  ${videoCapabilityHelp()}
24045
24110
 
24046
24111
  Audio:
24047
- --audio Request native synchronized Veo audio
24048
- --no-audio Request a silent video (default)
24112
+ Video defaults to generated audio. Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
24049
24113
 
24050
24114
  Production metadata:
24051
24115
  --scene-label <label> --timeline-start-ms <ms> --duration-ms <ms>
@@ -24056,14 +24120,13 @@ Production metadata:
24056
24120
  if (subcommand === "refine") {
24057
24121
  console.log(`
24058
24122
  Usage:
24059
- makefx video refine --variant <variant_id> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio|--no-audio] [--space <id>]
24123
+ makefx video refine --variant <variant_id> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--space <id>]
24060
24124
  makefx video refine --follow <variant_id> -o <file> [--space <id>]
24061
24125
 
24062
24126
  ${videoCapabilityHelp()}
24063
24127
 
24064
24128
  Audio:
24065
- --audio Request native synchronized Veo audio
24066
- --no-audio Request a silent video (default)
24129
+ Video defaults to generated audio. Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
24067
24130
 
24068
24131
  Production metadata:
24069
24132
  --scene-label <label> --timeline-start-ms <ms> --duration-ms <ms>
@@ -24074,14 +24137,13 @@ Production metadata:
24074
24137
  if (subcommand === "derive") {
24075
24138
  console.log(`
24076
24139
  Usage:
24077
- makefx video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio|--no-audio] [--space <id>]
24140
+ makefx video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--space <id>]
24078
24141
  makefx video derive --follow <variant_id> -o <file> [--space <id>]
24079
24142
 
24080
24143
  ${videoCapabilityHelp()}
24081
24144
 
24082
24145
  Audio:
24083
- --audio Request native synchronized Veo audio
24084
- --no-audio Request a silent video (default)
24146
+ Video defaults to generated audio. Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
24085
24147
 
24086
24148
  Production metadata:
24087
24149
  --scene-label <label> --timeline-start-ms <ms> --duration-ms <ms>
@@ -24091,16 +24153,15 @@ Production metadata:
24091
24153
  }
24092
24154
  console.log(`
24093
24155
  Usage:
24094
- makefx video generate "prompt" --name <name> --type <type> -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio|--no-audio] [--space <id>]
24156
+ makefx video generate "prompt" --name <name> --type <type> -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--space <id>]
24095
24157
  makefx video generate --follow <variant_id> -o <file> [--space <id>]
24096
- makefx video refine --variant <variant_id> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio|--no-audio] [--space <id>]
24097
- makefx video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio|--no-audio] [--space <id>]
24158
+ makefx video refine --variant <variant_id> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--space <id>]
24159
+ makefx video derive --refs <variant_or_file,variant_or_file> --name <name> --type <type> "prompt" -o <file> [--aspect ${videoAspectValues()}] [--resolution ${videoResolutionValues()}] [--duration ${videoDurationValues()}] [--tier ${videoTierValues()}] [--audio] [--space <id>]
24098
24160
 
24099
24161
  ${videoCapabilityHelp()}
24100
24162
 
24101
24163
  Audio:
24102
- --audio Request native synchronized Veo audio
24103
- --no-audio Request a silent video (default)
24164
+ Video defaults to generated audio. Current Veo models do not support --no-audio; the CLI rejects it before creating a job.
24104
24165
 
24105
24166
  Production metadata:
24106
24167
  --scene-label <label> --timeline-start-ms <ms> --duration-ms <ms>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "makefx",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Command-line interface for AI-assisted game asset production with Make Effects.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,7 +9,7 @@
9
9
  "url": "git+https://github.com/krasnoperov/inventory.git"
10
10
  },
11
11
  "bin": {
12
- "makefx": "./makefx.mjs"
12
+ "makefx": "makefx.mjs"
13
13
  },
14
14
  "files": [
15
15
  "makefx.mjs",