makefx 1.4.0 → 1.5.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.
- package/README.md +1 -1
- package/makefx.mjs +1032 -114
- package/package.json +1 -1
package/makefx.mjs
CHANGED
|
@@ -660,6 +660,9 @@ function createVariantRef(name, assetId, variantId) {
|
|
|
660
660
|
function createDraftRef(name, draftId) {
|
|
661
661
|
return `draft:${slugify(name, "draft")}~${compactIdPrefix(draftId)}`;
|
|
662
662
|
}
|
|
663
|
+
function createGraphRunRef(runId) {
|
|
664
|
+
return `graph-run:${compactIdPrefix(runId)}`;
|
|
665
|
+
}
|
|
663
666
|
function parseAssetRef(value) {
|
|
664
667
|
const match = /^asset:[^~]+~([a-z0-9]{4,8})$/u.exec(value);
|
|
665
668
|
return match ? { idPrefix: match[1] } : null;
|
|
@@ -4399,6 +4402,7 @@ var WebSocketClient = class WebSocketClient {
|
|
|
4399
4402
|
chatHandlers = /* @__PURE__ */ new Map();
|
|
4400
4403
|
generateHandlers = /* @__PURE__ */ new Map();
|
|
4401
4404
|
earlyTerminalVariants = /* @__PURE__ */ new Map();
|
|
4405
|
+
draftRunStartsAwaitingVariant = /* @__PURE__ */ new Set();
|
|
4402
4406
|
variantCompletionHandlers = /* @__PURE__ */ new Map();
|
|
4403
4407
|
describeHandlers = /* @__PURE__ */ new Map();
|
|
4404
4408
|
compareHandlers = /* @__PURE__ */ new Map();
|
|
@@ -4724,7 +4728,7 @@ var WebSocketClient = class WebSocketClient {
|
|
|
4724
4728
|
return handled;
|
|
4725
4729
|
}
|
|
4726
4730
|
hasRequestsAwaitingStarted() {
|
|
4727
|
-
return this.generateHandlers.size > 0;
|
|
4731
|
+
return this.generateHandlers.size > 0 || this.draftRunStartsAwaitingVariant.size > 0;
|
|
4728
4732
|
}
|
|
4729
4733
|
clearOrphanedEarlyTerminalVariants() {
|
|
4730
4734
|
if (!this.hasRequestsAwaitingStarted()) this.earlyTerminalVariants.clear();
|
|
@@ -4869,6 +4873,58 @@ var WebSocketClient = class WebSocketClient {
|
|
|
4869
4873
|
bindingId
|
|
4870
4874
|
}, (msg) => msg.type === "binding:cleared" && msg.draftId === draftId && msg.bindingId === bindingId);
|
|
4871
4875
|
}
|
|
4876
|
+
async runDraft(draftId, requestId, onStarted) {
|
|
4877
|
+
if (onStarted) this.draftRunStartsAwaitingVariant.add(requestId);
|
|
4878
|
+
try {
|
|
4879
|
+
const result = await this.awaitServerMessage({
|
|
4880
|
+
type: "drafts.run",
|
|
4881
|
+
draftId,
|
|
4882
|
+
requestId,
|
|
4883
|
+
source: "cli"
|
|
4884
|
+
}, (msg) => (msg.type === "drafts.run_started" || msg.type === "drafts.run_error") && msg.requestId === requestId);
|
|
4885
|
+
if (result.type === "drafts.run_error") throw new Error(`${result.code}: ${result.error}`);
|
|
4886
|
+
onStarted?.(result);
|
|
4887
|
+
return result;
|
|
4888
|
+
} finally {
|
|
4889
|
+
this.draftRunStartsAwaitingVariant.delete(requestId);
|
|
4890
|
+
this.clearOrphanedEarlyTerminalVariants();
|
|
4891
|
+
}
|
|
4892
|
+
}
|
|
4893
|
+
async runGraph(input) {
|
|
4894
|
+
const result = await this.awaitServerMessage({
|
|
4895
|
+
type: "graph.run",
|
|
4896
|
+
...input,
|
|
4897
|
+
source: "cli"
|
|
4898
|
+
}, (msg) => msg.type === "graph.run_started" && msg.run.request_id === input.requestId || msg.type === "graph.run_error" && msg.requestId === input.requestId);
|
|
4899
|
+
if (result.type === "graph.run_error") {
|
|
4900
|
+
const detail = result.failures.map((failure) => `${failure.draftId}: ${failure.error}`).join("; ");
|
|
4901
|
+
throw new Error(`${result.code}: ${detail || result.error}`);
|
|
4902
|
+
}
|
|
4903
|
+
return {
|
|
4904
|
+
type: "graph.run_status",
|
|
4905
|
+
run: result.run,
|
|
4906
|
+
drafts: result.drafts
|
|
4907
|
+
};
|
|
4908
|
+
}
|
|
4909
|
+
async getGraphRunStatus(runRef) {
|
|
4910
|
+
return this.awaitServerMessage({
|
|
4911
|
+
type: "graph.status",
|
|
4912
|
+
runRef
|
|
4913
|
+
}, (msg) => msg.type === "graph.run_status");
|
|
4914
|
+
}
|
|
4915
|
+
async cancelGraphRun(runId) {
|
|
4916
|
+
return this.awaitServerMessage({
|
|
4917
|
+
type: "graph.cancel",
|
|
4918
|
+
runId
|
|
4919
|
+
}, (msg) => msg.type === "graph.run_status" && msg.run.id === runId);
|
|
4920
|
+
}
|
|
4921
|
+
async waitForGraphRun(runRef, runId, timeoutMs = GENERATION_REQUEST_TIMEOUT_MS) {
|
|
4922
|
+
await this.awaitServerMessage({
|
|
4923
|
+
type: "graph.status",
|
|
4924
|
+
runRef
|
|
4925
|
+
}, (msg) => (msg.type === "graph.run_status" && msg.run.id === runId || msg.type === "graph.run_progress" && msg.run.id === runId) && msg.run.status !== "running", timeoutMs);
|
|
4926
|
+
return this.getGraphRunStatus(runRef);
|
|
4927
|
+
}
|
|
4872
4928
|
async setCanvasLens(lens) {
|
|
4873
4929
|
return (await this.awaitServerMessage({
|
|
4874
4930
|
type: "canvas.set_lens",
|
|
@@ -4992,6 +5048,11 @@ var WebSocketClient = class WebSocketClient {
|
|
|
4992
5048
|
reject,
|
|
4993
5049
|
timeout
|
|
4994
5050
|
});
|
|
5051
|
+
const earlyTerminal = this.earlyTerminalVariants.get(params.variantId);
|
|
5052
|
+
if (earlyTerminal) {
|
|
5053
|
+
this.earlyTerminalVariants.delete(params.variantId);
|
|
5054
|
+
this.handleTerminalVariant(earlyTerminal);
|
|
5055
|
+
}
|
|
4995
5056
|
});
|
|
4996
5057
|
}
|
|
4997
5058
|
cancelFollowVariant(variantId, requestId) {
|
|
@@ -6017,6 +6078,11 @@ var VIDEO_GENERATION_RESOLUTIONS = [
|
|
|
6017
6078
|
];
|
|
6018
6079
|
var ALL_VIDEO_GENERATION_RESOLUTIONS = ["480p", ...VIDEO_GENERATION_RESOLUTIONS];
|
|
6019
6080
|
var KLING_VIDEO_GENERATION_RESOLUTIONS = ["720p", "1080p"];
|
|
6081
|
+
var VIDEO_GENERATION_DURATION_SECONDS = [
|
|
6082
|
+
4,
|
|
6083
|
+
6,
|
|
6084
|
+
8
|
|
6085
|
+
];
|
|
6020
6086
|
var SEEDANCE_2_DURATION_SECONDS = [
|
|
6021
6087
|
4,
|
|
6022
6088
|
5,
|
|
@@ -6042,6 +6108,12 @@ var VIDEO_MODEL_SELECTIONS = [
|
|
|
6042
6108
|
"kling",
|
|
6043
6109
|
"fal-seedance"
|
|
6044
6110
|
];
|
|
6111
|
+
var VIDEO_MODEL_LABELS = {
|
|
6112
|
+
"veo-3.1": "Veo 3.1",
|
|
6113
|
+
"omni-flash": "Omni Flash",
|
|
6114
|
+
kling: "Kling 3.0",
|
|
6115
|
+
"fal-seedance": "fal.ai Seedance v1 (text-to-video)"
|
|
6116
|
+
};
|
|
6045
6117
|
var VIDEO_MODEL_SUPPORTED_OPERATIONS = {
|
|
6046
6118
|
"veo-3.1": [
|
|
6047
6119
|
"generate",
|
|
@@ -6069,6 +6141,7 @@ var VIDEO_GENERATION_RESOLUTIONS_BY_TIER = {
|
|
|
6069
6141
|
fast: VIDEO_GENERATION_RESOLUTIONS,
|
|
6070
6142
|
lite: ["720p", "1080p"]
|
|
6071
6143
|
};
|
|
6144
|
+
var DEFAULT_VIDEO_GENERATION_RESOLUTION = "720p";
|
|
6072
6145
|
var DEFAULT_VIDEO_GENERATION_TIER = "generate";
|
|
6073
6146
|
var DEFAULT_VIDEO_MODEL_SELECTION = "veo-3.1";
|
|
6074
6147
|
function normalizeVideoGenerationAspectRatio(value) {
|
|
@@ -6144,6 +6217,12 @@ function isFalSeedanceV1VideoGenerationModel(model) {
|
|
|
6144
6217
|
function isFalSeedance2VideoGenerationModel(model) {
|
|
6145
6218
|
return typeof model === "string" && getSeedance2CapabilityByEndpoint(model) !== void 0;
|
|
6146
6219
|
}
|
|
6220
|
+
function getVideoGenerationMaxReferenceImages(model) {
|
|
6221
|
+
if (isFalSeedanceV1VideoGenerationModel(model)) return 0;
|
|
6222
|
+
if (isFalSeedance2VideoGenerationModel(model)) return getSeedance2CapabilityByEndpoint(model)?.references.find((reference) => reference.mediaKind === "image")?.maxCount ?? 0;
|
|
6223
|
+
if (isKlingVideoGenerationModel(model)) return 1;
|
|
6224
|
+
return 3;
|
|
6225
|
+
}
|
|
6147
6226
|
function isVideoOperationSupportedByModel(model, operation) {
|
|
6148
6227
|
const seedanceCapability = getSeedance2CapabilityByEndpoint(model);
|
|
6149
6228
|
if (seedanceCapability) return seedanceCapability.operations.includes(operation);
|
|
@@ -6234,6 +6313,9 @@ var IMAGE_MODEL_CAPABILITIES = {
|
|
|
6234
6313
|
function isImageModelSelection(value) {
|
|
6235
6314
|
return IMAGE_MODEL_SELECTIONS.includes(value);
|
|
6236
6315
|
}
|
|
6316
|
+
function isImageModelId(value) {
|
|
6317
|
+
return Object.values(IMAGE_MODEL_IDS).includes(value);
|
|
6318
|
+
}
|
|
6237
6319
|
function isImageSize(value) {
|
|
6238
6320
|
return IMAGE_SIZES.includes(value);
|
|
6239
6321
|
}
|
|
@@ -6382,9 +6464,21 @@ var AUDIO_FORGE_MEDIA_MODES = MEDIA_OPERATION_MATRIX.filter((entry) => entry.med
|
|
|
6382
6464
|
function getMediaOperationEntry(mode) {
|
|
6383
6465
|
return ENTRY_BY_MODE.get(mode) ?? MEDIA_OPERATION_MATRIX[0];
|
|
6384
6466
|
}
|
|
6467
|
+
function getMediaKindForForgeMode(mode) {
|
|
6468
|
+
return getMediaOperationEntry(mode).mediaKind;
|
|
6469
|
+
}
|
|
6385
6470
|
function isAudioForgeMediaMode(value) {
|
|
6386
6471
|
return AUDIO_FORGE_MEDIA_MODES.includes(value);
|
|
6387
6472
|
}
|
|
6473
|
+
function getForgeModeForAudioAssetType(assetType) {
|
|
6474
|
+
switch (assetType) {
|
|
6475
|
+
case "speech":
|
|
6476
|
+
case "dialogue":
|
|
6477
|
+
case "music":
|
|
6478
|
+
case "sfx": return assetType;
|
|
6479
|
+
default: return "speech";
|
|
6480
|
+
}
|
|
6481
|
+
}
|
|
6388
6482
|
function getCliGenerationProfile(namespace) {
|
|
6389
6483
|
const profile = PROFILE_BY_NAMESPACE.get(namespace);
|
|
6390
6484
|
if (!profile) throw new Error(`Unknown CLI generation namespace: ${namespace}`);
|
|
@@ -6489,49 +6583,49 @@ async function executeForgeCommand(command, parsed, deps = defaultDeps$12, optio
|
|
|
6489
6583
|
client.disconnect();
|
|
6490
6584
|
}
|
|
6491
6585
|
}
|
|
6586
|
+
var CLI_GENERATION_COMMON_OPTIONS = [
|
|
6587
|
+
"env",
|
|
6588
|
+
"local",
|
|
6589
|
+
"space",
|
|
6590
|
+
"force",
|
|
6591
|
+
"name",
|
|
6592
|
+
"type",
|
|
6593
|
+
"o",
|
|
6594
|
+
"output",
|
|
6595
|
+
"collection"
|
|
6596
|
+
];
|
|
6597
|
+
var CLI_GENERATION_MEDIA_OPTIONS = {
|
|
6598
|
+
image: [
|
|
6599
|
+
"model",
|
|
6600
|
+
"refs",
|
|
6601
|
+
"aspect",
|
|
6602
|
+
"size"
|
|
6603
|
+
],
|
|
6604
|
+
audio: [
|
|
6605
|
+
"model",
|
|
6606
|
+
"input",
|
|
6607
|
+
"voice",
|
|
6608
|
+
"dialogue-voices"
|
|
6609
|
+
],
|
|
6610
|
+
video: [
|
|
6611
|
+
"model",
|
|
6612
|
+
"refs",
|
|
6613
|
+
"aspect",
|
|
6614
|
+
"audio",
|
|
6615
|
+
"no-audio",
|
|
6616
|
+
"resolution",
|
|
6617
|
+
"duration",
|
|
6618
|
+
"tier",
|
|
6619
|
+
"bitrate",
|
|
6620
|
+
"first-frame",
|
|
6621
|
+
"last-frame",
|
|
6622
|
+
"image-refs",
|
|
6623
|
+
"video-refs",
|
|
6624
|
+
"audio-refs"
|
|
6625
|
+
]
|
|
6626
|
+
};
|
|
6492
6627
|
function rejectUnknownGenerationOptions(options, mediaKind) {
|
|
6493
|
-
const
|
|
6494
|
-
"env",
|
|
6495
|
-
"local",
|
|
6496
|
-
"space",
|
|
6497
|
-
"force",
|
|
6498
|
-
"name",
|
|
6499
|
-
"type",
|
|
6500
|
-
"o",
|
|
6501
|
-
"output",
|
|
6502
|
-
"collection"
|
|
6503
|
-
];
|
|
6504
|
-
const byKind = {
|
|
6505
|
-
image: [
|
|
6506
|
-
"model",
|
|
6507
|
-
"refs",
|
|
6508
|
-
"aspect",
|
|
6509
|
-
"size"
|
|
6510
|
-
],
|
|
6511
|
-
audio: [
|
|
6512
|
-
"model",
|
|
6513
|
-
"input",
|
|
6514
|
-
"voice",
|
|
6515
|
-
"dialogue-voices"
|
|
6516
|
-
],
|
|
6517
|
-
video: [
|
|
6518
|
-
"model",
|
|
6519
|
-
"refs",
|
|
6520
|
-
"aspect",
|
|
6521
|
-
"audio",
|
|
6522
|
-
"no-audio",
|
|
6523
|
-
"resolution",
|
|
6524
|
-
"duration",
|
|
6525
|
-
"tier",
|
|
6526
|
-
"bitrate",
|
|
6527
|
-
"first-frame",
|
|
6528
|
-
"last-frame",
|
|
6529
|
-
"image-refs",
|
|
6530
|
-
"video-refs",
|
|
6531
|
-
"audio-refs"
|
|
6532
|
-
]
|
|
6533
|
-
};
|
|
6534
|
-
const allowed = new Set([...common, ...byKind[mediaKind]]);
|
|
6628
|
+
const allowed = new Set([...CLI_GENERATION_COMMON_OPTIONS, ...CLI_GENERATION_MEDIA_OPTIONS[mediaKind]]);
|
|
6535
6629
|
const unknown = Object.keys(options).find((name) => !allowed.has(name));
|
|
6536
6630
|
if (unknown) throw new Error(`Unknown option: --${unknown}`);
|
|
6537
6631
|
}
|
|
@@ -6585,12 +6679,16 @@ async function executeGenerate(parsed, ctx, client, deps, mediaKind, followOptio
|
|
|
6585
6679
|
const seedanceCapability = mediaKind === "video" ? getSeedance2CapabilityByEndpoint(effectiveVideoModel) : void 0;
|
|
6586
6680
|
const videoFrameRefs = parseVideoFrameReferenceOptions(parsed, "generate", mediaKind).refs;
|
|
6587
6681
|
const seedanceRefs = parseSeedanceReferenceOptions(parsed);
|
|
6682
|
+
const plainRefs = parseOptionalRefs(parsed, "refs");
|
|
6588
6683
|
validateSeedanceReferenceOptions(seedanceRefs, effectiveVideoModel, "generate");
|
|
6589
6684
|
if (seedanceCapability?.mode === "frame" && videoFrameRefs.length === 0) throw new Error(`--model ${seedanceCapability.selection} requires --first-frame`);
|
|
6590
6685
|
if (seedanceCapability?.mode === "text" && videoFrameRefs.length > 0) throw new Error(`--model ${seedanceCapability.selection} does not accept references`);
|
|
6591
6686
|
if (seedanceCapability?.mode === "reference" && videoFrameRefs.length > 0) throw new Error(`--model ${seedanceCapability.selection} uses --image-refs, --video-refs, and --audio-refs`);
|
|
6687
|
+
if (seedanceCapability && plainRefs.length > 0) throw new Error(`--model ${seedanceCapability.selection} uses --image-refs, --video-refs, and --audio-refs instead of --refs`);
|
|
6688
|
+
if (mediaKind === "video" && isKlingVideoGenerationModel(effectiveVideoModel) && videoFrameRefs.length + plainRefs.length > 1) throw new Error("--model kling supports at most one image reference");
|
|
6689
|
+
if (mediaKind === "video" && isFalVideoGenerationModel(effectiveVideoModel) && !isFalSeedance2VideoGenerationModel(effectiveVideoModel) && (videoFrameRefs.length > 0 || plainRefs.length > 0)) throw new Error(`--model ${getVideoModelSelectionForModel(effectiveVideoModel) ?? effectiveVideoModel} does not support image references`);
|
|
6592
6690
|
const seedanceReferenceCount = seedanceRefs.imageRefs.length + seedanceRefs.videoRefs.length + seedanceRefs.audioRefs.length;
|
|
6593
|
-
const state = videoFrameRefs.length > 0 || seedanceReferenceCount > 0 ? await requestSpaceState(client) : void 0;
|
|
6691
|
+
const state = videoFrameRefs.length > 0 || seedanceReferenceCount > 0 || plainRefs.length > 0 ? await requestSpaceState(client) : void 0;
|
|
6594
6692
|
const referenceDeps = {
|
|
6595
6693
|
...deps,
|
|
6596
6694
|
waitForReferenceVariant: (variant) => waitForReferenceVariant(client, variant)
|
|
@@ -6599,12 +6697,12 @@ async function executeGenerate(parsed, ctx, client, deps, mediaKind, followOptio
|
|
|
6599
6697
|
refs: [],
|
|
6600
6698
|
ids: []
|
|
6601
6699
|
};
|
|
6602
|
-
const
|
|
6700
|
+
const directRefs = videoFrameRefs.length > 0 ? videoFrameRefs : plainRefs;
|
|
6701
|
+
const directRefMediaKind = videoFrameRefs.length > 0 ? CLI_GENERATION_MEDIA_KIND : mediaKind;
|
|
6702
|
+
const referenceVariantIds = resolvedSeedanceRefs.ids.length > 0 ? resolvedSeedanceRefs.ids : directRefs.length > 0 ? await resolveReferenceVariantIds(directRefs, ctx, referenceDeps, state?.variants, directRefMediaKind, state?.assets) : [];
|
|
6603
6703
|
const imageOptions = parseImageGenerationOptions(parsed, mediaKind);
|
|
6604
6704
|
const audioModelOptions = parseAudioGenerationOptions(parsed, mediaKind);
|
|
6605
6705
|
const videoAudioOptions = parseVideoAudioOptions(parsed, mediaKind);
|
|
6606
|
-
if (mediaKind === "video" && isKlingVideoGenerationModel(effectiveVideoModel) && videoFrameRefs.length > 1) throw new Error("--model kling supports at most one image reference");
|
|
6607
|
-
if (mediaKind === "video" && isFalVideoGenerationModel(effectiveVideoModel) && !isFalSeedance2VideoGenerationModel(effectiveVideoModel) && videoFrameRefs.length > 0) throw new Error(`--model ${getVideoModelSelectionForModel(effectiveVideoModel) ?? effectiveVideoModel} does not support image references`);
|
|
6608
6706
|
const collectionPlacement = parseCollectionPlacementOptions(parsed);
|
|
6609
6707
|
const followCommandOptions = {
|
|
6610
6708
|
...followOptions,
|
|
@@ -7290,7 +7388,7 @@ function cliImageModelValues(command) {
|
|
|
7290
7388
|
function printUsage$6(command) {
|
|
7291
7389
|
console.log(`
|
|
7292
7390
|
Usage:
|
|
7293
|
-
makefx image generate "prompt" --name <name> --type <type> -o <file> [--model ${cliImageModelValues(command)}] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>] [--space <id>]
|
|
7391
|
+
makefx image generate "prompt" --name <name> --type <type> -o <file> [--model ${cliImageModelValues(command)}] [--refs <variant-ref-or-file,...>] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>] [--space <id>]
|
|
7294
7392
|
`);
|
|
7295
7393
|
}
|
|
7296
7394
|
//#endregion
|
|
@@ -7431,7 +7529,7 @@ function resolveVideoRegenerationModel(model, parsed, sourceRecipe) {
|
|
|
7431
7529
|
"video-refs",
|
|
7432
7530
|
"audio-refs"
|
|
7433
7531
|
].some((name) => parsed.options[name] !== void 0);
|
|
7434
|
-
const storedRecipe = parseStoredRecipe$
|
|
7532
|
+
const storedRecipe = parseStoredRecipe$2(sourceRecipe);
|
|
7435
7533
|
return getSeedance2RegenerationCapability(model, {
|
|
7436
7534
|
model: storedRecipe?.model,
|
|
7437
7535
|
references: storedRecipe?.references ?? [],
|
|
@@ -7442,7 +7540,7 @@ function resolveVideoRegenerationModel(model, parsed, sourceRecipe) {
|
|
|
7442
7540
|
if (!selection) throw new Error("Unsupported video model. Expected veo-3.1, omni-flash, kling, seedance-1, seedance-2, or seedance-2-fast");
|
|
7443
7541
|
return getVideoGenerationModelForSelection(selection, tier);
|
|
7444
7542
|
}
|
|
7445
|
-
function parseStoredRecipe$
|
|
7543
|
+
function parseStoredRecipe$2(recipe) {
|
|
7446
7544
|
if (!recipe) return void 0;
|
|
7447
7545
|
try {
|
|
7448
7546
|
const parsed = JSON.parse(recipe);
|
|
@@ -8360,13 +8458,575 @@ async function executeSpaceLens(parsed, deps = defaultDeps$8) {
|
|
|
8360
8458
|
return result;
|
|
8361
8459
|
}
|
|
8362
8460
|
//#endregion
|
|
8461
|
+
//#region src/shared/generatorCapabilities.ts
|
|
8462
|
+
function input(name, type, required, description, options = {}) {
|
|
8463
|
+
return {
|
|
8464
|
+
name,
|
|
8465
|
+
type,
|
|
8466
|
+
required,
|
|
8467
|
+
description,
|
|
8468
|
+
...options
|
|
8469
|
+
};
|
|
8470
|
+
}
|
|
8471
|
+
var SPACE_INPUT = input("space_id", "string", true, "Target Space ID from list_spaces.");
|
|
8472
|
+
var NAME_INPUT = input("name", "string", true, "Human-readable asset name.");
|
|
8473
|
+
var PROMPT_INPUT = input("prompt", "string", true, "Generation instruction.");
|
|
8474
|
+
function fixedInput(name, value, description) {
|
|
8475
|
+
return input(name, "string", true, description, { allowedValues: [value] });
|
|
8476
|
+
}
|
|
8477
|
+
function imageGenerator(capability) {
|
|
8478
|
+
const referenceInput = input("reference_variant_refs", "string_array", false, "Completed image variant references from find_assets or get_asset.", {
|
|
8479
|
+
minItems: 1,
|
|
8480
|
+
maxItems: capability.maxReferenceImages
|
|
8481
|
+
});
|
|
8482
|
+
const generateInputs = [
|
|
8483
|
+
SPACE_INPUT,
|
|
8484
|
+
fixedInput("generator_id", `image/${capability.selection}`, "Selects this image generator."),
|
|
8485
|
+
NAME_INPUT,
|
|
8486
|
+
input("asset_type", "string", true, "Asset classification stored in the Space."),
|
|
8487
|
+
PROMPT_INPUT,
|
|
8488
|
+
input("aspect_ratio", "string", false, "Output aspect ratio.", {
|
|
8489
|
+
allowedValues: capability.supportedAspectRatios,
|
|
8490
|
+
defaultValue: "1:1"
|
|
8491
|
+
}),
|
|
8492
|
+
input("image_size", "string", false, "Output image size.", {
|
|
8493
|
+
allowedValues: capability.supportedImageSizes,
|
|
8494
|
+
defaultValue: "1K"
|
|
8495
|
+
})
|
|
8496
|
+
];
|
|
8497
|
+
const operations = [{
|
|
8498
|
+
operation: "generate",
|
|
8499
|
+
tool: "generate_image",
|
|
8500
|
+
description: "Create a new image asset from text.",
|
|
8501
|
+
inputs: generateInputs
|
|
8502
|
+
}];
|
|
8503
|
+
if (capability.supportedOperations.includes("derive")) operations.push({
|
|
8504
|
+
operation: "derive",
|
|
8505
|
+
tool: "generate_image",
|
|
8506
|
+
description: "Create a new image asset using completed image variants as references.",
|
|
8507
|
+
inputs: [...generateInputs, {
|
|
8508
|
+
...referenceInput,
|
|
8509
|
+
required: true
|
|
8510
|
+
}]
|
|
8511
|
+
});
|
|
8512
|
+
if (capability.supportedOperations.includes("refine")) operations.push({
|
|
8513
|
+
operation: "refine",
|
|
8514
|
+
tool: "edit_image",
|
|
8515
|
+
description: "Create a new variant on an existing image asset.",
|
|
8516
|
+
inputs: [
|
|
8517
|
+
SPACE_INPUT,
|
|
8518
|
+
fixedInput("generator_id", `image/${capability.selection}`, "Selects this image generator."),
|
|
8519
|
+
input("asset_ref", "string", true, "Target image asset reference from find_assets."),
|
|
8520
|
+
PROMPT_INPUT,
|
|
8521
|
+
input("source_variant_ref", "string", true, "Completed image variant to edit."),
|
|
8522
|
+
input("reference_variant_refs", "string_array", false, "Additional completed image references.", {
|
|
8523
|
+
minItems: 1,
|
|
8524
|
+
maxItems: Math.max(0, capability.maxReferenceImages - 1)
|
|
8525
|
+
}),
|
|
8526
|
+
input("aspect_ratio", "string", false, "Output aspect ratio.", {
|
|
8527
|
+
allowedValues: capability.supportedAspectRatios,
|
|
8528
|
+
defaultValue: "1:1"
|
|
8529
|
+
}),
|
|
8530
|
+
input("image_size", "string", false, "Output image size.", {
|
|
8531
|
+
allowedValues: capability.supportedImageSizes,
|
|
8532
|
+
defaultValue: "1K"
|
|
8533
|
+
})
|
|
8534
|
+
]
|
|
8535
|
+
});
|
|
8536
|
+
return {
|
|
8537
|
+
id: `image/${capability.selection}`,
|
|
8538
|
+
label: capability.label,
|
|
8539
|
+
mediaKind: "image",
|
|
8540
|
+
provider: capability.provider === "gemini" ? "google_ai" : "fal",
|
|
8541
|
+
modelIds: [capability.modelId],
|
|
8542
|
+
defaultModelId: capability.modelId,
|
|
8543
|
+
operations,
|
|
8544
|
+
referenceRules: {
|
|
8545
|
+
mediaKind: capability.maxReferenceImages > 0 ? "image" : null,
|
|
8546
|
+
completedOnly: capability.maxReferenceImages > 0,
|
|
8547
|
+
maxCount: capability.maxReferenceImages
|
|
8548
|
+
},
|
|
8549
|
+
notes: capability.maxReferenceImages > 0 ? ["Use compact variant references; binary image input is not accepted."] : ["Text-to-image only; reference inputs are not supported."]
|
|
8550
|
+
};
|
|
8551
|
+
}
|
|
8552
|
+
function videoGenerator(selection) {
|
|
8553
|
+
const defaultModel = getVideoGenerationModelForSelection(selection);
|
|
8554
|
+
const isVeo = selection === "veo-3.1";
|
|
8555
|
+
const isOmni = selection === "omni-flash";
|
|
8556
|
+
const isKling = selection === "kling";
|
|
8557
|
+
const modelIds = isVeo ? Object.values(VIDEO_GENERATION_TIER_MODELS) : [defaultModel];
|
|
8558
|
+
const resolutions = isVeo ? VIDEO_GENERATION_RESOLUTIONS : getVideoGenerationResolutionsForModel(defaultModel);
|
|
8559
|
+
const maxReferences = getVideoGenerationMaxReferenceImages(defaultModel);
|
|
8560
|
+
const parameterInputs = [input("aspect_ratio", "string", false, "Output aspect ratio.", {
|
|
8561
|
+
allowedValues: VIDEO_GENERATION_ASPECT_RATIOS,
|
|
8562
|
+
defaultValue: "16:9"
|
|
8563
|
+
})];
|
|
8564
|
+
if (!isOmni) parameterInputs.push(input("video_resolution", "string", false, "Output resolution.", {
|
|
8565
|
+
allowedValues: resolutions,
|
|
8566
|
+
defaultValue: DEFAULT_VIDEO_GENERATION_RESOLUTION
|
|
8567
|
+
}), input("video_duration_seconds", "integer", false, "Output duration in seconds.", {
|
|
8568
|
+
allowedValues: VIDEO_GENERATION_DURATION_SECONDS,
|
|
8569
|
+
defaultValue: 8
|
|
8570
|
+
}));
|
|
8571
|
+
if (isVeo) parameterInputs.push(input("video_tier", "string", false, "Veo model tier.", {
|
|
8572
|
+
allowedValues: VIDEO_GENERATION_TIERS,
|
|
8573
|
+
defaultValue: DEFAULT_VIDEO_GENERATION_TIER
|
|
8574
|
+
}));
|
|
8575
|
+
if (isKling) parameterInputs.push(input("generate_audio", "boolean", false, "Generate synchronized audio.", {
|
|
8576
|
+
allowedValues: [true, false],
|
|
8577
|
+
defaultValue: true
|
|
8578
|
+
}));
|
|
8579
|
+
const commonInputs = [
|
|
8580
|
+
SPACE_INPUT,
|
|
8581
|
+
fixedInput("generator_id", `video/${selection}`, "Selects this video generator."),
|
|
8582
|
+
NAME_INPUT,
|
|
8583
|
+
input("asset_type", "string", true, "Asset classification stored in the Space."),
|
|
8584
|
+
PROMPT_INPUT,
|
|
8585
|
+
...parameterInputs
|
|
8586
|
+
];
|
|
8587
|
+
const operations = [{
|
|
8588
|
+
operation: "generate",
|
|
8589
|
+
tool: "generate_video",
|
|
8590
|
+
description: "Create a new video asset from text.",
|
|
8591
|
+
inputs: commonInputs
|
|
8592
|
+
}];
|
|
8593
|
+
if (VIDEO_MODEL_SUPPORTED_OPERATIONS[selection].includes("refine")) operations.push({
|
|
8594
|
+
operation: "refine",
|
|
8595
|
+
tool: "edit_video",
|
|
8596
|
+
description: "Create a new sibling variant from a completed video variant.",
|
|
8597
|
+
inputs: [
|
|
8598
|
+
SPACE_INPUT,
|
|
8599
|
+
fixedInput("generator_id", `video/${selection}`, "Selects this video generator."),
|
|
8600
|
+
input("asset_ref", "string", true, "Target video asset reference from find_assets."),
|
|
8601
|
+
input("source_variant_ref", "string", true, "Completed video variant to refine."),
|
|
8602
|
+
PROMPT_INPUT,
|
|
8603
|
+
...parameterInputs
|
|
8604
|
+
]
|
|
8605
|
+
});
|
|
8606
|
+
if (VIDEO_MODEL_SUPPORTED_OPERATIONS[selection].includes("derive")) operations.push({
|
|
8607
|
+
operation: "derive",
|
|
8608
|
+
tool: "generate_video",
|
|
8609
|
+
description: "Create a new video from completed image variants.",
|
|
8610
|
+
inputs: [...commonInputs, input("reference_variant_refs", "string_array", true, "Completed image variant references from find_assets or get_asset.", {
|
|
8611
|
+
minItems: 1,
|
|
8612
|
+
maxItems: maxReferences
|
|
8613
|
+
})]
|
|
8614
|
+
});
|
|
8615
|
+
const notes = isVeo ? [`Resolution support by tier: ${VIDEO_GENERATION_TIERS.map((tier) => `${tier}=${VIDEO_GENERATION_RESOLUTIONS_BY_TIER[tier].join("/")}`).join(", ")}.`, "Synchronized audio is always enabled."] : isOmni ? ["Resolution, duration, tier, and generated-audio options are not accepted."] : selection === "fal-seedance" ? ["Text-to-video only; generated audio is not supported."] : ["At most one completed image reference is accepted."];
|
|
8616
|
+
return {
|
|
8617
|
+
id: `video/${selection}`,
|
|
8618
|
+
label: VIDEO_MODEL_LABELS[selection],
|
|
8619
|
+
mediaKind: "video",
|
|
8620
|
+
provider: selection === "kling" ? "kling" : selection === "fal-seedance" ? "fal" : "google_ai",
|
|
8621
|
+
modelIds,
|
|
8622
|
+
defaultModelId: defaultModel,
|
|
8623
|
+
operations,
|
|
8624
|
+
referenceRules: {
|
|
8625
|
+
mediaKind: maxReferences > 0 ? "image" : null,
|
|
8626
|
+
completedOnly: maxReferences > 0,
|
|
8627
|
+
maxCount: maxReferences
|
|
8628
|
+
},
|
|
8629
|
+
notes
|
|
8630
|
+
};
|
|
8631
|
+
}
|
|
8632
|
+
function seedanceVideoGenerator(capability) {
|
|
8633
|
+
const fixedGenerator = fixedInput("generator_id", capability.generatorId, "Selects this exact Seedance 2 mode and tier.");
|
|
8634
|
+
const parameters = [
|
|
8635
|
+
input("aspect_ratio", "string", false, "Output aspect ratio; auto lets Seedance infer it.", {
|
|
8636
|
+
allowedValues: capability.aspectRatios,
|
|
8637
|
+
defaultValue: capability.defaultAspectRatio
|
|
8638
|
+
}),
|
|
8639
|
+
input("resolution", "string", false, "Output resolution.", {
|
|
8640
|
+
allowedValues: capability.resolutions,
|
|
8641
|
+
defaultValue: capability.defaultResolution
|
|
8642
|
+
}),
|
|
8643
|
+
input("duration", "string_or_integer", false, "Output seconds from 4 to 15, or auto.", {
|
|
8644
|
+
allowedValues: capability.durations,
|
|
8645
|
+
defaultValue: capability.defaultDuration
|
|
8646
|
+
}),
|
|
8647
|
+
input("generate_audio", "boolean", false, "Generate synchronized native audio.", {
|
|
8648
|
+
allowedValues: [true, false],
|
|
8649
|
+
defaultValue: capability.generateAudio.default
|
|
8650
|
+
}),
|
|
8651
|
+
input("bitrate_mode", "string", false, "Output bitrate quality.", {
|
|
8652
|
+
allowedValues: capability.bitrateModes,
|
|
8653
|
+
defaultValue: capability.defaultBitrateMode
|
|
8654
|
+
})
|
|
8655
|
+
];
|
|
8656
|
+
const common = [
|
|
8657
|
+
SPACE_INPUT,
|
|
8658
|
+
fixedGenerator,
|
|
8659
|
+
NAME_INPUT,
|
|
8660
|
+
input("asset_type", "string", true, "Asset classification stored in the Space."),
|
|
8661
|
+
PROMPT_INPUT,
|
|
8662
|
+
...parameters
|
|
8663
|
+
];
|
|
8664
|
+
const frameInputs = [input("start_frame_variant_ref", "string", true, "Completed image variant used as the authoritative first frame; cannot be combined with extended references."), input("end_frame_variant_ref", "string", false, "Completed image variant used as the authoritative final frame; cannot be combined with extended references.")];
|
|
8665
|
+
const referenceInputs = [
|
|
8666
|
+
input("image_reference_variant_refs", "string_array", false, "Ordered completed images addressed as @Image1 through @Image9 for soft subject, style, or geography guidance; not authoritative boundary frames.", {
|
|
8667
|
+
minItems: 1,
|
|
8668
|
+
maxItems: 9
|
|
8669
|
+
}),
|
|
8670
|
+
input("video_reference_variant_refs", "string_array", false, "Ordered completed videos addressed as @Video1 through @Video3.", {
|
|
8671
|
+
minItems: 1,
|
|
8672
|
+
maxItems: 3
|
|
8673
|
+
}),
|
|
8674
|
+
input("audio_reference_variant_refs", "string_array", false, "Ordered completed audio clips addressed as @Audio1 through @Audio3.", {
|
|
8675
|
+
minItems: 1,
|
|
8676
|
+
maxItems: 3
|
|
8677
|
+
})
|
|
8678
|
+
];
|
|
8679
|
+
const modeInputs = capability.mode === "frame" ? frameInputs : capability.mode === "reference" ? referenceInputs : [];
|
|
8680
|
+
const operations = capability.operations.filter((operation) => operation !== "refine").map((operation) => ({
|
|
8681
|
+
operation,
|
|
8682
|
+
tool: "generate_video",
|
|
8683
|
+
description: capability.mode === "text" ? "Create a video from text." : capability.mode === "frame" ? "Animate a required authoritative start frame and optional authoritative end frame; extended references cannot be combined with them." : "Direct a video with ordered image, video, and audio references; these guide generation but cannot serve as authoritative start/end frames.",
|
|
8684
|
+
inputs: [...common, ...modeInputs]
|
|
8685
|
+
}));
|
|
8686
|
+
if (capability.operations.includes("refine")) {
|
|
8687
|
+
const budget = getSeedance2ReferenceBudget(capability, "refine");
|
|
8688
|
+
const editReferenceInputs = referenceInputs.map((referenceInput) => referenceInput.name === "video_reference_variant_refs" ? {
|
|
8689
|
+
...referenceInput,
|
|
8690
|
+
maxItems: 2,
|
|
8691
|
+
description: "Up to two additional completed videos addressed as @Video2 and @Video3; the source video is @Video1."
|
|
8692
|
+
} : referenceInput);
|
|
8693
|
+
operations.push({
|
|
8694
|
+
operation: "refine",
|
|
8695
|
+
tool: "edit_video",
|
|
8696
|
+
description: "Edit or continue a completed video using it as @Video1 plus optional ordered references.",
|
|
8697
|
+
referenceLimits: {
|
|
8698
|
+
maxAdditionalCount: budget.maxAdditionalFiles,
|
|
8699
|
+
implicitSourceCount: 1,
|
|
8700
|
+
maxAdditionalByKind: budget.maxAdditionalByKind
|
|
8701
|
+
},
|
|
8702
|
+
inputs: [
|
|
8703
|
+
SPACE_INPUT,
|
|
8704
|
+
fixedGenerator,
|
|
8705
|
+
input("asset_ref", "string", true, "Target video asset reference from find_assets."),
|
|
8706
|
+
input("source_variant_ref", "string", true, "Completed target video used as @Video1."),
|
|
8707
|
+
PROMPT_INPUT,
|
|
8708
|
+
...parameters,
|
|
8709
|
+
...editReferenceInputs
|
|
8710
|
+
]
|
|
8711
|
+
});
|
|
8712
|
+
}
|
|
8713
|
+
return {
|
|
8714
|
+
id: capability.generatorId,
|
|
8715
|
+
label: capability.label,
|
|
8716
|
+
mediaKind: "video",
|
|
8717
|
+
provider: "fal",
|
|
8718
|
+
modelIds: [capability.endpointId],
|
|
8719
|
+
defaultModelId: capability.endpointId,
|
|
8720
|
+
operations,
|
|
8721
|
+
referenceRules: {
|
|
8722
|
+
mediaKind: capability.mode === "frame" ? "image" : null,
|
|
8723
|
+
completedOnly: capability.mode !== "text",
|
|
8724
|
+
maxCount: capability.maxReferenceFiles,
|
|
8725
|
+
maxTotalCount: capability.maxReferenceFiles,
|
|
8726
|
+
requiresVisualWithAudio: capability.requiresVisualReferenceWithAudio,
|
|
8727
|
+
modalities: capability.references.map((reference) => ({
|
|
8728
|
+
mediaKind: reference.mediaKind,
|
|
8729
|
+
minCount: reference.minCount,
|
|
8730
|
+
maxCount: reference.maxCount,
|
|
8731
|
+
promptLabel: reference.promptLabel,
|
|
8732
|
+
acceptedMimeTypes: reference.acceptedMimeTypes,
|
|
8733
|
+
maxBytesPerFile: reference.maxBytesPerFile,
|
|
8734
|
+
...reference.combinedMaxBytes !== void 0 ? { combinedMaxBytes: reference.combinedMaxBytes } : {},
|
|
8735
|
+
...reference.combinedDurationSeconds ? { combinedDurationSeconds: reference.combinedDurationSeconds } : {}
|
|
8736
|
+
}))
|
|
8737
|
+
},
|
|
8738
|
+
notes: [
|
|
8739
|
+
"Use compact variant references; binary media input is not accepted.",
|
|
8740
|
+
capability.mode === "reference" ? "Prompt labels are modality-specific and one-based: @ImageN, @VideoN, and @AudioN. @ImageN guides content, style, or geography but is not an authoritative start/end frame." : capability.mode === "frame" ? "The start and end images are authoritative boundary frames. The provider does not allow extended image, video, or audio references in this mode." : "This mode rejects all reference inputs.",
|
|
8741
|
+
"Seedance 2 cannot combine authoritative start/end frames with extended multimodal references in one request.",
|
|
8742
|
+
capability.resolutions.includes("4k") ? "Standard supports 480p, 720p, 1080p, and 4K output." : "Fast supports 480p and 720p output."
|
|
8743
|
+
]
|
|
8744
|
+
};
|
|
8745
|
+
}
|
|
8746
|
+
function audioGenerator(input_) {
|
|
8747
|
+
const inputs = [
|
|
8748
|
+
SPACE_INPUT,
|
|
8749
|
+
fixedInput("generator_id", input_.id, "Selects this audio generator and mode."),
|
|
8750
|
+
NAME_INPUT,
|
|
8751
|
+
PROMPT_INPUT
|
|
8752
|
+
];
|
|
8753
|
+
if (input_.provider === "elevenlabs" && (input_.assetType === "speech" || input_.assetType === "dialogue")) inputs.push(input("model", "string", false, "Optional ElevenLabs model override.", { defaultValue: input_.modelId }));
|
|
8754
|
+
if (input_.assetType === "speech") inputs.push(input("voice_id", "string", true, "Voice ID returned by list_voices."));
|
|
8755
|
+
else if (input_.assetType === "dialogue") inputs.push(input("dialogue_voice_ids", "string_array", true, "One voice ID per distinct speaker, in first-appearance order.", { minItems: 2 }));
|
|
8756
|
+
const notes = input_.assetType === "dialogue" ? ["Prompt must contain at least two `Speaker: line` entries and at least two distinct speakers."] : input_.assetType === "speech" ? ["Prompt must be plain speech text, not `Speaker: line` dialogue."] : ["Prompt describes the desired audio; voice inputs and image references are not accepted."];
|
|
8757
|
+
return {
|
|
8758
|
+
id: input_.id,
|
|
8759
|
+
label: input_.label,
|
|
8760
|
+
mediaKind: "audio",
|
|
8761
|
+
provider: input_.provider,
|
|
8762
|
+
modelIds: [input_.modelId],
|
|
8763
|
+
defaultModelId: input_.modelId,
|
|
8764
|
+
operations: [{
|
|
8765
|
+
operation: "generate",
|
|
8766
|
+
tool: "generate_audio",
|
|
8767
|
+
description: `Create a new ${input_.assetType} audio asset.`,
|
|
8768
|
+
inputs
|
|
8769
|
+
}],
|
|
8770
|
+
referenceRules: {
|
|
8771
|
+
mediaKind: null,
|
|
8772
|
+
completedOnly: false,
|
|
8773
|
+
maxCount: 0
|
|
8774
|
+
},
|
|
8775
|
+
notes
|
|
8776
|
+
};
|
|
8777
|
+
}
|
|
8778
|
+
function getGeneratorCatalog(overrides = {}) {
|
|
8779
|
+
const elevenLabsSpeech = overrides.elevenLabsSpeech ?? "eleven_v3";
|
|
8780
|
+
const elevenLabsMusic = overrides.elevenLabsMusic ?? "music_v1";
|
|
8781
|
+
const elevenLabsSfx = overrides.elevenLabsSfx ?? "eleven_text_to_sound_v2";
|
|
8782
|
+
const lyria = overrides.lyria ?? "lyria-3-clip-preview";
|
|
8783
|
+
return [
|
|
8784
|
+
...Object.values(IMAGE_MODEL_CAPABILITIES).map(imageGenerator),
|
|
8785
|
+
...VIDEO_MODEL_SELECTIONS.map(videoGenerator),
|
|
8786
|
+
...SEEDANCE_2_SELECTIONS.map((selection) => seedanceVideoGenerator(SEEDANCE_2_CAPABILITIES[selection])),
|
|
8787
|
+
audioGenerator({
|
|
8788
|
+
id: "audio/elevenlabs-speech",
|
|
8789
|
+
label: "ElevenLabs Speech",
|
|
8790
|
+
provider: "elevenlabs",
|
|
8791
|
+
assetType: "speech",
|
|
8792
|
+
modelId: elevenLabsSpeech
|
|
8793
|
+
}),
|
|
8794
|
+
audioGenerator({
|
|
8795
|
+
id: "audio/elevenlabs-dialogue",
|
|
8796
|
+
label: "ElevenLabs Dialogue",
|
|
8797
|
+
provider: "elevenlabs",
|
|
8798
|
+
assetType: "dialogue",
|
|
8799
|
+
modelId: elevenLabsSpeech
|
|
8800
|
+
}),
|
|
8801
|
+
audioGenerator({
|
|
8802
|
+
id: "audio/elevenlabs-music",
|
|
8803
|
+
label: "ElevenLabs Music",
|
|
8804
|
+
provider: "elevenlabs",
|
|
8805
|
+
assetType: "music",
|
|
8806
|
+
modelId: elevenLabsMusic
|
|
8807
|
+
}),
|
|
8808
|
+
audioGenerator({
|
|
8809
|
+
id: "audio/elevenlabs-sfx",
|
|
8810
|
+
label: "ElevenLabs Sound Effects",
|
|
8811
|
+
provider: "elevenlabs",
|
|
8812
|
+
assetType: "sfx",
|
|
8813
|
+
modelId: elevenLabsSfx
|
|
8814
|
+
}),
|
|
8815
|
+
audioGenerator({
|
|
8816
|
+
id: "audio/lyria-music",
|
|
8817
|
+
label: "Lyria Music",
|
|
8818
|
+
provider: "lyria",
|
|
8819
|
+
assetType: "music",
|
|
8820
|
+
modelId: lyria
|
|
8821
|
+
})
|
|
8822
|
+
];
|
|
8823
|
+
}
|
|
8824
|
+
function getGeneratorDefinition(id, overrides = {}) {
|
|
8825
|
+
return getGeneratorCatalog(overrides).find((generator) => generator.id === id);
|
|
8826
|
+
}
|
|
8827
|
+
//#endregion
|
|
8828
|
+
//#region src/shared/generationReferences.ts
|
|
8829
|
+
function isGenerationReference(value) {
|
|
8830
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
8831
|
+
const reference = value;
|
|
8832
|
+
return typeof reference.variantId === "string" && reference.variantId.length > 0 && (reference.mediaKind === "image" || reference.mediaKind === "video" || reference.mediaKind === "audio") && typeof reference.storageKey === "string" && reference.storageKey.length > 0 && Number.isInteger(reference.sequenceIndex) && Number.isInteger(reference.modalityIndex) && (reference.mimeType === void 0 || typeof reference.mimeType === "string") && (reference.sizeBytes === void 0 || typeof reference.sizeBytes === "number") && (reference.width === void 0 || typeof reference.width === "number") && (reference.height === void 0 || typeof reference.height === "number") && (reference.durationMs === void 0 || typeof reference.durationMs === "number");
|
|
8833
|
+
}
|
|
8834
|
+
function areGenerationReferencesIndexed(value) {
|
|
8835
|
+
if (!Array.isArray(value)) return false;
|
|
8836
|
+
const modalityCounts = {
|
|
8837
|
+
image: 0,
|
|
8838
|
+
video: 0,
|
|
8839
|
+
audio: 0
|
|
8840
|
+
};
|
|
8841
|
+
return value.every((reference, sequenceIndex) => {
|
|
8842
|
+
if (!isGenerationReference(reference) || reference.sequenceIndex !== sequenceIndex) return false;
|
|
8843
|
+
const expectedModalityIndex = modalityCounts[reference.mediaKind]++;
|
|
8844
|
+
return reference.modalityIndex === expectedModalityIndex;
|
|
8845
|
+
});
|
|
8846
|
+
}
|
|
8847
|
+
//#endregion
|
|
8848
|
+
//#region src/shared/draftMapping.ts
|
|
8849
|
+
/** Generator input names map to the canonical camel-case keys stored in recipes. */
|
|
8850
|
+
var DRAFT_RECIPE_INPUT_KEYS = {
|
|
8851
|
+
asset_type: "assetType",
|
|
8852
|
+
prompt: "prompt",
|
|
8853
|
+
aspect_ratio: "aspectRatio",
|
|
8854
|
+
image_size: "imageSize",
|
|
8855
|
+
model: "model",
|
|
8856
|
+
voice_id: "voiceId",
|
|
8857
|
+
dialogue_voice_ids: "dialogueVoiceIds",
|
|
8858
|
+
generate_audio: "generateAudio",
|
|
8859
|
+
video_resolution: "videoResolution",
|
|
8860
|
+
resolution: "videoResolution",
|
|
8861
|
+
video_duration_seconds: "videoDurationSeconds",
|
|
8862
|
+
video_tier: "videoTier",
|
|
8863
|
+
duration: "seedanceDuration",
|
|
8864
|
+
bitrate_mode: "seedanceBitrateMode"
|
|
8865
|
+
};
|
|
8866
|
+
var DRAFT_REFERENCE_FIELD = /(?:_variant_refs?|VariantRefs?)$/;
|
|
8867
|
+
/**
|
|
8868
|
+
* The one slot-naming convention used while authoring and resolving Bindings.
|
|
8869
|
+
* Unknown reference slots inherit the Draft output kind.
|
|
8870
|
+
*/
|
|
8871
|
+
function mediaKindForDraftSlot(slot, fallback) {
|
|
8872
|
+
if (slot.startsWith("image_") || slot === "start_frame_variant_ref" || slot === "end_frame_variant_ref" || slot === "reference_variant_refs") return "image";
|
|
8873
|
+
if (slot.startsWith("video_")) return "video";
|
|
8874
|
+
if (slot.startsWith("audio_")) return "audio";
|
|
8875
|
+
return fallback;
|
|
8876
|
+
}
|
|
8877
|
+
function generatorIdForDraftRecipe(mediaMode, recipe) {
|
|
8878
|
+
if (mediaMode === "image") {
|
|
8879
|
+
if (recipe.modelProvider === "custom") throw new Error("Custom-provider image Recipes do not map to a Draft generator");
|
|
8880
|
+
const model = typeof recipe.model === "string" ? recipe.model : "pro";
|
|
8881
|
+
if (!isImageModelSelection(model) && !isImageModelId(model)) throw new Error(`Stored image model ${model} does not map to a Draft generator`);
|
|
8882
|
+
return `image/${getImageModelSelection(model)}`;
|
|
8883
|
+
}
|
|
8884
|
+
if (mediaMode === "video") {
|
|
8885
|
+
const model = typeof recipe.model === "string" ? recipe.model : "veo-3.1";
|
|
8886
|
+
const seedance = getSeedance2CapabilityByEndpoint(model);
|
|
8887
|
+
if (seedance) return seedance.generatorId;
|
|
8888
|
+
const selection = getVideoModelSelectionForModel(model);
|
|
8889
|
+
if (!selection) throw new Error(`Stored video model ${model} does not map to a Draft generator`);
|
|
8890
|
+
return `video/${selection}`;
|
|
8891
|
+
}
|
|
8892
|
+
if (mediaMode === "speech") return "audio/elevenlabs-speech";
|
|
8893
|
+
if (mediaMode === "dialogue") return "audio/elevenlabs-dialogue";
|
|
8894
|
+
if (mediaMode === "sfx") return "audio/elevenlabs-sfx";
|
|
8895
|
+
return recipe.musicProvider === "lyria" ? "audio/lyria-music" : "audio/elevenlabs-music";
|
|
8896
|
+
}
|
|
8897
|
+
function mediaModeForDraftRecipe(mediaKind, assetType) {
|
|
8898
|
+
if (mediaKind === "image" || mediaKind === "video") return mediaKind;
|
|
8899
|
+
return getForgeModeForAudioAssetType(assetType);
|
|
8900
|
+
}
|
|
8901
|
+
function buildDraftMapping(args) {
|
|
8902
|
+
const { name, mediaMode, generatorId, recipe, references, destinationKind, destinationAssetId, sourceVariantId } = args;
|
|
8903
|
+
const operation = destinationKind === "sibling" ? "refine" : references.length > 0 ? "derive" : "generate";
|
|
8904
|
+
const operationDefinition = getGeneratorDefinition(generatorId)?.operations.find((candidate) => candidate.operation === operation);
|
|
8905
|
+
if (!operationDefinition) throw new Error(`${generatorId} does not support ${operation} drafts`);
|
|
8906
|
+
const recipeTemplate = { operation };
|
|
8907
|
+
for (const input of operationDefinition.inputs) {
|
|
8908
|
+
const key = DRAFT_RECIPE_INPUT_KEYS[input.name];
|
|
8909
|
+
if (!key) continue;
|
|
8910
|
+
const value = recipe[key];
|
|
8911
|
+
if (value !== void 0) recipeTemplate[key] = value;
|
|
8912
|
+
}
|
|
8913
|
+
const availableSlots = operationDefinition.inputs.filter((input) => DRAFT_REFERENCE_FIELD.test(input.name)).map((input) => input.name);
|
|
8914
|
+
const bindings = [];
|
|
8915
|
+
if (destinationKind === "sibling" && sourceVariantId && availableSlots.includes("source_variant_ref")) bindings.push({
|
|
8916
|
+
slot: "source_variant_ref",
|
|
8917
|
+
sourceKind: "variant",
|
|
8918
|
+
sourceVariantId,
|
|
8919
|
+
sortIndex: 0
|
|
8920
|
+
});
|
|
8921
|
+
const outputMediaKind = getMediaKindForForgeMode(mediaMode);
|
|
8922
|
+
const additionalSlots = availableSlots.filter((slot) => slot !== "source_variant_ref");
|
|
8923
|
+
const usedScalarSlots = /* @__PURE__ */ new Set();
|
|
8924
|
+
for (const [index, reference] of references.entries()) {
|
|
8925
|
+
const targetSlot = additionalSlots.filter((slot) => mediaKindForDraftSlot(slot, outputMediaKind) === reference.mediaKind).find((slot) => slot.endsWith("_refs") || !usedScalarSlots.has(slot));
|
|
8926
|
+
if (!targetSlot) throw new Error(`No ${reference.mediaKind} input slot is available for ${generatorId}`);
|
|
8927
|
+
if (!targetSlot.endsWith("_refs")) usedScalarSlots.add(targetSlot);
|
|
8928
|
+
bindings.push({
|
|
8929
|
+
id: reference.id,
|
|
8930
|
+
slot: targetSlot,
|
|
8931
|
+
sourceKind: reference.sourceKind,
|
|
8932
|
+
sourceVariantId: reference.sourceVariantId,
|
|
8933
|
+
sourceAssetId: reference.sourceAssetId,
|
|
8934
|
+
sourceDraftId: reference.sourceDraftId,
|
|
8935
|
+
sortIndex: index
|
|
8936
|
+
});
|
|
8937
|
+
}
|
|
8938
|
+
return {
|
|
8939
|
+
name,
|
|
8940
|
+
mediaMode,
|
|
8941
|
+
generatorId,
|
|
8942
|
+
recipeTemplate,
|
|
8943
|
+
destinationKind,
|
|
8944
|
+
destinationAssetId: destinationKind === "sibling" ? destinationAssetId : null,
|
|
8945
|
+
bindings
|
|
8946
|
+
};
|
|
8947
|
+
}
|
|
8948
|
+
function materializeDraftFromVariant(args) {
|
|
8949
|
+
const storedRecipe = parseStoredRecipe$1(args.recipe);
|
|
8950
|
+
if (!areGenerationReferencesIndexed(storedRecipe.references)) throw new Error("Variant recipe has invalid references");
|
|
8951
|
+
const mediaMode = args.mediaMode ?? mediaModeForDraftRecipe(args.variantMediaKind, args.assetType ?? stringValue(storedRecipe.assetType));
|
|
8952
|
+
const recipe = args.recipeOverride ?? storedRecipe;
|
|
8953
|
+
const generatorId = args.generatorId ?? generatorIdForDraftRecipe(mediaMode, storedRecipe);
|
|
8954
|
+
const storedOperation = stringValue(storedRecipe.operation);
|
|
8955
|
+
const destinationKind = args.destinationKind ?? (storedOperation === "refine" ? "sibling" : "new_asset");
|
|
8956
|
+
const storedReferences = storedRecipe.references;
|
|
8957
|
+
if (storedOperation === "refine" && destinationKind === "sibling" && storedReferences.length === 0) throw new Error("Stored refine Recipe has no source Variant reference");
|
|
8958
|
+
const preservesStoredRefine = storedOperation === "refine" && destinationKind === "sibling";
|
|
8959
|
+
const sourceVariantId = preservesStoredRefine ? storedReferences[0]?.variantId : destinationKind === "sibling" ? args.variantId : void 0;
|
|
8960
|
+
const additionalReferences = preservesStoredRefine ? storedReferences.slice(1) : storedReferences;
|
|
8961
|
+
return buildDraftMapping({
|
|
8962
|
+
name: args.name?.trim() || args.assetName,
|
|
8963
|
+
mediaMode,
|
|
8964
|
+
generatorId,
|
|
8965
|
+
recipe,
|
|
8966
|
+
references: additionalReferences.map((reference) => ({
|
|
8967
|
+
mediaKind: reference.mediaKind,
|
|
8968
|
+
sourceKind: "variant",
|
|
8969
|
+
sourceVariantId: reference.variantId
|
|
8970
|
+
})),
|
|
8971
|
+
destinationKind,
|
|
8972
|
+
destinationAssetId: destinationKind === "sibling" ? args.destinationAssetId ?? args.assetId : null,
|
|
8973
|
+
sourceVariantId
|
|
8974
|
+
});
|
|
8975
|
+
}
|
|
8976
|
+
function parseStoredRecipe$1(value) {
|
|
8977
|
+
let parsed = value;
|
|
8978
|
+
if (typeof value === "string") try {
|
|
8979
|
+
parsed = JSON.parse(value);
|
|
8980
|
+
} catch {
|
|
8981
|
+
throw new Error("Variant recipe is not valid JSON");
|
|
8982
|
+
}
|
|
8983
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("Variant recipe is not a JSON object");
|
|
8984
|
+
return parsed;
|
|
8985
|
+
}
|
|
8986
|
+
function stringValue(value) {
|
|
8987
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
8988
|
+
}
|
|
8989
|
+
//#endregion
|
|
8363
8990
|
//#region src/cli/commands/drafts.ts
|
|
8991
|
+
var CLI_DRAFT_OPTIONS = {
|
|
8992
|
+
list: [],
|
|
8993
|
+
show: [],
|
|
8994
|
+
create: [
|
|
8995
|
+
"from",
|
|
8996
|
+
"name",
|
|
8997
|
+
"media",
|
|
8998
|
+
"generator",
|
|
8999
|
+
"recipe",
|
|
9000
|
+
"destination",
|
|
9001
|
+
"asset",
|
|
9002
|
+
"x",
|
|
9003
|
+
"y"
|
|
9004
|
+
],
|
|
9005
|
+
update: [
|
|
9006
|
+
"name",
|
|
9007
|
+
"media",
|
|
9008
|
+
"generator",
|
|
9009
|
+
"recipe",
|
|
9010
|
+
"destination",
|
|
9011
|
+
"asset",
|
|
9012
|
+
"x",
|
|
9013
|
+
"y"
|
|
9014
|
+
],
|
|
9015
|
+
delete: [],
|
|
9016
|
+
run: ["request-id", "wait"]
|
|
9017
|
+
};
|
|
8364
9018
|
var defaultDeps$7 = {
|
|
8365
9019
|
loadConfig: loadStoredConfig,
|
|
8366
9020
|
loadProjectConfig,
|
|
8367
9021
|
createMutationClient: (env, spaceId) => WebSocketClient.create(env, spaceId),
|
|
8368
9022
|
print: console.log
|
|
8369
9023
|
};
|
|
9024
|
+
var defaultGraphDeps = {
|
|
9025
|
+
loadConfig: loadStoredConfig,
|
|
9026
|
+
loadProjectConfig,
|
|
9027
|
+
createClient: (env, spaceId) => WebSocketClient.create(env, spaceId),
|
|
9028
|
+
print: console.log
|
|
9029
|
+
};
|
|
8370
9030
|
async function handleDrafts(parsed) {
|
|
8371
9031
|
try {
|
|
8372
9032
|
await executeDrafts(parsed);
|
|
@@ -8383,9 +9043,17 @@ async function handleBindings(parsed) {
|
|
|
8383
9043
|
process$1.exitCode = 1;
|
|
8384
9044
|
}
|
|
8385
9045
|
}
|
|
9046
|
+
async function handleGraph(parsed) {
|
|
9047
|
+
try {
|
|
9048
|
+
await executeGraph(parsed);
|
|
9049
|
+
} catch (error) {
|
|
9050
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
9051
|
+
process$1.exitCode = 1;
|
|
9052
|
+
}
|
|
9053
|
+
}
|
|
8386
9054
|
async function executeDrafts(parsed, deps = defaultDeps$7) {
|
|
8387
9055
|
const subcommand = parsed.positionals[0];
|
|
8388
|
-
if (!subcommand) throw new Error("Drafts command is required: list, create, update, or
|
|
9056
|
+
if (!subcommand) throw new Error("Drafts command is required: list, show, create, update, delete, or run");
|
|
8389
9057
|
rejectUnknownOptions("drafts", subcommand, parsed.options);
|
|
8390
9058
|
const ctx = await buildContext$3(parsed, deps);
|
|
8391
9059
|
if (subcommand === "list") {
|
|
@@ -8395,12 +9063,75 @@ async function executeDrafts(parsed, deps = defaultDeps$7) {
|
|
|
8395
9063
|
return drafts;
|
|
8396
9064
|
}
|
|
8397
9065
|
if (subcommand === "create") {
|
|
8398
|
-
const
|
|
9066
|
+
const fromVariantRef = optionValue$2(parsed.options.from);
|
|
9067
|
+
const name = optionValue$2(parsed.options.name) ?? parsed.positionals.slice(1).join(" ").trim();
|
|
9068
|
+
if (fromVariantRef) {
|
|
9069
|
+
const state = await readDraftState(ctx, deps);
|
|
9070
|
+
const sourceVariantId = requireExactVariantRef$1(fromVariantRef, state);
|
|
9071
|
+
const sourceVariant = state.variants.find((variant) => variant.id === sourceVariantId);
|
|
9072
|
+
const sourceAsset = sourceVariant ? state.assets.find((asset) => asset.id === sourceVariant.asset_id) : void 0;
|
|
9073
|
+
if (!sourceVariant || !sourceAsset) throw new Error("Source Variant is unavailable");
|
|
9074
|
+
if (sourceVariant.status !== "completed") throw new Error("Source Variant must be completed");
|
|
9075
|
+
const destinationKind = parseDestination(parsed.options.destination);
|
|
9076
|
+
const destinationAssetRef = optionValue$2(parsed.options.asset);
|
|
9077
|
+
const mapped = materializeDraftFromVariant({
|
|
9078
|
+
variantId: sourceVariant.id,
|
|
9079
|
+
variantMediaKind: sourceVariant.media_kind,
|
|
9080
|
+
recipe: sourceVariant.recipe,
|
|
9081
|
+
assetName: sourceAsset.name,
|
|
9082
|
+
assetType: sourceAsset.type,
|
|
9083
|
+
assetId: sourceAsset.id,
|
|
9084
|
+
name,
|
|
9085
|
+
mediaMode: parseMediaMode(parsed.options.media),
|
|
9086
|
+
generatorId: optionValue$2(parsed.options.generator),
|
|
9087
|
+
recipeOverride: parseRecipe(parsed.options.recipe),
|
|
9088
|
+
destinationKind,
|
|
9089
|
+
destinationAssetId: destinationAssetRef ? requireAssetRef(destinationAssetRef, state.assets) : void 0
|
|
9090
|
+
});
|
|
9091
|
+
for (const binding of mapped.bindings) {
|
|
9092
|
+
const variantId = binding.sourceVariantId;
|
|
9093
|
+
if (variantId && !state.variants.some((variant) => variant.id === variantId)) throw new Error(`Variant recipe reference ${variantId} is unavailable`);
|
|
9094
|
+
}
|
|
9095
|
+
const created = await withClient(ctx, deps, async (client) => {
|
|
9096
|
+
const draft = await client.createDraft({
|
|
9097
|
+
name: mapped.name,
|
|
9098
|
+
mediaMode: mapped.mediaMode,
|
|
9099
|
+
generatorId: mapped.generatorId,
|
|
9100
|
+
recipeTemplate: mapped.recipeTemplate,
|
|
9101
|
+
destinationKind: mapped.destinationKind,
|
|
9102
|
+
destinationAssetId: mapped.destinationAssetId,
|
|
9103
|
+
canvasX: parseNullableFinite(parsed.options.x, "--x"),
|
|
9104
|
+
canvasY: parseNullableFinite(parsed.options.y, "--y")
|
|
9105
|
+
});
|
|
9106
|
+
const bindings = [];
|
|
9107
|
+
try {
|
|
9108
|
+
for (const binding of mapped.bindings) bindings.push(await client.setBinding({
|
|
9109
|
+
draftId: draft.id,
|
|
9110
|
+
...binding
|
|
9111
|
+
}));
|
|
9112
|
+
} catch (error) {
|
|
9113
|
+
await client.deleteDraft(draft.id);
|
|
9114
|
+
throw error;
|
|
9115
|
+
}
|
|
9116
|
+
return {
|
|
9117
|
+
draft,
|
|
9118
|
+
bindings
|
|
9119
|
+
};
|
|
9120
|
+
});
|
|
9121
|
+
const resultState = {
|
|
9122
|
+
...state,
|
|
9123
|
+
drafts: [...state.drafts, created.draft],
|
|
9124
|
+
bindings: [...state.bindings, ...created.bindings]
|
|
9125
|
+
};
|
|
9126
|
+
const result = publicDraft(created.draft, resultState);
|
|
9127
|
+
printJsonOrValue(parsed, deps, result, () => deps.print(`Created Draft ${result.draftRef}`));
|
|
9128
|
+
return created.draft;
|
|
9129
|
+
}
|
|
8399
9130
|
const mediaMode = parseMediaMode(parsed.options.media);
|
|
8400
9131
|
const generatorId = optionValue$2(parsed.options.generator);
|
|
8401
9132
|
const recipeTemplate = parseRecipe(parsed.options.recipe);
|
|
8402
9133
|
const destinationKind = parseDestination(parsed.options.destination);
|
|
8403
|
-
if (!name || !mediaMode || !generatorId || recipeTemplate === void 0 || !destinationKind) throw new Error("Usage: makefx drafts create \"<name>\" --media <mode> --generator <id> --recipe <json> --destination new_asset|sibling [--asset <asset-ref>]");
|
|
9134
|
+
if (!name || !mediaMode || !generatorId || recipeTemplate === void 0 || !destinationKind) throw new Error("Usage: makefx drafts create \"<name>\" --media <mode> --generator <id> --recipe <json> --destination new_asset|sibling [--asset <asset-ref>], or makefx drafts create --from <variant-ref> [--name <name>]");
|
|
8404
9135
|
const state = await readDraftState(ctx, deps);
|
|
8405
9136
|
const destinationAssetRef = optionValue$2(parsed.options.asset);
|
|
8406
9137
|
const destinationAssetId = destinationAssetRef ? requireAssetRef(destinationAssetRef, state.assets) : null;
|
|
@@ -8425,6 +9156,52 @@ async function executeDrafts(parsed, deps = defaultDeps$7) {
|
|
|
8425
9156
|
if (!draftRef) throw new Error(`Usage: makefx drafts ${subcommand} <draft-ref>`);
|
|
8426
9157
|
const state = await readDraftState(ctx, deps);
|
|
8427
9158
|
const draftId = requireDraftRef(draftRef, state.drafts);
|
|
9159
|
+
if (subcommand === "show") {
|
|
9160
|
+
const draft = state.drafts.find((candidate) => candidate.id === draftId);
|
|
9161
|
+
if (!draft) throw new Error("Draft is unavailable");
|
|
9162
|
+
const result = publicDraft(draft, state);
|
|
9163
|
+
printJsonOrValue(parsed, deps, result, () => printDraft(result, deps.print));
|
|
9164
|
+
return result;
|
|
9165
|
+
}
|
|
9166
|
+
if (subcommand === "run") {
|
|
9167
|
+
const requestId = optionValue$2(parsed.options["request-id"]) ?? crypto.randomUUID();
|
|
9168
|
+
const waitSeconds = parsed.options.wait === void 0 ? void 0 : parseGraphWaitSeconds(parsed.options.wait);
|
|
9169
|
+
const run = await withClient(ctx, deps, async (client) => {
|
|
9170
|
+
if (!client.runDraft) throw new Error("The connected client does not support Draft runs");
|
|
9171
|
+
if (waitSeconds !== void 0 && !client.followVariant) throw new Error("The connected client does not support waiting for Draft runs");
|
|
9172
|
+
let outcomePromise;
|
|
9173
|
+
const started = await client.runDraft(draftId, requestId, waitSeconds === void 0 ? void 0 : (runStarted) => {
|
|
9174
|
+
if (runStarted.status !== "completed" && runStarted.status !== "failed") outcomePromise = client.followVariant({
|
|
9175
|
+
variantId: runStarted.variantId,
|
|
9176
|
+
requestId,
|
|
9177
|
+
timeoutMs: waitSeconds * 1e3
|
|
9178
|
+
});
|
|
9179
|
+
});
|
|
9180
|
+
if (waitSeconds === void 0 || started.status === "completed" || started.status === "failed") return {
|
|
9181
|
+
started,
|
|
9182
|
+
terminalStatus: started.status
|
|
9183
|
+
};
|
|
9184
|
+
if (!outcomePromise) throw new Error("Draft run wait was not initialized");
|
|
9185
|
+
return {
|
|
9186
|
+
started,
|
|
9187
|
+
terminalStatus: (await outcomePromise).success ? "completed" : "failed"
|
|
9188
|
+
};
|
|
9189
|
+
});
|
|
9190
|
+
const updatedState = await readDraftState(ctx, deps);
|
|
9191
|
+
const variantRef = variantRefForId(run.started.variantId, updatedState.assets, updatedState.variants);
|
|
9192
|
+
if (!variantRef) throw new Error("Draft run Variant is unavailable");
|
|
9193
|
+
const result = {
|
|
9194
|
+
draftRef,
|
|
9195
|
+
requestId,
|
|
9196
|
+
variantRef,
|
|
9197
|
+
status: run.terminalStatus
|
|
9198
|
+
};
|
|
9199
|
+
printJsonOrValue(parsed, deps, result, () => {
|
|
9200
|
+
deps.print(`${parsed.options.wait === void 0 ? "Started" : "Finished"} ${draftRef} (${run.terminalStatus})`);
|
|
9201
|
+
if (variantRef) deps.print(` Variant: ${variantRef}`);
|
|
9202
|
+
});
|
|
9203
|
+
return result;
|
|
9204
|
+
}
|
|
8428
9205
|
if (subcommand === "update") {
|
|
8429
9206
|
const destinationAssetRef = optionValue$2(parsed.options.asset);
|
|
8430
9207
|
const changes = {
|
|
@@ -8495,6 +9272,47 @@ async function executeBindings(parsed, deps = defaultDeps$7) {
|
|
|
8495
9272
|
printJsonOrValue(parsed, deps, publicBinding(binding, state), () => deps.print(`Set ${slot}[${sortIndex}] on ${draftRef}`));
|
|
8496
9273
|
return binding;
|
|
8497
9274
|
}
|
|
9275
|
+
async function executeGraph(parsed, deps = defaultGraphDeps) {
|
|
9276
|
+
const subcommand = parsed.positionals[0];
|
|
9277
|
+
if (subcommand !== "run" && subcommand !== "status" && subcommand !== "cancel") throw new Error("Graph command is required: run, status, or cancel");
|
|
9278
|
+
rejectGraphUnknownOptions(subcommand, parsed.options);
|
|
9279
|
+
const ctx = await buildContext$3(parsed, deps);
|
|
9280
|
+
const state = await readDraftState(ctx, { createMutationClient: deps.createClient });
|
|
9281
|
+
const client = await deps.createClient(ctx.env, ctx.spaceId);
|
|
9282
|
+
await client.connect();
|
|
9283
|
+
try {
|
|
9284
|
+
if (subcommand === "status" || subcommand === "cancel") {
|
|
9285
|
+
const runRef = parsed.positionals[1];
|
|
9286
|
+
if (!runRef) throw new Error(`Usage: makefx graph ${subcommand} <graph-run-ref>`);
|
|
9287
|
+
const current = await client.getGraphRunStatus(runRef);
|
|
9288
|
+
const status = subcommand === "cancel" ? await client.cancelGraphRun(current.run.id) : current;
|
|
9289
|
+
const result = publicGraphRun(status.run, status.drafts, state);
|
|
9290
|
+
printJsonOrValue(parsed, deps, result, () => {
|
|
9291
|
+
if (subcommand === "cancel") deps.print(`Cancelled pending work in ${runRef}`);
|
|
9292
|
+
printGraphRun(result, deps.print);
|
|
9293
|
+
});
|
|
9294
|
+
return result;
|
|
9295
|
+
}
|
|
9296
|
+
const draftRefs = parsed.positionals.slice(1);
|
|
9297
|
+
if (draftRefs.length === 0) throw new Error("Usage: makefx graph run <draft-ref> [draft-ref...] [--upstream] [--downstream] [--from-scratch] [--wait]");
|
|
9298
|
+
const requestId = optionValue$2(parsed.options["request-id"]) ?? crypto.randomUUID();
|
|
9299
|
+
let status = await client.runGraph({
|
|
9300
|
+
draftIds: draftRefs.map((draftRef) => requireDraftRef(draftRef, state.drafts)),
|
|
9301
|
+
requestId,
|
|
9302
|
+
includeUpstream: parsed.options.upstream === "true",
|
|
9303
|
+
includeDownstream: parsed.options.downstream === "true",
|
|
9304
|
+
fromScratch: parsed.options["from-scratch"] === "true"
|
|
9305
|
+
});
|
|
9306
|
+
const runRef = createGraphRunRef(status.run.id);
|
|
9307
|
+
if (parsed.options.wait !== void 0 && status.run.status === "running") status = await client.waitForGraphRun(runRef, status.run.id, parseGraphWaitSeconds(parsed.options.wait) * 1e3);
|
|
9308
|
+
const freshState = await readDraftState(ctx, { createMutationClient: deps.createClient });
|
|
9309
|
+
const result = publicGraphRun(status.run, status.drafts, freshState);
|
|
9310
|
+
printJsonOrValue(parsed, deps, result, () => printGraphRun(result, deps.print));
|
|
9311
|
+
return result;
|
|
9312
|
+
} finally {
|
|
9313
|
+
client.disconnect();
|
|
9314
|
+
}
|
|
9315
|
+
}
|
|
8498
9316
|
async function buildContext$3(parsed, deps) {
|
|
8499
9317
|
const project = await deps.loadProjectConfig();
|
|
8500
9318
|
const env = resolveCommandEnvironment(parsed, project);
|
|
@@ -8655,29 +9473,7 @@ function rejectUnknownOptions(noun, subcommand, options) {
|
|
|
8655
9473
|
"local",
|
|
8656
9474
|
"json"
|
|
8657
9475
|
];
|
|
8658
|
-
const commands = noun === "drafts" ? {
|
|
8659
|
-
list: [],
|
|
8660
|
-
create: [
|
|
8661
|
-
"media",
|
|
8662
|
-
"generator",
|
|
8663
|
-
"recipe",
|
|
8664
|
-
"destination",
|
|
8665
|
-
"asset",
|
|
8666
|
-
"x",
|
|
8667
|
-
"y"
|
|
8668
|
-
],
|
|
8669
|
-
update: [
|
|
8670
|
-
"name",
|
|
8671
|
-
"media",
|
|
8672
|
-
"generator",
|
|
8673
|
-
"recipe",
|
|
8674
|
-
"destination",
|
|
8675
|
-
"asset",
|
|
8676
|
-
"x",
|
|
8677
|
-
"y"
|
|
8678
|
-
],
|
|
8679
|
-
delete: []
|
|
8680
|
-
} : {
|
|
9476
|
+
const commands = noun === "drafts" ? CLI_DRAFT_OPTIONS : {
|
|
8681
9477
|
set: [
|
|
8682
9478
|
"source",
|
|
8683
9479
|
"ref",
|
|
@@ -8689,6 +9485,50 @@ function rejectUnknownOptions(noun, subcommand, options) {
|
|
|
8689
9485
|
const unknown = Object.keys(options).find((name) => !allowed.has(name));
|
|
8690
9486
|
if (unknown) throw new Error(`Unknown option for ${noun} ${subcommand}: --${unknown}`);
|
|
8691
9487
|
}
|
|
9488
|
+
function rejectGraphUnknownOptions(subcommand, options) {
|
|
9489
|
+
const allowed = new Set([...[
|
|
9490
|
+
"space",
|
|
9491
|
+
"env",
|
|
9492
|
+
"local",
|
|
9493
|
+
"json"
|
|
9494
|
+
], ...subcommand === "run" ? [
|
|
9495
|
+
"upstream",
|
|
9496
|
+
"downstream",
|
|
9497
|
+
"from-scratch",
|
|
9498
|
+
"wait",
|
|
9499
|
+
"request-id"
|
|
9500
|
+
] : []]);
|
|
9501
|
+
const unknown = Object.keys(options).find((name) => !allowed.has(name));
|
|
9502
|
+
if (unknown) throw new Error(`Unknown option for graph ${subcommand}: --${unknown}`);
|
|
9503
|
+
}
|
|
9504
|
+
function parseGraphWaitSeconds(value) {
|
|
9505
|
+
if (value === void 0 || value === "true") return 1800;
|
|
9506
|
+
const seconds = Number(value);
|
|
9507
|
+
if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 3600) throw new Error("--wait must be between 1 and 3600 seconds");
|
|
9508
|
+
return seconds;
|
|
9509
|
+
}
|
|
9510
|
+
function publicGraphRun(run, drafts, state) {
|
|
9511
|
+
return {
|
|
9512
|
+
runRef: createGraphRunRef(run.id),
|
|
9513
|
+
requestId: run.request_id,
|
|
9514
|
+
status: run.status,
|
|
9515
|
+
drafts: drafts.map((item) => {
|
|
9516
|
+
const draft = state.drafts.find((candidate) => candidate.id === item.draft_id);
|
|
9517
|
+
const ancestor = state.drafts.find((candidate) => candidate.id === item.failing_ancestor_draft_id);
|
|
9518
|
+
return {
|
|
9519
|
+
draftRef: draft ? createDraftRef(draft.name, draft.id) : null,
|
|
9520
|
+
status: item.status,
|
|
9521
|
+
variantRef: item.variant_id ? variantRefForId(item.variant_id, state.assets, state.variants) : null,
|
|
9522
|
+
reused: item.reused,
|
|
9523
|
+
failingAncestorDraftRef: ancestor ? createDraftRef(ancestor.name, ancestor.id) : null
|
|
9524
|
+
};
|
|
9525
|
+
})
|
|
9526
|
+
};
|
|
9527
|
+
}
|
|
9528
|
+
function printGraphRun(result, print) {
|
|
9529
|
+
print(`${result.runRef} (${result.status})`);
|
|
9530
|
+
for (const draft of result.drafts) print(` ${draft.draftRef ?? "unavailable draft"}: ${draft.status}${draft.variantRef ? ` → ${draft.variantRef}` : ""}`);
|
|
9531
|
+
}
|
|
8692
9532
|
function printJsonOrValue(parsed, deps, value, printHuman) {
|
|
8693
9533
|
if (parsed.options.json === "true") deps.print(JSON.stringify(value, null, 2));
|
|
8694
9534
|
else printHuman();
|
|
@@ -8700,6 +9540,20 @@ function printDrafts(drafts, print) {
|
|
|
8700
9540
|
}
|
|
8701
9541
|
for (const draft of drafts) print(`${draft.draftRef} ${draft.mediaMode} ${draft.status} ${draft.name}`);
|
|
8702
9542
|
}
|
|
9543
|
+
function printDraft(draft, print) {
|
|
9544
|
+
print(`${draft.draftRef} ${draft.name}`);
|
|
9545
|
+
print(` Media: ${draft.mediaMode} (${draft.generatorId})`);
|
|
9546
|
+
print(` Destination: ${draft.destination}${draft.destinationAssetRef ? ` → ${draft.destinationAssetRef}` : ""}`);
|
|
9547
|
+
print(` Recipe: ${JSON.stringify(draft.recipeTemplate)}`);
|
|
9548
|
+
const bindings = draft.bindings;
|
|
9549
|
+
print(" Bindings:");
|
|
9550
|
+
if (bindings.length === 0) print(" none");
|
|
9551
|
+
else for (const binding of bindings) {
|
|
9552
|
+
const broken = binding.broken ? ` [broken${binding.brokenReason ? `: ${binding.brokenReason}` : ""}]` : "";
|
|
9553
|
+
print(` ${binding.slot}[${binding.sortIndex}]: ${binding.sourceKind} → ${binding.sourceRef ?? "unavailable"}${broken}`);
|
|
9554
|
+
}
|
|
9555
|
+
print(` Last run: ${draft.lastRunVariantRef ?? "none"}`);
|
|
9556
|
+
}
|
|
8703
9557
|
//#endregion
|
|
8704
9558
|
//#region src/cli/commands/image.ts
|
|
8705
9559
|
async function handleImage(parsed) {
|
|
@@ -9749,6 +10603,33 @@ var defaultDeps$2 = {
|
|
|
9749
10603
|
print: console.log
|
|
9750
10604
|
};
|
|
9751
10605
|
var UploadUsageError = class extends Error {};
|
|
10606
|
+
var LINEAGE_RELATION_TYPES = new Set([
|
|
10607
|
+
"derived",
|
|
10608
|
+
"refined",
|
|
10609
|
+
"forked"
|
|
10610
|
+
]);
|
|
10611
|
+
function parseLineageOption(raw, defaultRelationType) {
|
|
10612
|
+
if (!raw) return [];
|
|
10613
|
+
const entries = raw.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
10614
|
+
if (entries.length === 0) throw new UploadUsageError("--lineage requires at least one compact variant ref");
|
|
10615
|
+
return entries.map((entry) => {
|
|
10616
|
+
const atIndex = entry.lastIndexOf("@");
|
|
10617
|
+
const separator = entry.lastIndexOf(":");
|
|
10618
|
+
let ref = entry;
|
|
10619
|
+
let relationType = defaultRelationType;
|
|
10620
|
+
if (atIndex !== -1 && separator > atIndex) {
|
|
10621
|
+
const suffix = entry.slice(separator + 1);
|
|
10622
|
+
if (!LINEAGE_RELATION_TYPES.has(suffix)) throw new UploadUsageError(`--lineage relation in "${entry}" must be derived, refined, or forked`);
|
|
10623
|
+
ref = entry.slice(0, separator);
|
|
10624
|
+
relationType = suffix;
|
|
10625
|
+
}
|
|
10626
|
+
if (!ref.startsWith("asset:")) throw new UploadUsageError(`--lineage requires compact variant refs, got "${ref}"`);
|
|
10627
|
+
return {
|
|
10628
|
+
ref,
|
|
10629
|
+
relationType
|
|
10630
|
+
};
|
|
10631
|
+
});
|
|
10632
|
+
}
|
|
9752
10633
|
async function handleUpload(parsed) {
|
|
9753
10634
|
try {
|
|
9754
10635
|
await executeUpload(parsed);
|
|
@@ -9773,6 +10654,7 @@ async function executeUpload(parsed, deps = defaultDeps$2) {
|
|
|
9773
10654
|
const jsonOutput = parsed.options.json === "true";
|
|
9774
10655
|
if (!spaceId) throw new UploadUsageError("--space is required, or run: makefx init --space <id>");
|
|
9775
10656
|
if (!assetId && !assetName) throw new UploadUsageError("Either --asset or --name is required");
|
|
10657
|
+
const lineageEntries = parseLineageOption(parsed.options.lineage, assetId ? "refined" : "derived");
|
|
9776
10658
|
const mediaType = resolveMediaType(path.extname(filePath).toLowerCase(), requestedMediaKind);
|
|
9777
10659
|
const config = await deps.loadConfig(env);
|
|
9778
10660
|
if (!config) throw new Error(`Not logged in to ${env} environment. Run: ${loginCommandForEnvironment(env)}`);
|
|
@@ -9780,7 +10662,16 @@ async function executeUpload(parsed, deps = defaultDeps$2) {
|
|
|
9780
10662
|
const baseUrl = deps.resolveBaseUrl(env);
|
|
9781
10663
|
const accessToken = config.token.accessToken;
|
|
9782
10664
|
const createStateClient = () => (deps.createStateClient ?? defaultDeps$2.createStateClient)(env, spaceId);
|
|
9783
|
-
|
|
10665
|
+
let lineage = [];
|
|
10666
|
+
if (assetId || lineageEntries.length > 0) {
|
|
10667
|
+
if (assetId && !assetId.startsWith("asset:")) throw new Error("A compact asset ref is required");
|
|
10668
|
+
const state = await readReferenceSpaceState(createStateClient);
|
|
10669
|
+
if (assetId) assetId = resolveAssetRef(assetId, state.assets);
|
|
10670
|
+
lineage = lineageEntries.map((entry) => ({
|
|
10671
|
+
parentVariantId: resolveVariantRef(entry.ref, state.assets, state.variants),
|
|
10672
|
+
relationType: entry.relationType
|
|
10673
|
+
}));
|
|
10674
|
+
}
|
|
9784
10675
|
if (env === "local") process$1.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
9785
10676
|
try {
|
|
9786
10677
|
const fileStat = await deps.stat(filePath);
|
|
@@ -9798,11 +10689,13 @@ async function executeUpload(parsed, deps = defaultDeps$2) {
|
|
|
9798
10689
|
formData.append("assetName", assetName);
|
|
9799
10690
|
formData.append("assetType", assetType);
|
|
9800
10691
|
}
|
|
10692
|
+
if (lineage.length > 0) formData.append("lineage", JSON.stringify(lineage));
|
|
9801
10693
|
if (!jsonOutput) {
|
|
9802
10694
|
deps.print(`\nUploading "${fileName}" to space ${spaceId}...`);
|
|
9803
10695
|
deps.print(` Media kind: ${mediaType.mediaKind}`);
|
|
9804
10696
|
if (assetId) deps.print(` Target asset: ${requestedAssetRef}`);
|
|
9805
10697
|
else deps.print(` Creating asset: "${assetName}" (${assetType})`);
|
|
10698
|
+
for (const entry of lineageEntries) deps.print(` Lineage: ${entry.relationType} from ${entry.ref}`);
|
|
9806
10699
|
}
|
|
9807
10700
|
const response = await deps.fetch(`${baseUrl}/api/spaces/${spaceId}/upload`, {
|
|
9808
10701
|
method: "POST",
|
|
@@ -9888,6 +10781,7 @@ function rejectUnknownUploadOptions(options) {
|
|
|
9888
10781
|
"name",
|
|
9889
10782
|
"type",
|
|
9890
10783
|
"media-kind",
|
|
10784
|
+
"lineage",
|
|
9891
10785
|
"json"
|
|
9892
10786
|
]);
|
|
9893
10787
|
const unknown = Object.keys(options).find((name) => !allowed.has(name));
|
|
@@ -9905,6 +10799,9 @@ Options:
|
|
|
9905
10799
|
--name <name> New asset name (creates asset + variant)
|
|
9906
10800
|
--type <type> Asset type for new assets (default: character)
|
|
9907
10801
|
--media-kind <k> Optional explicit kind: image, audio, or video
|
|
10802
|
+
--lineage <refs> Source variant refs this upload was made from, comma-separated,
|
|
10803
|
+
each optionally suffixed :derived, :refined, or :forked
|
|
10804
|
+
(default: refined with --asset, derived with --name)
|
|
9908
10805
|
--json Print machine-readable output
|
|
9909
10806
|
--env <env> Environment (production|stage|local)
|
|
9910
10807
|
--local Shortcut for --env local
|
|
@@ -9912,6 +10809,7 @@ Options:
|
|
|
9912
10809
|
Examples:
|
|
9913
10810
|
makefx assets upload hero.png --name "Hero Character"
|
|
9914
10811
|
makefx assets upload paintover.png --asset asset:hero~27f8f176
|
|
10812
|
+
makefx assets upload paintover.png --asset asset:hero~27f8f176 --lineage asset:hero~27f8f176@active
|
|
9915
10813
|
`);
|
|
9916
10814
|
}
|
|
9917
10815
|
//#endregion
|
|
@@ -10317,15 +11215,45 @@ async function handleVideo(parsed) {
|
|
|
10317
11215
|
}
|
|
10318
11216
|
}
|
|
10319
11217
|
//#endregion
|
|
10320
|
-
//#region src/cli/
|
|
10321
|
-
var
|
|
11218
|
+
//#region src/cli/help.ts
|
|
11219
|
+
var TOP_LEVEL_HELP = `Make Effects CLI
|
|
11220
|
+
|
|
11221
|
+
Creative:
|
|
11222
|
+
models list | show
|
|
11223
|
+
image generate | regenerate
|
|
11224
|
+
video generate | regenerate
|
|
11225
|
+
audio speech|dialogue|music|sfx generate|regenerate
|
|
11226
|
+
audio voices
|
|
11227
|
+
audio align
|
|
11228
|
+
|
|
11229
|
+
Assets:
|
|
11230
|
+
assets list | show | update | delete | upload | download
|
|
11231
|
+
variants show | update | activate | retry | delete
|
|
11232
|
+
collections list | show | create | update | delete | add | remove | pin | unpin
|
|
11233
|
+
drafts list | show | create | update | delete | run
|
|
11234
|
+
bindings set | clear
|
|
11235
|
+
graph run | status | cancel
|
|
11236
|
+
|
|
11237
|
+
Workspace:
|
|
11238
|
+
spaces list | show | create | delete | lens
|
|
11239
|
+
init | login | logout
|
|
11240
|
+
usage | spend | billing
|
|
11241
|
+
|
|
11242
|
+
Assets and variants use compact refs:
|
|
11243
|
+
asset:name~prefix
|
|
11244
|
+
asset:name~prefix@variant
|
|
11245
|
+
|
|
11246
|
+
Run makefx help <noun> for details.`;
|
|
10322
11247
|
var HELP = {
|
|
10323
11248
|
image: `Usage:
|
|
10324
|
-
makefx image generate "prompt" --name <name> --type <type> -o <file> [--model pro|flash|flux] [--refs <variant-ref-or-file,...>]
|
|
11249
|
+
makefx image generate "prompt" --name <name> --type <type> -o <file> [--model pro|flash|flux] [--refs <variant-ref-or-file,...>] [--aspect <ratio>] [--size 1K|2K|4K] [--collection <id>] [--space <id>]
|
|
10325
11250
|
makefx image regenerate <variant-ref> ["prompt"] [--model pro|flash|flux] [--aspect <ratio>] [--size <size>] [--refs <refs>] [--no-activate] [--wait]`,
|
|
10326
11251
|
video: `Usage:
|
|
10327
11252
|
makefx video generate "prompt" --name <name> --type <type> -o <file> [--model veo-3.1|omni-flash|kling|seedance-1|seedance-2|seedance-2-fast]
|
|
10328
|
-
|
|
11253
|
+
[--refs <variant-ref-or-file,...>] [--first-frame <ref>] [--last-frame <ref>] [--image-refs <refs>] [--video-refs <refs>] [--audio-refs <refs>]
|
|
11254
|
+
[--aspect <ratio>] [--resolution 480p|720p|1080p|4k] [--duration <seconds|auto>] [--tier generate|fast|lite] [--bitrate standard|high]
|
|
11255
|
+
[--audio | --no-audio] [--collection <id>] [--space <id>]
|
|
11256
|
+
makefx video regenerate <variant-ref> ["prompt"] [--model <model>] [--aspect <ratio>] [--resolution <value>] [--duration <seconds>] [--tier <tier>] [--bitrate standard|high] [--audio | --no-audio] [--image-refs <refs>] [--video-refs <refs>] [--audio-refs <refs>] [--no-activate] [--wait]
|
|
10329
11257
|
|
|
10330
11258
|
Seedance mode is inferred: first/last frame selects frame mode, image/video/audio refs select reference mode, and no references selects text mode.`,
|
|
10331
11259
|
audio: `Usage:
|
|
@@ -10339,7 +11267,9 @@ Seedance mode is inferred: first/last frame selects frame mode, image/video/audi
|
|
|
10339
11267
|
makefx audio music generate "prompt" --model eleven-music|lyria-3 --name <name> -o <file>
|
|
10340
11268
|
makefx audio music regenerate <variant-ref> ["prompt"] [--model eleven-music|lyria-3] [--no-activate] [--wait]
|
|
10341
11269
|
makefx audio sfx generate "prompt" --name <name> -o <file>
|
|
10342
|
-
makefx audio sfx regenerate <variant-ref> ["prompt"] [--no-activate] [--wait]
|
|
11270
|
+
makefx audio sfx regenerate <variant-ref> ["prompt"] [--no-activate] [--wait]
|
|
11271
|
+
|
|
11272
|
+
Generate commands also accept [--collection <id>] [--space <id>].`,
|
|
10343
11273
|
models: `Usage:
|
|
10344
11274
|
makefx models list [--media image|video|audio] [--available] [--json]
|
|
10345
11275
|
makefx models show <model> [--json]`,
|
|
@@ -10348,8 +11278,12 @@ Seedance mode is inferred: first/last frame selects frame mode, image/video/audi
|
|
|
10348
11278
|
makefx assets show <asset-ref> [--json]
|
|
10349
11279
|
makefx assets update <asset-ref> [--name <name>] [--type <type>] [--tags <tag,...>]
|
|
10350
11280
|
makefx assets delete <asset-ref> [--yes]
|
|
10351
|
-
makefx assets upload <file> (--name <name> | --asset <asset-ref>) [--type <type>]
|
|
10352
|
-
makefx assets download <variant-ref> -o <file
|
|
11281
|
+
makefx assets upload <file> (--name <name> | --asset <asset-ref>) [--type <type>] [--lineage <variant-ref[:relation],...>]
|
|
11282
|
+
makefx assets download <variant-ref> -o <file>
|
|
11283
|
+
|
|
11284
|
+
Upload --lineage records which variants the file was made from: comma-separated
|
|
11285
|
+
compact variant refs, each optionally suffixed :derived, :refined, or :forked
|
|
11286
|
+
(default: refined when uploading to --asset, derived when creating with --name).`,
|
|
10353
11287
|
variants: `Usage:
|
|
10354
11288
|
makefx variants show <variant-ref> [--wait <seconds>] [--json]
|
|
10355
11289
|
makefx variants update <variant-ref> [--starred true|false] [--rating approved|rejected|none]
|
|
@@ -10368,9 +11302,15 @@ Seedance mode is inferred: first/last frame selects frame mode, image/video/audi
|
|
|
10368
11302
|
makefx collections unpin <collection-id>`,
|
|
10369
11303
|
drafts: `Usage:
|
|
10370
11304
|
makefx drafts list [--json]
|
|
10371
|
-
makefx drafts
|
|
10372
|
-
makefx drafts
|
|
10373
|
-
makefx drafts
|
|
11305
|
+
makefx drafts show <draft-ref> [--json]
|
|
11306
|
+
makefx drafts create ("<name>" --media <mode> --generator <id> --recipe <json> | --from <variant-ref> [--name <name>]) [--destination new_asset|sibling] [--asset <asset-ref>] [--x <number>] [--y <number>]
|
|
11307
|
+
makefx drafts update <draft-ref> [--name <name>] [--media <mode>] [--generator <id>] [--recipe <json>] [--destination new_asset|sibling] [--asset <asset-ref|none>] [--x <number|null>] [--y <number|null>]
|
|
11308
|
+
makefx drafts delete <draft-ref>
|
|
11309
|
+
makefx drafts run <draft-ref> [--request-id <id>] [--wait [seconds]]`,
|
|
11310
|
+
graph: `Usage:
|
|
11311
|
+
makefx graph run <draft-ref> [draft-ref...] [--upstream] [--downstream] [--from-scratch] [--wait [seconds]]
|
|
11312
|
+
makefx graph status <graph-run-ref> [--json]
|
|
11313
|
+
makefx graph cancel <graph-run-ref> [--json]`,
|
|
10374
11314
|
bindings: `Usage:
|
|
10375
11315
|
makefx bindings set <draft-ref> <slot> --source variant|asset-active|draft-output --ref <ref> [--sort <index>]
|
|
10376
11316
|
makefx bindings clear <draft-ref> <slot> [--sort <index>]`,
|
|
@@ -10391,34 +11331,11 @@ Seedance mode is inferred: first/last frame selects frame mode, image/video/audi
|
|
|
10391
11331
|
makefx billing reconcile
|
|
10392
11332
|
makefx billing retry-failed`
|
|
10393
11333
|
};
|
|
11334
|
+
//#endregion
|
|
11335
|
+
//#region src/cli/index.ts
|
|
11336
|
+
var CLI_VERSION = "1.5.0+27ffb5049678";
|
|
10394
11337
|
function printHelp() {
|
|
10395
|
-
console.log(
|
|
10396
|
-
|
|
10397
|
-
Creative:
|
|
10398
|
-
models list | show
|
|
10399
|
-
image generate | regenerate
|
|
10400
|
-
video generate | regenerate
|
|
10401
|
-
audio speech|dialogue|music|sfx generate|regenerate
|
|
10402
|
-
audio voices
|
|
10403
|
-
audio align
|
|
10404
|
-
|
|
10405
|
-
Assets:
|
|
10406
|
-
assets list | show | update | delete | upload | download
|
|
10407
|
-
variants show | update | activate | retry | delete
|
|
10408
|
-
collections list | show | create | update | delete | add | remove | pin | unpin
|
|
10409
|
-
drafts list | create | update | delete
|
|
10410
|
-
bindings set | clear
|
|
10411
|
-
|
|
10412
|
-
Workspace:
|
|
10413
|
-
spaces list | show | create | delete | lens
|
|
10414
|
-
init | login | logout
|
|
10415
|
-
usage | spend | billing
|
|
10416
|
-
|
|
10417
|
-
Assets and variants use compact refs:
|
|
10418
|
-
asset:name~prefix
|
|
10419
|
-
asset:name~prefix@variant
|
|
10420
|
-
|
|
10421
|
-
Run makefx help <noun> for details.`);
|
|
11338
|
+
console.log(TOP_LEVEL_HELP);
|
|
10422
11339
|
}
|
|
10423
11340
|
function printCommandHelp(noun) {
|
|
10424
11341
|
if (!noun) {
|
|
@@ -10449,6 +11366,7 @@ async function dispatchCommand(command, parsed) {
|
|
|
10449
11366
|
case "collections": return handleCollections(parsed);
|
|
10450
11367
|
case "drafts": return handleDrafts(parsed);
|
|
10451
11368
|
case "bindings": return handleBindings(parsed);
|
|
11369
|
+
case "graph": return handleGraph(parsed);
|
|
10452
11370
|
case "usage": return handleUsage(parsed);
|
|
10453
11371
|
case "spend": return handleSpend(parsed);
|
|
10454
11372
|
case "variants": return handleVariants(parsed);
|