makefx 1.4.0 → 1.6.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 +1288 -147
- package/package.json +1 -1
package/makefx.mjs
CHANGED
|
@@ -621,9 +621,85 @@ function isProviderAuthMessage(message, providerErrorCode, provider) {
|
|
|
621
621
|
return providerErrorCode?.toLowerCase() === "api_key_invalid" || message.includes("api_key_invalid") || message.includes("api key not valid") || message.includes("invalid api key") || message.includes("api key is required") || message.includes("not configured") || message.includes("unauthenticated");
|
|
622
622
|
}
|
|
623
623
|
//#endregion
|
|
624
|
+
//#region src/shared/generation-blockers.ts
|
|
625
|
+
var GENERATION_BLOCKER_CODES = [
|
|
626
|
+
"SUBSCRIPTION_REQUIRED",
|
|
627
|
+
"PROVIDER_KEY_REQUIRED",
|
|
628
|
+
"BYOK_CREDENTIAL_FAILED",
|
|
629
|
+
"MANAGED_AI_UNAVAILABLE"
|
|
630
|
+
];
|
|
631
|
+
var PROVIDER_LABELS = {
|
|
632
|
+
google_ai: "Google AI",
|
|
633
|
+
elevenlabs: "ElevenLabs",
|
|
634
|
+
lyria: "Lyria",
|
|
635
|
+
kling: "Kling",
|
|
636
|
+
fal: "fal.ai",
|
|
637
|
+
replicate: "Replicate"
|
|
638
|
+
};
|
|
639
|
+
function isGenerationBlockerCode(code) {
|
|
640
|
+
return GENERATION_BLOCKER_CODES.includes(code);
|
|
641
|
+
}
|
|
642
|
+
function inferGenerationBlockerProvider(message) {
|
|
643
|
+
const normalized = message?.toLowerCase() ?? "";
|
|
644
|
+
if (normalized.includes("google ai") || normalized.includes("gemini") || normalized.includes("veo")) return "google_ai";
|
|
645
|
+
if (normalized.includes("elevenlabs")) return "elevenlabs";
|
|
646
|
+
if (normalized.includes("lyria")) return "lyria";
|
|
647
|
+
if (normalized.includes("kling")) return "kling";
|
|
648
|
+
if (normalized.includes("fal.ai") || normalized.includes("fal provider")) return "fal";
|
|
649
|
+
if (normalized.includes("replicate")) return "replicate";
|
|
650
|
+
}
|
|
651
|
+
function generationBlockerProviderFromService(provider) {
|
|
652
|
+
if (provider === "google_ai" || provider === "veo") return "google_ai";
|
|
653
|
+
if (provider === "elevenlabs" || provider === "lyria" || provider === "kling" || provider === "fal" || provider === "replicate") return provider;
|
|
654
|
+
}
|
|
655
|
+
function getGenerationBlockerPresentation(code, serverMessage, provider) {
|
|
656
|
+
if (!isGenerationBlockerCode(code)) return null;
|
|
657
|
+
if (code === "SUBSCRIPTION_REQUIRED") return {
|
|
658
|
+
code,
|
|
659
|
+
message: "A BYOK Platform subscription is required before generation can start.",
|
|
660
|
+
retryable: false,
|
|
661
|
+
actionLabel: "View billing",
|
|
662
|
+
actionPath: "/profile#billing",
|
|
663
|
+
remediation: "Start or restore the BYOK Platform subscription at https://makefx.app/profile#billing, then try again."
|
|
664
|
+
};
|
|
665
|
+
if (code === "MANAGED_AI_UNAVAILABLE") return {
|
|
666
|
+
code,
|
|
667
|
+
message: "Managed AI is coming soon and cannot be selected for customer generation.",
|
|
668
|
+
retryable: false,
|
|
669
|
+
remediation: "Choose a BYOK model after connecting its provider key. Managed AI is not available yet."
|
|
670
|
+
};
|
|
671
|
+
const resolvedProvider = provider ?? inferGenerationBlockerProvider(serverMessage);
|
|
672
|
+
const providerLabel = resolvedProvider ? PROVIDER_LABELS[resolvedProvider] : "provider";
|
|
673
|
+
const actionPath = resolvedProvider ? `/profile#provider-key-${resolvedProvider}` : "/profile#provider-keys";
|
|
674
|
+
const setupUrl = `https://makefx.app${actionPath}`;
|
|
675
|
+
if (code === "PROVIDER_KEY_REQUIRED") return {
|
|
676
|
+
code,
|
|
677
|
+
message: `A ${providerLabel} account key is required before generation can start.`,
|
|
678
|
+
retryable: false,
|
|
679
|
+
actionLabel: "Configure key",
|
|
680
|
+
actionPath,
|
|
681
|
+
remediation: `Configure the ${providerLabel} account key at ${setupUrl}, then try again.`,
|
|
682
|
+
...resolvedProvider ? { provider: resolvedProvider } : {}
|
|
683
|
+
};
|
|
684
|
+
return {
|
|
685
|
+
code,
|
|
686
|
+
message: `The ${providerLabel} account key could not be used. Replace or reconnect it before trying again.`,
|
|
687
|
+
retryable: false,
|
|
688
|
+
actionLabel: "Reconnect key",
|
|
689
|
+
actionPath,
|
|
690
|
+
remediation: `Replace or reconnect the ${providerLabel} account key at ${setupUrl}, then try again.`,
|
|
691
|
+
...resolvedProvider ? { provider: resolvedProvider } : {}
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
function formatGenerationBlockerForTerminal(code, message) {
|
|
695
|
+
const blocker = getGenerationBlockerPresentation(code, message);
|
|
696
|
+
if (!blocker) return `${code}: ${message}`;
|
|
697
|
+
return `${blocker.code}: ${blocker.message}\n${blocker.remediation}`;
|
|
698
|
+
}
|
|
699
|
+
//#endregion
|
|
624
700
|
//#region src/cli/lib/error-format.ts
|
|
625
701
|
function formatServerErrorMessage(code, message) {
|
|
626
|
-
return
|
|
702
|
+
return formatGenerationBlockerForTerminal(code, formatGenerationFailureMessage(message));
|
|
627
703
|
}
|
|
628
704
|
function formatGenerationFailureMessage(message, providerMetadata) {
|
|
629
705
|
return sanitizeGenerationFailureMessage(message, providerMetadata);
|
|
@@ -631,6 +707,9 @@ function formatGenerationFailureMessage(message, providerMetadata) {
|
|
|
631
707
|
function getGenerationFailureCode(providerMetadata) {
|
|
632
708
|
return extractGenerationDiagnostic(providerMetadata)?.code ?? "GENERATION_FAILED";
|
|
633
709
|
}
|
|
710
|
+
function getGenerationFailureProvider(providerMetadata) {
|
|
711
|
+
return extractGenerationDiagnostic(providerMetadata)?.provider;
|
|
712
|
+
}
|
|
634
713
|
//#endregion
|
|
635
714
|
//#region src/shared/compact-references.ts
|
|
636
715
|
var COMPACT_ID_LENGTH = 8;
|
|
@@ -660,6 +739,9 @@ function createVariantRef(name, assetId, variantId) {
|
|
|
660
739
|
function createDraftRef(name, draftId) {
|
|
661
740
|
return `draft:${slugify(name, "draft")}~${compactIdPrefix(draftId)}`;
|
|
662
741
|
}
|
|
742
|
+
function createGraphRunRef(runId) {
|
|
743
|
+
return `graph-run:${compactIdPrefix(runId)}`;
|
|
744
|
+
}
|
|
663
745
|
function parseAssetRef(value) {
|
|
664
746
|
const match = /^asset:[^~]+~([a-z0-9]{4,8})$/u.exec(value);
|
|
665
747
|
return match ? { idPrefix: match[1] } : null;
|
|
@@ -4399,6 +4481,7 @@ var WebSocketClient = class WebSocketClient {
|
|
|
4399
4481
|
chatHandlers = /* @__PURE__ */ new Map();
|
|
4400
4482
|
generateHandlers = /* @__PURE__ */ new Map();
|
|
4401
4483
|
earlyTerminalVariants = /* @__PURE__ */ new Map();
|
|
4484
|
+
draftRunStartsAwaitingVariant = /* @__PURE__ */ new Set();
|
|
4402
4485
|
variantCompletionHandlers = /* @__PURE__ */ new Map();
|
|
4403
4486
|
describeHandlers = /* @__PURE__ */ new Map();
|
|
4404
4487
|
compareHandlers = /* @__PURE__ */ new Map();
|
|
@@ -4718,13 +4801,14 @@ var WebSocketClient = class WebSocketClient {
|
|
|
4718
4801
|
success: variant.status === "completed",
|
|
4719
4802
|
variant: variant.status === "completed" ? variant : void 0,
|
|
4720
4803
|
error: variant.status === "failed" ? formatGenerationFailureMessage(variant.error_message, variant.provider_metadata) : void 0,
|
|
4721
|
-
errorCode: variant.status === "failed" ? getGenerationFailureCode(variant.provider_metadata) : void 0
|
|
4804
|
+
errorCode: variant.status === "failed" ? getGenerationFailureCode(variant.provider_metadata) : void 0,
|
|
4805
|
+
errorProvider: variant.status === "failed" ? getGenerationFailureProvider(variant.provider_metadata) : void 0
|
|
4722
4806
|
});
|
|
4723
4807
|
}
|
|
4724
4808
|
return handled;
|
|
4725
4809
|
}
|
|
4726
4810
|
hasRequestsAwaitingStarted() {
|
|
4727
|
-
return this.generateHandlers.size > 0;
|
|
4811
|
+
return this.generateHandlers.size > 0 || this.draftRunStartsAwaitingVariant.size > 0;
|
|
4728
4812
|
}
|
|
4729
4813
|
clearOrphanedEarlyTerminalVariants() {
|
|
4730
4814
|
if (!this.hasRequestsAwaitingStarted()) this.earlyTerminalVariants.clear();
|
|
@@ -4869,6 +4953,58 @@ var WebSocketClient = class WebSocketClient {
|
|
|
4869
4953
|
bindingId
|
|
4870
4954
|
}, (msg) => msg.type === "binding:cleared" && msg.draftId === draftId && msg.bindingId === bindingId);
|
|
4871
4955
|
}
|
|
4956
|
+
async runDraft(draftId, requestId, onStarted) {
|
|
4957
|
+
if (onStarted) this.draftRunStartsAwaitingVariant.add(requestId);
|
|
4958
|
+
try {
|
|
4959
|
+
const result = await this.awaitServerMessage({
|
|
4960
|
+
type: "drafts.run",
|
|
4961
|
+
draftId,
|
|
4962
|
+
requestId,
|
|
4963
|
+
source: "cli"
|
|
4964
|
+
}, (msg) => (msg.type === "drafts.run_started" || msg.type === "drafts.run_error") && msg.requestId === requestId);
|
|
4965
|
+
if (result.type === "drafts.run_error") throw new Error(`${result.code}: ${result.error}`);
|
|
4966
|
+
onStarted?.(result);
|
|
4967
|
+
return result;
|
|
4968
|
+
} finally {
|
|
4969
|
+
this.draftRunStartsAwaitingVariant.delete(requestId);
|
|
4970
|
+
this.clearOrphanedEarlyTerminalVariants();
|
|
4971
|
+
}
|
|
4972
|
+
}
|
|
4973
|
+
async runGraph(input) {
|
|
4974
|
+
const result = await this.awaitServerMessage({
|
|
4975
|
+
type: "graph.run",
|
|
4976
|
+
...input,
|
|
4977
|
+
source: "cli"
|
|
4978
|
+
}, (msg) => msg.type === "graph.run_started" && msg.run.request_id === input.requestId || msg.type === "graph.run_error" && msg.requestId === input.requestId);
|
|
4979
|
+
if (result.type === "graph.run_error") {
|
|
4980
|
+
const detail = result.failures.map((failure) => `${failure.draftId}: ${failure.error}`).join("; ");
|
|
4981
|
+
throw new Error(`${result.code}: ${detail || result.error}`);
|
|
4982
|
+
}
|
|
4983
|
+
return {
|
|
4984
|
+
type: "graph.run_status",
|
|
4985
|
+
run: result.run,
|
|
4986
|
+
drafts: result.drafts
|
|
4987
|
+
};
|
|
4988
|
+
}
|
|
4989
|
+
async getGraphRunStatus(runRef) {
|
|
4990
|
+
return this.awaitServerMessage({
|
|
4991
|
+
type: "graph.status",
|
|
4992
|
+
runRef
|
|
4993
|
+
}, (msg) => msg.type === "graph.run_status");
|
|
4994
|
+
}
|
|
4995
|
+
async cancelGraphRun(runId) {
|
|
4996
|
+
return this.awaitServerMessage({
|
|
4997
|
+
type: "graph.cancel",
|
|
4998
|
+
runId
|
|
4999
|
+
}, (msg) => msg.type === "graph.run_status" && msg.run.id === runId);
|
|
5000
|
+
}
|
|
5001
|
+
async waitForGraphRun(runRef, runId, timeoutMs = GENERATION_REQUEST_TIMEOUT_MS) {
|
|
5002
|
+
await this.awaitServerMessage({
|
|
5003
|
+
type: "graph.status",
|
|
5004
|
+
runRef
|
|
5005
|
+
}, (msg) => (msg.type === "graph.run_status" && msg.run.id === runId || msg.type === "graph.run_progress" && msg.run.id === runId) && msg.run.status !== "running", timeoutMs);
|
|
5006
|
+
return this.getGraphRunStatus(runRef);
|
|
5007
|
+
}
|
|
4872
5008
|
async setCanvasLens(lens) {
|
|
4873
5009
|
return (await this.awaitServerMessage({
|
|
4874
5010
|
type: "canvas.set_lens",
|
|
@@ -4961,7 +5097,9 @@ var WebSocketClient = class WebSocketClient {
|
|
|
4961
5097
|
videoDurationSeconds: params.videoDurationSeconds,
|
|
4962
5098
|
videoTier: params.videoTier,
|
|
4963
5099
|
seedanceDuration: params.seedanceDuration,
|
|
4964
|
-
seedanceBitrateMode: params.seedanceBitrateMode
|
|
5100
|
+
seedanceBitrateMode: params.seedanceBitrateMode,
|
|
5101
|
+
avatarResolution: params.avatarResolution,
|
|
5102
|
+
avatarMode: params.avatarMode
|
|
4965
5103
|
};
|
|
4966
5104
|
try {
|
|
4967
5105
|
this.send(message);
|
|
@@ -4992,6 +5130,11 @@ var WebSocketClient = class WebSocketClient {
|
|
|
4992
5130
|
reject,
|
|
4993
5131
|
timeout
|
|
4994
5132
|
});
|
|
5133
|
+
const earlyTerminal = this.earlyTerminalVariants.get(params.variantId);
|
|
5134
|
+
if (earlyTerminal) {
|
|
5135
|
+
this.earlyTerminalVariants.delete(params.variantId);
|
|
5136
|
+
this.handleTerminalVariant(earlyTerminal);
|
|
5137
|
+
}
|
|
4995
5138
|
});
|
|
4996
5139
|
}
|
|
4997
5140
|
cancelFollowVariant(variantId, requestId) {
|
|
@@ -5809,6 +5952,16 @@ function readIsoBmffVideoMetadata(bytes) {
|
|
|
5809
5952
|
return durationMs ? { durationMs } : {};
|
|
5810
5953
|
}
|
|
5811
5954
|
//#endregion
|
|
5955
|
+
//#region src/shared/avatarGenerationOptions.ts
|
|
5956
|
+
var AVATAR_MODEL_IDS = ["kling-avatar-v2"];
|
|
5957
|
+
var AVATAR_MODES = ["standard", "pro"];
|
|
5958
|
+
function isAvatarModelId(value) {
|
|
5959
|
+
return typeof value === "string" && AVATAR_MODEL_IDS.includes(value);
|
|
5960
|
+
}
|
|
5961
|
+
function isAvatarMode(value) {
|
|
5962
|
+
return typeof value === "string" && AVATAR_MODES.includes(value);
|
|
5963
|
+
}
|
|
5964
|
+
//#endregion
|
|
5812
5965
|
//#region src/shared/seedance2Capabilities.ts
|
|
5813
5966
|
var SEEDANCE_2_ASPECT_RATIOS = [
|
|
5814
5967
|
"auto",
|
|
@@ -6017,6 +6170,11 @@ var VIDEO_GENERATION_RESOLUTIONS = [
|
|
|
6017
6170
|
];
|
|
6018
6171
|
var ALL_VIDEO_GENERATION_RESOLUTIONS = ["480p", ...VIDEO_GENERATION_RESOLUTIONS];
|
|
6019
6172
|
var KLING_VIDEO_GENERATION_RESOLUTIONS = ["720p", "1080p"];
|
|
6173
|
+
var VIDEO_GENERATION_DURATION_SECONDS = [
|
|
6174
|
+
4,
|
|
6175
|
+
6,
|
|
6176
|
+
8
|
|
6177
|
+
];
|
|
6020
6178
|
var SEEDANCE_2_DURATION_SECONDS = [
|
|
6021
6179
|
4,
|
|
6022
6180
|
5,
|
|
@@ -6042,6 +6200,12 @@ var VIDEO_MODEL_SELECTIONS = [
|
|
|
6042
6200
|
"kling",
|
|
6043
6201
|
"fal-seedance"
|
|
6044
6202
|
];
|
|
6203
|
+
var VIDEO_MODEL_LABELS = {
|
|
6204
|
+
"veo-3.1": "Veo 3.1",
|
|
6205
|
+
"omni-flash": "Omni Flash",
|
|
6206
|
+
kling: "Kling 3.0",
|
|
6207
|
+
"fal-seedance": "fal.ai Seedance v1 (text-to-video)"
|
|
6208
|
+
};
|
|
6045
6209
|
var VIDEO_MODEL_SUPPORTED_OPERATIONS = {
|
|
6046
6210
|
"veo-3.1": [
|
|
6047
6211
|
"generate",
|
|
@@ -6069,6 +6233,7 @@ var VIDEO_GENERATION_RESOLUTIONS_BY_TIER = {
|
|
|
6069
6233
|
fast: VIDEO_GENERATION_RESOLUTIONS,
|
|
6070
6234
|
lite: ["720p", "1080p"]
|
|
6071
6235
|
};
|
|
6236
|
+
var DEFAULT_VIDEO_GENERATION_RESOLUTION = "720p";
|
|
6072
6237
|
var DEFAULT_VIDEO_GENERATION_TIER = "generate";
|
|
6073
6238
|
var DEFAULT_VIDEO_MODEL_SELECTION = "veo-3.1";
|
|
6074
6239
|
function normalizeVideoGenerationAspectRatio(value) {
|
|
@@ -6144,6 +6309,12 @@ function isFalSeedanceV1VideoGenerationModel(model) {
|
|
|
6144
6309
|
function isFalSeedance2VideoGenerationModel(model) {
|
|
6145
6310
|
return typeof model === "string" && getSeedance2CapabilityByEndpoint(model) !== void 0;
|
|
6146
6311
|
}
|
|
6312
|
+
function getVideoGenerationMaxReferenceImages(model) {
|
|
6313
|
+
if (isFalSeedanceV1VideoGenerationModel(model)) return 0;
|
|
6314
|
+
if (isFalSeedance2VideoGenerationModel(model)) return getSeedance2CapabilityByEndpoint(model)?.references.find((reference) => reference.mediaKind === "image")?.maxCount ?? 0;
|
|
6315
|
+
if (isKlingVideoGenerationModel(model)) return 1;
|
|
6316
|
+
return 3;
|
|
6317
|
+
}
|
|
6147
6318
|
function isVideoOperationSupportedByModel(model, operation) {
|
|
6148
6319
|
const seedanceCapability = getSeedance2CapabilityByEndpoint(model);
|
|
6149
6320
|
if (seedanceCapability) return seedanceCapability.operations.includes(operation);
|
|
@@ -6234,6 +6405,9 @@ var IMAGE_MODEL_CAPABILITIES = {
|
|
|
6234
6405
|
function isImageModelSelection(value) {
|
|
6235
6406
|
return IMAGE_MODEL_SELECTIONS.includes(value);
|
|
6236
6407
|
}
|
|
6408
|
+
function isImageModelId(value) {
|
|
6409
|
+
return Object.values(IMAGE_MODEL_IDS).includes(value);
|
|
6410
|
+
}
|
|
6237
6411
|
function isImageSize(value) {
|
|
6238
6412
|
return IMAGE_SIZES.includes(value);
|
|
6239
6413
|
}
|
|
@@ -6299,6 +6473,20 @@ var MEDIA_OPERATION_MATRIX = [
|
|
|
6299
6473
|
cliCommands: ["generate"],
|
|
6300
6474
|
cliSupportsRefs: true
|
|
6301
6475
|
},
|
|
6476
|
+
{
|
|
6477
|
+
mode: "avatar",
|
|
6478
|
+
label: "Avatar",
|
|
6479
|
+
shortLabel: "Avatar",
|
|
6480
|
+
mediaKind: "video",
|
|
6481
|
+
assetType: "avatar",
|
|
6482
|
+
promptNoun: "avatar video",
|
|
6483
|
+
inheritsReferenceAssetType: false,
|
|
6484
|
+
compatibleSlotMediaKinds: ["image", "audio"],
|
|
6485
|
+
supportsBatch: false,
|
|
6486
|
+
cliNamespace: null,
|
|
6487
|
+
cliCommands: [],
|
|
6488
|
+
cliSupportsRefs: false
|
|
6489
|
+
},
|
|
6302
6490
|
{
|
|
6303
6491
|
mode: "speech",
|
|
6304
6492
|
label: "Speech",
|
|
@@ -6382,9 +6570,21 @@ var AUDIO_FORGE_MEDIA_MODES = MEDIA_OPERATION_MATRIX.filter((entry) => entry.med
|
|
|
6382
6570
|
function getMediaOperationEntry(mode) {
|
|
6383
6571
|
return ENTRY_BY_MODE.get(mode) ?? MEDIA_OPERATION_MATRIX[0];
|
|
6384
6572
|
}
|
|
6573
|
+
function getMediaKindForForgeMode(mode) {
|
|
6574
|
+
return getMediaOperationEntry(mode).mediaKind;
|
|
6575
|
+
}
|
|
6385
6576
|
function isAudioForgeMediaMode(value) {
|
|
6386
6577
|
return AUDIO_FORGE_MEDIA_MODES.includes(value);
|
|
6387
6578
|
}
|
|
6579
|
+
function getForgeModeForAudioAssetType(assetType) {
|
|
6580
|
+
switch (assetType) {
|
|
6581
|
+
case "speech":
|
|
6582
|
+
case "dialogue":
|
|
6583
|
+
case "music":
|
|
6584
|
+
case "sfx": return assetType;
|
|
6585
|
+
default: return "speech";
|
|
6586
|
+
}
|
|
6587
|
+
}
|
|
6388
6588
|
function getCliGenerationProfile(namespace) {
|
|
6389
6589
|
const profile = PROFILE_BY_NAMESPACE.get(namespace);
|
|
6390
6590
|
if (!profile) throw new Error(`Unknown CLI generation namespace: ${namespace}`);
|
|
@@ -6489,49 +6689,50 @@ async function executeForgeCommand(command, parsed, deps = defaultDeps$12, optio
|
|
|
6489
6689
|
client.disconnect();
|
|
6490
6690
|
}
|
|
6491
6691
|
}
|
|
6692
|
+
var CLI_GENERATION_COMMON_OPTIONS = [
|
|
6693
|
+
"env",
|
|
6694
|
+
"local",
|
|
6695
|
+
"space",
|
|
6696
|
+
"force",
|
|
6697
|
+
"name",
|
|
6698
|
+
"type",
|
|
6699
|
+
"o",
|
|
6700
|
+
"output",
|
|
6701
|
+
"collection"
|
|
6702
|
+
];
|
|
6703
|
+
var CLI_GENERATION_MEDIA_OPTIONS = {
|
|
6704
|
+
image: [
|
|
6705
|
+
"model",
|
|
6706
|
+
"refs",
|
|
6707
|
+
"aspect",
|
|
6708
|
+
"size"
|
|
6709
|
+
],
|
|
6710
|
+
audio: [
|
|
6711
|
+
"model",
|
|
6712
|
+
"input",
|
|
6713
|
+
"voice",
|
|
6714
|
+
"dialogue-voices"
|
|
6715
|
+
],
|
|
6716
|
+
video: [
|
|
6717
|
+
"model",
|
|
6718
|
+
"refs",
|
|
6719
|
+
"aspect",
|
|
6720
|
+
"audio",
|
|
6721
|
+
"no-audio",
|
|
6722
|
+
"resolution",
|
|
6723
|
+
"duration",
|
|
6724
|
+
"tier",
|
|
6725
|
+
"bitrate",
|
|
6726
|
+
"first-frame",
|
|
6727
|
+
"last-frame",
|
|
6728
|
+
"image-refs",
|
|
6729
|
+
"video-refs",
|
|
6730
|
+
"audio-refs",
|
|
6731
|
+
"mode"
|
|
6732
|
+
]
|
|
6733
|
+
};
|
|
6492
6734
|
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]]);
|
|
6735
|
+
const allowed = new Set([...CLI_GENERATION_COMMON_OPTIONS, ...CLI_GENERATION_MEDIA_OPTIONS[mediaKind]]);
|
|
6535
6736
|
const unknown = Object.keys(options).find((name) => !allowed.has(name));
|
|
6536
6737
|
if (unknown) throw new Error(`Unknown option: --${unknown}`);
|
|
6537
6738
|
}
|
|
@@ -6575,36 +6776,40 @@ function validateAudioModeRequiredVoiceOptions(options, mode) {
|
|
|
6575
6776
|
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");
|
|
6576
6777
|
}
|
|
6577
6778
|
async function executeGenerate(parsed, ctx, client, deps, mediaKind, followOptions = {}) {
|
|
6578
|
-
const
|
|
6779
|
+
const videoOptions = parseVideoGenerationOptions(parsed, mediaKind);
|
|
6780
|
+
const prompt = isAvatarModelId(videoOptions.model) ? parsed.positionals.join(" ").trim() : getPrompt(parsed, "generate");
|
|
6579
6781
|
const outputPath = getOutputPath(parsed);
|
|
6580
6782
|
const name = requireOption(parsed, "name");
|
|
6581
6783
|
const assetType = requireOption(parsed, "type");
|
|
6582
6784
|
const musicProvider = parseMusicProviderOption(parsed, mediaKind, assetType);
|
|
6583
|
-
const videoOptions = parseVideoGenerationOptions(parsed, mediaKind);
|
|
6584
6785
|
const effectiveVideoModel = videoOptions.model ?? getVideoGenerationModelForSelection();
|
|
6585
6786
|
const seedanceCapability = mediaKind === "video" ? getSeedance2CapabilityByEndpoint(effectiveVideoModel) : void 0;
|
|
6586
6787
|
const videoFrameRefs = parseVideoFrameReferenceOptions(parsed, "generate", mediaKind).refs;
|
|
6587
6788
|
const seedanceRefs = parseSeedanceReferenceOptions(parsed);
|
|
6789
|
+
const plainRefs = parseOptionalRefs(parsed, "refs");
|
|
6588
6790
|
validateSeedanceReferenceOptions(seedanceRefs, effectiveVideoModel, "generate");
|
|
6589
6791
|
if (seedanceCapability?.mode === "frame" && videoFrameRefs.length === 0) throw new Error(`--model ${seedanceCapability.selection} requires --first-frame`);
|
|
6590
6792
|
if (seedanceCapability?.mode === "text" && videoFrameRefs.length > 0) throw new Error(`--model ${seedanceCapability.selection} does not accept references`);
|
|
6591
6793
|
if (seedanceCapability?.mode === "reference" && videoFrameRefs.length > 0) throw new Error(`--model ${seedanceCapability.selection} uses --image-refs, --video-refs, and --audio-refs`);
|
|
6794
|
+
if (seedanceCapability && plainRefs.length > 0) throw new Error(`--model ${seedanceCapability.selection} uses --image-refs, --video-refs, and --audio-refs instead of --refs`);
|
|
6795
|
+
if (mediaKind === "video" && isKlingVideoGenerationModel(effectiveVideoModel) && videoFrameRefs.length + plainRefs.length > 1) throw new Error("--model kling supports at most one image reference");
|
|
6796
|
+
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
6797
|
const seedanceReferenceCount = seedanceRefs.imageRefs.length + seedanceRefs.videoRefs.length + seedanceRefs.audioRefs.length;
|
|
6593
|
-
const state = videoFrameRefs.length > 0 || seedanceReferenceCount > 0 ? await requestSpaceState(client) : void 0;
|
|
6798
|
+
const state = videoFrameRefs.length > 0 || seedanceReferenceCount > 0 || plainRefs.length > 0 ? await requestSpaceState(client) : void 0;
|
|
6594
6799
|
const referenceDeps = {
|
|
6595
6800
|
...deps,
|
|
6596
6801
|
waitForReferenceVariant: (variant) => waitForReferenceVariant(client, variant)
|
|
6597
6802
|
};
|
|
6598
|
-
const resolvedSeedanceRefs = state && seedanceReferenceCount > 0 ? await resolveSeedanceReferenceIds(seedanceRefs, ctx, referenceDeps, state) : {
|
|
6803
|
+
const resolvedSeedanceRefs = state && seedanceReferenceCount > 0 ? isAvatarModelId(effectiveVideoModel) ? await resolveAvatarReferenceIds(seedanceRefs, ctx, referenceDeps, state) : await resolveSeedanceReferenceIds(seedanceRefs, ctx, referenceDeps, state) : {
|
|
6599
6804
|
refs: [],
|
|
6600
6805
|
ids: []
|
|
6601
6806
|
};
|
|
6602
|
-
const
|
|
6807
|
+
const directRefs = videoFrameRefs.length > 0 ? videoFrameRefs : plainRefs;
|
|
6808
|
+
const directRefMediaKind = videoFrameRefs.length > 0 ? CLI_GENERATION_MEDIA_KIND : mediaKind;
|
|
6809
|
+
const referenceVariantIds = resolvedSeedanceRefs.ids.length > 0 ? resolvedSeedanceRefs.ids : directRefs.length > 0 ? await resolveReferenceVariantIds(directRefs, ctx, referenceDeps, state?.variants, directRefMediaKind, state?.assets) : [];
|
|
6603
6810
|
const imageOptions = parseImageGenerationOptions(parsed, mediaKind);
|
|
6604
6811
|
const audioModelOptions = parseAudioGenerationOptions(parsed, mediaKind);
|
|
6605
6812
|
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
6813
|
const collectionPlacement = parseCollectionPlacementOptions(parsed);
|
|
6609
6814
|
const followCommandOptions = {
|
|
6610
6815
|
...followOptions,
|
|
@@ -6749,6 +6954,10 @@ function parseSeedanceReferenceOptions(parsed) {
|
|
|
6749
6954
|
};
|
|
6750
6955
|
}
|
|
6751
6956
|
function validateSeedanceReferenceOptions(options, model, command) {
|
|
6957
|
+
if (isAvatarModelId(model)) {
|
|
6958
|
+
if (options.imageRefs.length !== 1 || options.audioRefs.length !== 1 || options.videoRefs.length !== 0) throw new Error("Avatar generation requires exactly one --image-refs portrait and one --audio-refs input");
|
|
6959
|
+
return;
|
|
6960
|
+
}
|
|
6752
6961
|
const capability = getSeedance2CapabilityByEndpoint(model);
|
|
6753
6962
|
const total = options.imageRefs.length + options.videoRefs.length + options.audioRefs.length;
|
|
6754
6963
|
if (!capability) {
|
|
@@ -6766,6 +6975,15 @@ function validateSeedanceReferenceOptions(options, model, command) {
|
|
|
6766
6975
|
});
|
|
6767
6976
|
if (error) throw new Error(error.message);
|
|
6768
6977
|
}
|
|
6978
|
+
async function resolveAvatarReferenceIds(options, ctx, deps, state) {
|
|
6979
|
+
const resolve = (refs, kind) => resolveReferenceVariantIds(refs, ctx, deps, state.variants, "video", state.assets, kind);
|
|
6980
|
+
const imageIds = await resolve(options.imageRefs, "image");
|
|
6981
|
+
const audioIds = await resolve(options.audioRefs, "audio");
|
|
6982
|
+
return {
|
|
6983
|
+
refs: [...options.imageRefs, ...options.audioRefs],
|
|
6984
|
+
ids: [...imageIds, ...audioIds]
|
|
6985
|
+
};
|
|
6986
|
+
}
|
|
6769
6987
|
async function resolveSeedanceReferenceIds(options, ctx, deps, state, implicitVideoReferenceIds = []) {
|
|
6770
6988
|
await preflightLocalSeedanceReferences({
|
|
6771
6989
|
...options,
|
|
@@ -7043,7 +7261,9 @@ function compactStartedVariantRef(started) {
|
|
|
7043
7261
|
}
|
|
7044
7262
|
function formatTerminalGenerationError(result) {
|
|
7045
7263
|
const message = result.error || "Generation failed without a completed variant";
|
|
7046
|
-
|
|
7264
|
+
if (!result.errorCode) return message;
|
|
7265
|
+
const blocker = getGenerationBlockerPresentation(result.errorCode, message, generationBlockerProviderFromService(result.errorProvider));
|
|
7266
|
+
return blocker ? `${blocker.code}: ${blocker.message}\n${blocker.remediation}` : formatGenerationBlockerForTerminal(result.errorCode, message);
|
|
7047
7267
|
}
|
|
7048
7268
|
function throwGenerationWaitErrorIfNeeded(input, params) {
|
|
7049
7269
|
if (!isGenerationWaitTimeout(input)) throw input;
|
|
@@ -7098,7 +7318,7 @@ function validateVideoAudioOptions(parsed, mediaKind) {
|
|
|
7098
7318
|
const model = parseVideoModelOption(modelValue, videoTier, parsed);
|
|
7099
7319
|
if (parsed.options.audio !== void 0 && (isGeminiOmniVideoGenerationModel(model) || isFalSeedanceV1VideoGenerationModel(model))) throw new Error("--audio is only supported with --model veo-3.1, kling, or Seedance 2");
|
|
7100
7320
|
if (parsed.options["no-audio"] !== void 0) {
|
|
7101
|
-
if (!doesVideoGenerationModelSupportAudioToggle(model) && !isFalSeedance2VideoGenerationModel(model)) throw new Error(`${model} does not support --no-audio. Use the default audio-enabled output or omit the flag.`);
|
|
7321
|
+
if (isAvatarModelId(model) || !doesVideoGenerationModelSupportAudioToggle(model) && !isFalSeedance2VideoGenerationModel(model)) throw new Error(`${model} does not support --no-audio. Use the default audio-enabled output or omit the flag.`);
|
|
7102
7322
|
}
|
|
7103
7323
|
}
|
|
7104
7324
|
function parseVideoAudioOptions(parsed, mediaKind) {
|
|
@@ -7113,6 +7333,7 @@ function parseVideoGenerationOptions(parsed, mediaKind) {
|
|
|
7113
7333
|
const durationValue = readOptionalOption(parsed, "duration");
|
|
7114
7334
|
const tierValue = readOptionalOption(parsed, "tier");
|
|
7115
7335
|
const bitrateValue = readOptionalOption(parsed, "bitrate");
|
|
7336
|
+
const modeValue = readOptionalOption(parsed, "mode");
|
|
7116
7337
|
const modelValue = mediaKind === "video" ? readOptionalOption(parsed, "model") : void 0;
|
|
7117
7338
|
const aspectValue = mediaKind === "video" ? readOptionalOption(parsed, "aspect") : void 0;
|
|
7118
7339
|
if (mediaKind !== "video" && resolutionValue === void 0 && durationValue === void 0 && tierValue === void 0 && aspectValue === void 0 && bitrateValue === void 0) return {};
|
|
@@ -7122,6 +7343,17 @@ function parseVideoGenerationOptions(parsed, mediaKind) {
|
|
|
7122
7343
|
const videoTier = tierValue === void 0 ? void 0 : normalizeVideoGenerationTier(tierValue);
|
|
7123
7344
|
if (tierValue !== void 0 && !videoTier) throw new Error("--tier must be generate, fast, or lite");
|
|
7124
7345
|
const model = parseVideoModelOption(modelValue, videoTier, parsed);
|
|
7346
|
+
if (isAvatarModelId(model)) {
|
|
7347
|
+
if (parsed.options.refs !== void 0 || parsed.options["first-frame"] !== void 0 || parsed.options["last-frame"] !== void 0) throw new Error("Avatar models accept only --image-refs and --audio-refs");
|
|
7348
|
+
if (aspectValue !== void 0 || durationValue !== void 0 || tierValue !== void 0 || bitrateValue !== void 0 || parsed.options.audio !== void 0 || parsed.options["no-audio"] !== void 0) throw new Error("Avatar models do not accept --aspect, --duration, --tier, --bitrate, --audio, or --no-audio");
|
|
7349
|
+
if (resolutionValue !== void 0) throw new Error("--resolution is not supported by Avatar models");
|
|
7350
|
+
if (modeValue !== void 0 && !isAvatarMode(modeValue)) throw new Error(`--mode must be ${AVATAR_MODES.join(" or ")}`);
|
|
7351
|
+
return {
|
|
7352
|
+
model,
|
|
7353
|
+
...modeValue ? { avatarMode: modeValue } : {}
|
|
7354
|
+
};
|
|
7355
|
+
}
|
|
7356
|
+
if (modeValue !== void 0) throw new Error("--mode is only supported by --model kling-avatar-v2");
|
|
7125
7357
|
const seedanceCapability = getSeedance2CapabilityByEndpoint(model);
|
|
7126
7358
|
const seedanceDuration = durationValue === void 0 ? void 0 : durationValue === "auto" ? "auto" : normalizeVideoGenerationDurationSeconds(durationValue);
|
|
7127
7359
|
const videoDurationSeconds = durationValue === void 0 || durationValue === "auto" ? void 0 : normalizeVideoGenerationDurationSeconds(durationValue);
|
|
@@ -7217,6 +7449,7 @@ function parseVideoModelOption(value, tier, parsed) {
|
|
|
7217
7449
|
const normalized = normalizeCliOption(value);
|
|
7218
7450
|
const effectiveTier = tier ?? "generate";
|
|
7219
7451
|
if (!normalized) return getVideoGenerationModelForSelection(DEFAULT_VIDEO_MODEL_SELECTION, effectiveTier);
|
|
7452
|
+
if (isAvatarModelId(normalized)) return normalized;
|
|
7220
7453
|
if (normalized === "seedance-2" || normalized === "seedance-2-fast") {
|
|
7221
7454
|
const hasFrames = Boolean(parsed?.options["first-frame"] || parsed?.options["last-frame"]);
|
|
7222
7455
|
const hasReferences = Boolean(parsed?.options.refs || parsed?.options["image-refs"] || parsed?.options["video-refs"] || parsed?.options["audio-refs"]);
|
|
@@ -7224,7 +7457,7 @@ function parseVideoModelOption(value, tier, parsed) {
|
|
|
7224
7457
|
}
|
|
7225
7458
|
const selection = normalizeVideoModelSelection(normalized === "seedance-1" ? "fal-seedance" : normalized);
|
|
7226
7459
|
if (selection) return getVideoGenerationModelForSelection(selection, effectiveTier);
|
|
7227
|
-
throw new Error("--model must be veo-3.1, omni-flash, kling, seedance-1, seedance-2,
|
|
7460
|
+
throw new Error("--model must be veo-3.1, omni-flash, kling, seedance-1, seedance-2, seedance-2-fast, or kling-avatar-v2");
|
|
7228
7461
|
}
|
|
7229
7462
|
function parseImageModelOption(value) {
|
|
7230
7463
|
if (!value) return void 0;
|
|
@@ -7262,6 +7495,10 @@ function validateImageModelOperation(command, mediaKind, model) {
|
|
|
7262
7495
|
function validateVideoModelOperation(command, mediaKind, model) {
|
|
7263
7496
|
if (mediaKind !== "video") return;
|
|
7264
7497
|
const effectiveModel = model ?? getVideoGenerationModelForSelection();
|
|
7498
|
+
if (isAvatarModelId(effectiveModel)) {
|
|
7499
|
+
if (command === "generate") return;
|
|
7500
|
+
throw new Error(`--model ${effectiveModel} does not support video ${command}`);
|
|
7501
|
+
}
|
|
7265
7502
|
if (isVideoOperationSupportedByModel(effectiveModel, command)) return;
|
|
7266
7503
|
throw new Error(`--model ${getVideoModelSelectionForModel(effectiveModel) ?? effectiveModel} does not support video ${command}`);
|
|
7267
7504
|
}
|
|
@@ -7290,7 +7527,7 @@ function cliImageModelValues(command) {
|
|
|
7290
7527
|
function printUsage$6(command) {
|
|
7291
7528
|
console.log(`
|
|
7292
7529
|
Usage:
|
|
7293
|
-
makefx image generate "prompt" --name <name> --type <type> -o <file> [--model ${cliImageModelValues(command)}] [--size ${cliImageSizeValues()}] [--aspect ${cliImageAspectValues()}] [--collection <id>] [--space <id>]
|
|
7530
|
+
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
7531
|
`);
|
|
7295
7532
|
}
|
|
7296
7533
|
//#endregion
|
|
@@ -7431,7 +7668,7 @@ function resolveVideoRegenerationModel(model, parsed, sourceRecipe) {
|
|
|
7431
7668
|
"video-refs",
|
|
7432
7669
|
"audio-refs"
|
|
7433
7670
|
].some((name) => parsed.options[name] !== void 0);
|
|
7434
|
-
const storedRecipe = parseStoredRecipe$
|
|
7671
|
+
const storedRecipe = parseStoredRecipe$2(sourceRecipe);
|
|
7435
7672
|
return getSeedance2RegenerationCapability(model, {
|
|
7436
7673
|
model: storedRecipe?.model,
|
|
7437
7674
|
references: storedRecipe?.references ?? [],
|
|
@@ -7442,7 +7679,7 @@ function resolveVideoRegenerationModel(model, parsed, sourceRecipe) {
|
|
|
7442
7679
|
if (!selection) throw new Error("Unsupported video model. Expected veo-3.1, omni-flash, kling, seedance-1, seedance-2, or seedance-2-fast");
|
|
7443
7680
|
return getVideoGenerationModelForSelection(selection, tier);
|
|
7444
7681
|
}
|
|
7445
|
-
function parseStoredRecipe$
|
|
7682
|
+
function parseStoredRecipe$2(recipe) {
|
|
7446
7683
|
if (!recipe) return void 0;
|
|
7447
7684
|
try {
|
|
7448
7685
|
const parsed = JSON.parse(recipe);
|
|
@@ -7701,14 +7938,14 @@ async function handleBilling(parsed) {
|
|
|
7701
7938
|
}
|
|
7702
7939
|
function printBillingHelp() {
|
|
7703
7940
|
console.log(`
|
|
7704
|
-
Billing Commands -
|
|
7941
|
+
Billing Commands - Platform Subscription Operations
|
|
7705
7942
|
|
|
7706
7943
|
Usage:
|
|
7707
7944
|
makefx billing <subcommand> [--env <environment>]
|
|
7708
7945
|
|
|
7709
7946
|
Subcommands:
|
|
7710
7947
|
status Show sync status (pending, failed, synced events)
|
|
7711
|
-
check Run operational checks for workers, Polar
|
|
7948
|
+
check Run operational checks for workers, Polar product, and sync health
|
|
7712
7949
|
reconcile Compare local billable usage with Polar usage for one user
|
|
7713
7950
|
retry-failed Reset failed events for retry (next cron will sync them)
|
|
7714
7951
|
|
|
@@ -7855,6 +8092,16 @@ function secondsSummary(seconds) {
|
|
|
7855
8092
|
const remainingSeconds = seconds % 60;
|
|
7856
8093
|
return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
|
|
7857
8094
|
}
|
|
8095
|
+
function resolveBillingOpsResult(options) {
|
|
8096
|
+
const statuses = [
|
|
8097
|
+
...options.workerStatuses,
|
|
8098
|
+
options.billingStatus,
|
|
8099
|
+
options.webhookStatus
|
|
8100
|
+
];
|
|
8101
|
+
if (statuses.includes("critical")) return "critical";
|
|
8102
|
+
if (statuses.includes("warning")) return "warning";
|
|
8103
|
+
return "ok";
|
|
8104
|
+
}
|
|
7858
8105
|
async function handleBillingOpsCheck(env) {
|
|
7859
8106
|
console.log(`Running billing operational checks for ${env}...\n`);
|
|
7860
8107
|
const workerChecks = await checkWorkerHealth(env);
|
|
@@ -7871,22 +8118,22 @@ async function handleBillingOpsCheck(env) {
|
|
|
7871
8118
|
process$1.exitCode = 1;
|
|
7872
8119
|
return;
|
|
7873
8120
|
}
|
|
7874
|
-
const
|
|
7875
|
-
console.log("\
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
if (
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
}
|
|
8121
|
+
const productCheck = billingChecks.checks.platformSubscriptionProduct;
|
|
8122
|
+
console.log("\nPlatform subscription product:");
|
|
8123
|
+
const product = productCheck.product;
|
|
8124
|
+
console.log(` ${statusLabel(productCheck.status)} configured=${product?.configured ?? false} recurring=${product?.isRecurring ?? "n/a"} archived=${product?.isArchived ?? "n/a"}`);
|
|
8125
|
+
console.log(` Environment: ${productCheck.actualEnvironment} (expected ${productCheck.expectedEnvironment})`);
|
|
8126
|
+
if (product?.productId) console.log(` Product: ${product.productId}${product.name ? ` (${product.name})` : ""}`);
|
|
8127
|
+
if (product?.fixedPrices.length) console.log(` Fixed price: ${product.fixedPrices.map((price) => `${price.amount} ${price.currency}/${price.interval ?? "one-time"}`).join(", ")}`);
|
|
8128
|
+
for (const error of productCheck.errors) console.log(` Error: ${error}`);
|
|
8129
|
+
const webhookCheck = billingChecks.checks.webhook ?? {
|
|
8130
|
+
status: "critical",
|
|
8131
|
+
configured: false,
|
|
8132
|
+
error: "Webhook readiness was not reported by the application Worker"
|
|
8133
|
+
};
|
|
8134
|
+
console.log("\nWebhook verifier:");
|
|
8135
|
+
console.log(` ${statusLabel(webhookCheck.status)} configured=${webhookCheck.configured}`);
|
|
8136
|
+
if (webhookCheck.error) console.log(` Error: ${webhookCheck.error}`);
|
|
7890
8137
|
const syncCheck = billingChecks.checks.syncHealth;
|
|
7891
8138
|
console.log("\nSync health:");
|
|
7892
8139
|
console.log(` ${statusLabel(syncCheck.status)} pending=${syncCheck.events.pending} failed=${syncCheck.events.failed} synced=${syncCheck.events.synced}`);
|
|
@@ -7895,13 +8142,15 @@ async function handleBillingOpsCheck(env) {
|
|
|
7895
8142
|
const internalCheck = billingChecks.checks.internalUsers;
|
|
7896
8143
|
console.log("\nInternal users:");
|
|
7897
8144
|
console.log(` ${statusLabel(internalCheck.status)} users=${internalCheck.internalUsers} nonBillableEvents=${internalCheck.nonBillableEvents} billableEvents=${internalCheck.billableEvents}`);
|
|
7898
|
-
const
|
|
7899
|
-
|
|
7900
|
-
|
|
7901
|
-
|
|
8145
|
+
const resultStatus = resolveBillingOpsResult({
|
|
8146
|
+
workerStatuses: workerChecks.map((check) => check.status),
|
|
8147
|
+
billingStatus: billingChecks.status,
|
|
8148
|
+
webhookStatus: webhookCheck.status
|
|
8149
|
+
});
|
|
8150
|
+
if (resultStatus === "critical") {
|
|
7902
8151
|
console.log("\nResult: CRITICAL - billing operations need attention.");
|
|
7903
8152
|
process$1.exitCode = 1;
|
|
7904
|
-
} else if (
|
|
8153
|
+
} else if (resultStatus === "warning") console.log("\nResult: WARNING - billing is operational but has lag or cleanup work.");
|
|
7905
8154
|
else console.log("\nResult: OK - billing workers, meters, and sync health are ready.");
|
|
7906
8155
|
}
|
|
7907
8156
|
async function handleBillingReconcile(env, parsed) {
|
|
@@ -8360,13 +8609,644 @@ async function executeSpaceLens(parsed, deps = defaultDeps$8) {
|
|
|
8360
8609
|
return result;
|
|
8361
8610
|
}
|
|
8362
8611
|
//#endregion
|
|
8612
|
+
//#region src/shared/generatorCapabilities.ts
|
|
8613
|
+
function input(name, type, required, description, options = {}) {
|
|
8614
|
+
return {
|
|
8615
|
+
name,
|
|
8616
|
+
type,
|
|
8617
|
+
required,
|
|
8618
|
+
description,
|
|
8619
|
+
...options
|
|
8620
|
+
};
|
|
8621
|
+
}
|
|
8622
|
+
var SPACE_INPUT = input("space_id", "string", true, "Target Space ID from list_spaces.");
|
|
8623
|
+
var NAME_INPUT = input("name", "string", true, "Human-readable asset name.");
|
|
8624
|
+
var PROMPT_INPUT = input("prompt", "string", true, "Generation instruction.");
|
|
8625
|
+
function fixedInput(name, value, description) {
|
|
8626
|
+
return input(name, "string", true, description, { allowedValues: [value] });
|
|
8627
|
+
}
|
|
8628
|
+
function imageGenerator(capability) {
|
|
8629
|
+
const referenceInput = input("reference_variant_refs", "string_array", false, "Completed image variant references from find_assets or get_asset.", {
|
|
8630
|
+
minItems: 1,
|
|
8631
|
+
maxItems: capability.maxReferenceImages
|
|
8632
|
+
});
|
|
8633
|
+
const generateInputs = [
|
|
8634
|
+
SPACE_INPUT,
|
|
8635
|
+
fixedInput("generator_id", `image/${capability.selection}`, "Selects this image generator."),
|
|
8636
|
+
NAME_INPUT,
|
|
8637
|
+
input("asset_type", "string", true, "Asset classification stored in the Space."),
|
|
8638
|
+
PROMPT_INPUT,
|
|
8639
|
+
input("aspect_ratio", "string", false, "Output aspect ratio.", {
|
|
8640
|
+
allowedValues: capability.supportedAspectRatios,
|
|
8641
|
+
defaultValue: "1:1"
|
|
8642
|
+
}),
|
|
8643
|
+
input("image_size", "string", false, "Output image size.", {
|
|
8644
|
+
allowedValues: capability.supportedImageSizes,
|
|
8645
|
+
defaultValue: "1K"
|
|
8646
|
+
})
|
|
8647
|
+
];
|
|
8648
|
+
const operations = [{
|
|
8649
|
+
operation: "generate",
|
|
8650
|
+
tool: "generate_image",
|
|
8651
|
+
description: "Create a new image asset from text.",
|
|
8652
|
+
inputs: generateInputs
|
|
8653
|
+
}];
|
|
8654
|
+
if (capability.supportedOperations.includes("derive")) operations.push({
|
|
8655
|
+
operation: "derive",
|
|
8656
|
+
tool: "generate_image",
|
|
8657
|
+
description: "Create a new image asset using completed image variants as references.",
|
|
8658
|
+
inputs: [...generateInputs, {
|
|
8659
|
+
...referenceInput,
|
|
8660
|
+
required: true
|
|
8661
|
+
}]
|
|
8662
|
+
});
|
|
8663
|
+
if (capability.supportedOperations.includes("refine")) operations.push({
|
|
8664
|
+
operation: "refine",
|
|
8665
|
+
tool: "edit_image",
|
|
8666
|
+
description: "Create a new variant on an existing image asset.",
|
|
8667
|
+
inputs: [
|
|
8668
|
+
SPACE_INPUT,
|
|
8669
|
+
fixedInput("generator_id", `image/${capability.selection}`, "Selects this image generator."),
|
|
8670
|
+
input("asset_ref", "string", true, "Target image asset reference from find_assets."),
|
|
8671
|
+
PROMPT_INPUT,
|
|
8672
|
+
input("source_variant_ref", "string", true, "Completed image variant to edit."),
|
|
8673
|
+
input("reference_variant_refs", "string_array", false, "Additional completed image references.", {
|
|
8674
|
+
minItems: 1,
|
|
8675
|
+
maxItems: Math.max(0, capability.maxReferenceImages - 1)
|
|
8676
|
+
}),
|
|
8677
|
+
input("aspect_ratio", "string", false, "Output aspect ratio.", {
|
|
8678
|
+
allowedValues: capability.supportedAspectRatios,
|
|
8679
|
+
defaultValue: "1:1"
|
|
8680
|
+
}),
|
|
8681
|
+
input("image_size", "string", false, "Output image size.", {
|
|
8682
|
+
allowedValues: capability.supportedImageSizes,
|
|
8683
|
+
defaultValue: "1K"
|
|
8684
|
+
})
|
|
8685
|
+
]
|
|
8686
|
+
});
|
|
8687
|
+
return {
|
|
8688
|
+
id: `image/${capability.selection}`,
|
|
8689
|
+
label: capability.label,
|
|
8690
|
+
mediaKind: "image",
|
|
8691
|
+
modelIds: [capability.modelId],
|
|
8692
|
+
defaultModelId: capability.modelId,
|
|
8693
|
+
operations,
|
|
8694
|
+
referenceRules: {
|
|
8695
|
+
mediaKind: capability.maxReferenceImages > 0 ? "image" : null,
|
|
8696
|
+
completedOnly: capability.maxReferenceImages > 0,
|
|
8697
|
+
maxCount: capability.maxReferenceImages
|
|
8698
|
+
},
|
|
8699
|
+
notes: capability.maxReferenceImages > 0 ? ["Use compact variant references; binary image input is not accepted."] : ["Text-to-image only; reference inputs are not supported."]
|
|
8700
|
+
};
|
|
8701
|
+
}
|
|
8702
|
+
function videoGenerator(selection) {
|
|
8703
|
+
const defaultModel = getVideoGenerationModelForSelection(selection);
|
|
8704
|
+
const isVeo = selection === "veo-3.1";
|
|
8705
|
+
const isOmni = selection === "omni-flash";
|
|
8706
|
+
const isKling = selection === "kling";
|
|
8707
|
+
const modelIds = isVeo ? Object.values(VIDEO_GENERATION_TIER_MODELS) : [defaultModel];
|
|
8708
|
+
const resolutions = isVeo ? VIDEO_GENERATION_RESOLUTIONS : getVideoGenerationResolutionsForModel(defaultModel);
|
|
8709
|
+
const maxReferences = getVideoGenerationMaxReferenceImages(defaultModel);
|
|
8710
|
+
const parameterInputs = [input("aspect_ratio", "string", false, "Output aspect ratio.", {
|
|
8711
|
+
allowedValues: VIDEO_GENERATION_ASPECT_RATIOS,
|
|
8712
|
+
defaultValue: "16:9"
|
|
8713
|
+
})];
|
|
8714
|
+
if (!isOmni) parameterInputs.push(input("video_resolution", "string", false, "Output resolution.", {
|
|
8715
|
+
allowedValues: resolutions,
|
|
8716
|
+
defaultValue: DEFAULT_VIDEO_GENERATION_RESOLUTION
|
|
8717
|
+
}), input("video_duration_seconds", "integer", false, "Output duration in seconds.", {
|
|
8718
|
+
allowedValues: VIDEO_GENERATION_DURATION_SECONDS,
|
|
8719
|
+
defaultValue: 8
|
|
8720
|
+
}));
|
|
8721
|
+
if (isVeo) parameterInputs.push(input("video_tier", "string", false, "Veo model tier.", {
|
|
8722
|
+
allowedValues: VIDEO_GENERATION_TIERS,
|
|
8723
|
+
defaultValue: DEFAULT_VIDEO_GENERATION_TIER
|
|
8724
|
+
}));
|
|
8725
|
+
if (isKling) parameterInputs.push(input("generate_audio", "boolean", false, "Generate synchronized audio.", {
|
|
8726
|
+
allowedValues: [true, false],
|
|
8727
|
+
defaultValue: true
|
|
8728
|
+
}));
|
|
8729
|
+
const commonInputs = [
|
|
8730
|
+
SPACE_INPUT,
|
|
8731
|
+
fixedInput("generator_id", `video/${selection}`, "Selects this video generator."),
|
|
8732
|
+
NAME_INPUT,
|
|
8733
|
+
input("asset_type", "string", true, "Asset classification stored in the Space."),
|
|
8734
|
+
PROMPT_INPUT,
|
|
8735
|
+
...parameterInputs
|
|
8736
|
+
];
|
|
8737
|
+
const operations = [{
|
|
8738
|
+
operation: "generate",
|
|
8739
|
+
tool: "generate_video",
|
|
8740
|
+
description: "Create a new video asset from text.",
|
|
8741
|
+
inputs: commonInputs
|
|
8742
|
+
}];
|
|
8743
|
+
if (VIDEO_MODEL_SUPPORTED_OPERATIONS[selection].includes("refine")) operations.push({
|
|
8744
|
+
operation: "refine",
|
|
8745
|
+
tool: "edit_video",
|
|
8746
|
+
description: "Create a new sibling variant from a completed video variant.",
|
|
8747
|
+
inputs: [
|
|
8748
|
+
SPACE_INPUT,
|
|
8749
|
+
fixedInput("generator_id", `video/${selection}`, "Selects this video generator."),
|
|
8750
|
+
input("asset_ref", "string", true, "Target video asset reference from find_assets."),
|
|
8751
|
+
input("source_variant_ref", "string", true, "Completed video variant to refine."),
|
|
8752
|
+
PROMPT_INPUT,
|
|
8753
|
+
...parameterInputs
|
|
8754
|
+
]
|
|
8755
|
+
});
|
|
8756
|
+
if (VIDEO_MODEL_SUPPORTED_OPERATIONS[selection].includes("derive")) operations.push({
|
|
8757
|
+
operation: "derive",
|
|
8758
|
+
tool: "generate_video",
|
|
8759
|
+
description: "Create a new video from completed image variants.",
|
|
8760
|
+
inputs: [...commonInputs, input("reference_variant_refs", "string_array", true, "Completed image variant references from find_assets or get_asset.", {
|
|
8761
|
+
minItems: 1,
|
|
8762
|
+
maxItems: maxReferences
|
|
8763
|
+
})]
|
|
8764
|
+
});
|
|
8765
|
+
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."];
|
|
8766
|
+
return {
|
|
8767
|
+
id: `video/${selection}`,
|
|
8768
|
+
label: VIDEO_MODEL_LABELS[selection],
|
|
8769
|
+
mediaKind: "video",
|
|
8770
|
+
modelIds,
|
|
8771
|
+
defaultModelId: defaultModel,
|
|
8772
|
+
operations,
|
|
8773
|
+
referenceRules: {
|
|
8774
|
+
mediaKind: maxReferences > 0 ? "image" : null,
|
|
8775
|
+
completedOnly: maxReferences > 0,
|
|
8776
|
+
maxCount: maxReferences
|
|
8777
|
+
},
|
|
8778
|
+
notes
|
|
8779
|
+
};
|
|
8780
|
+
}
|
|
8781
|
+
function seedanceVideoGenerator(capability) {
|
|
8782
|
+
const fixedGenerator = fixedInput("generator_id", capability.generatorId, "Selects this exact Seedance 2 mode and tier.");
|
|
8783
|
+
const parameters = [
|
|
8784
|
+
input("aspect_ratio", "string", false, "Output aspect ratio; auto lets Seedance infer it.", {
|
|
8785
|
+
allowedValues: capability.aspectRatios,
|
|
8786
|
+
defaultValue: capability.defaultAspectRatio
|
|
8787
|
+
}),
|
|
8788
|
+
input("resolution", "string", false, "Output resolution.", {
|
|
8789
|
+
allowedValues: capability.resolutions,
|
|
8790
|
+
defaultValue: capability.defaultResolution
|
|
8791
|
+
}),
|
|
8792
|
+
input("duration", "string_or_integer", false, "Output seconds from 4 to 15, or auto.", {
|
|
8793
|
+
allowedValues: capability.durations,
|
|
8794
|
+
defaultValue: capability.defaultDuration
|
|
8795
|
+
}),
|
|
8796
|
+
input("generate_audio", "boolean", false, "Generate synchronized native audio.", {
|
|
8797
|
+
allowedValues: [true, false],
|
|
8798
|
+
defaultValue: capability.generateAudio.default
|
|
8799
|
+
}),
|
|
8800
|
+
input("bitrate_mode", "string", false, "Output bitrate quality.", {
|
|
8801
|
+
allowedValues: capability.bitrateModes,
|
|
8802
|
+
defaultValue: capability.defaultBitrateMode
|
|
8803
|
+
})
|
|
8804
|
+
];
|
|
8805
|
+
const common = [
|
|
8806
|
+
SPACE_INPUT,
|
|
8807
|
+
fixedGenerator,
|
|
8808
|
+
NAME_INPUT,
|
|
8809
|
+
input("asset_type", "string", true, "Asset classification stored in the Space."),
|
|
8810
|
+
PROMPT_INPUT,
|
|
8811
|
+
...parameters
|
|
8812
|
+
];
|
|
8813
|
+
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.")];
|
|
8814
|
+
const referenceInputs = [
|
|
8815
|
+
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.", {
|
|
8816
|
+
minItems: 1,
|
|
8817
|
+
maxItems: 9
|
|
8818
|
+
}),
|
|
8819
|
+
input("video_reference_variant_refs", "string_array", false, "Ordered completed videos addressed as @Video1 through @Video3.", {
|
|
8820
|
+
minItems: 1,
|
|
8821
|
+
maxItems: 3
|
|
8822
|
+
}),
|
|
8823
|
+
input("audio_reference_variant_refs", "string_array", false, "Ordered completed audio clips addressed as @Audio1 through @Audio3.", {
|
|
8824
|
+
minItems: 1,
|
|
8825
|
+
maxItems: 3
|
|
8826
|
+
})
|
|
8827
|
+
];
|
|
8828
|
+
const modeInputs = capability.mode === "frame" ? frameInputs : capability.mode === "reference" ? referenceInputs : [];
|
|
8829
|
+
const operations = capability.operations.filter((operation) => operation !== "refine").map((operation) => ({
|
|
8830
|
+
operation,
|
|
8831
|
+
tool: "generate_video",
|
|
8832
|
+
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.",
|
|
8833
|
+
inputs: [...common, ...modeInputs]
|
|
8834
|
+
}));
|
|
8835
|
+
if (capability.operations.includes("refine")) {
|
|
8836
|
+
const budget = getSeedance2ReferenceBudget(capability, "refine");
|
|
8837
|
+
const editReferenceInputs = referenceInputs.map((referenceInput) => referenceInput.name === "video_reference_variant_refs" ? {
|
|
8838
|
+
...referenceInput,
|
|
8839
|
+
maxItems: 2,
|
|
8840
|
+
description: "Up to two additional completed videos addressed as @Video2 and @Video3; the source video is @Video1."
|
|
8841
|
+
} : referenceInput);
|
|
8842
|
+
operations.push({
|
|
8843
|
+
operation: "refine",
|
|
8844
|
+
tool: "edit_video",
|
|
8845
|
+
description: "Edit or continue a completed video using it as @Video1 plus optional ordered references.",
|
|
8846
|
+
referenceLimits: {
|
|
8847
|
+
maxAdditionalCount: budget.maxAdditionalFiles,
|
|
8848
|
+
implicitSourceCount: 1,
|
|
8849
|
+
maxAdditionalByKind: budget.maxAdditionalByKind
|
|
8850
|
+
},
|
|
8851
|
+
inputs: [
|
|
8852
|
+
SPACE_INPUT,
|
|
8853
|
+
fixedGenerator,
|
|
8854
|
+
input("asset_ref", "string", true, "Target video asset reference from find_assets."),
|
|
8855
|
+
input("source_variant_ref", "string", true, "Completed target video used as @Video1."),
|
|
8856
|
+
PROMPT_INPUT,
|
|
8857
|
+
...parameters,
|
|
8858
|
+
...editReferenceInputs
|
|
8859
|
+
]
|
|
8860
|
+
});
|
|
8861
|
+
}
|
|
8862
|
+
return {
|
|
8863
|
+
id: capability.generatorId,
|
|
8864
|
+
label: capability.label,
|
|
8865
|
+
mediaKind: "video",
|
|
8866
|
+
modelIds: [capability.endpointId],
|
|
8867
|
+
defaultModelId: capability.endpointId,
|
|
8868
|
+
operations,
|
|
8869
|
+
referenceRules: {
|
|
8870
|
+
mediaKind: capability.mode === "frame" ? "image" : null,
|
|
8871
|
+
completedOnly: capability.mode !== "text",
|
|
8872
|
+
maxCount: capability.maxReferenceFiles,
|
|
8873
|
+
maxTotalCount: capability.maxReferenceFiles,
|
|
8874
|
+
requiresVisualWithAudio: capability.requiresVisualReferenceWithAudio,
|
|
8875
|
+
modalities: capability.references.map((reference) => ({
|
|
8876
|
+
mediaKind: reference.mediaKind,
|
|
8877
|
+
minCount: reference.minCount,
|
|
8878
|
+
maxCount: reference.maxCount,
|
|
8879
|
+
promptLabel: reference.promptLabel,
|
|
8880
|
+
acceptedMimeTypes: reference.acceptedMimeTypes,
|
|
8881
|
+
maxBytesPerFile: reference.maxBytesPerFile,
|
|
8882
|
+
...reference.combinedMaxBytes !== void 0 ? { combinedMaxBytes: reference.combinedMaxBytes } : {},
|
|
8883
|
+
...reference.combinedDurationSeconds ? { combinedDurationSeconds: reference.combinedDurationSeconds } : {}
|
|
8884
|
+
}))
|
|
8885
|
+
},
|
|
8886
|
+
notes: [
|
|
8887
|
+
"Use compact variant references; binary media input is not accepted.",
|
|
8888
|
+
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.",
|
|
8889
|
+
"Seedance 2 cannot combine authoritative start/end frames with extended multimodal references in one request.",
|
|
8890
|
+
capability.resolutions.includes("4k") ? "Standard supports 480p, 720p, 1080p, and 4K output." : "Fast supports 480p and 720p output."
|
|
8891
|
+
]
|
|
8892
|
+
};
|
|
8893
|
+
}
|
|
8894
|
+
function avatarVideoGenerator(model) {
|
|
8895
|
+
const parameters = [input("mode", "string", false, "Generation quality.", {
|
|
8896
|
+
allowedValues: AVATAR_MODES,
|
|
8897
|
+
defaultValue: "standard"
|
|
8898
|
+
})];
|
|
8899
|
+
return {
|
|
8900
|
+
id: `video/${model}`,
|
|
8901
|
+
label: "Kling Avatar V2",
|
|
8902
|
+
mediaKind: "video",
|
|
8903
|
+
modelIds: [model],
|
|
8904
|
+
defaultModelId: model,
|
|
8905
|
+
operations: [{
|
|
8906
|
+
operation: "derive",
|
|
8907
|
+
tool: "generate_video",
|
|
8908
|
+
description: "Create an Avatar video from one portrait image and one audio Variant.",
|
|
8909
|
+
inputs: [
|
|
8910
|
+
SPACE_INPUT,
|
|
8911
|
+
fixedInput("generator_id", `video/${model}`, "Selects this Avatar generator."),
|
|
8912
|
+
NAME_INPUT,
|
|
8913
|
+
input("asset_type", "string", true, "Asset classification stored in the Space."),
|
|
8914
|
+
input("prompt", "string", false, "Optional motion and expression guidance."),
|
|
8915
|
+
...parameters,
|
|
8916
|
+
input("image_reference_variant_refs", "string_array", true, "Exactly one completed portrait image Variant.", {
|
|
8917
|
+
minItems: 1,
|
|
8918
|
+
maxItems: 1
|
|
8919
|
+
}),
|
|
8920
|
+
input("audio_reference_variant_refs", "string_array", true, "Exactly one completed audio Variant.", {
|
|
8921
|
+
minItems: 1,
|
|
8922
|
+
maxItems: 1
|
|
8923
|
+
})
|
|
8924
|
+
]
|
|
8925
|
+
}],
|
|
8926
|
+
referenceRules: {
|
|
8927
|
+
mediaKind: null,
|
|
8928
|
+
completedOnly: true,
|
|
8929
|
+
maxCount: 2,
|
|
8930
|
+
maxTotalCount: 2,
|
|
8931
|
+
modalities: [{
|
|
8932
|
+
mediaKind: "image",
|
|
8933
|
+
minCount: 1,
|
|
8934
|
+
maxCount: 1,
|
|
8935
|
+
promptLabel: "Portrait",
|
|
8936
|
+
acceptedMimeTypes: [
|
|
8937
|
+
"image/jpeg",
|
|
8938
|
+
"image/png",
|
|
8939
|
+
"image/webp"
|
|
8940
|
+
],
|
|
8941
|
+
maxBytesPerFile: 10 * 1024 * 1024
|
|
8942
|
+
}, {
|
|
8943
|
+
mediaKind: "audio",
|
|
8944
|
+
minCount: 1,
|
|
8945
|
+
maxCount: 1,
|
|
8946
|
+
promptLabel: "Audio",
|
|
8947
|
+
acceptedMimeTypes: [
|
|
8948
|
+
"audio/mpeg",
|
|
8949
|
+
"audio/wav",
|
|
8950
|
+
"audio/x-wav",
|
|
8951
|
+
"audio/mp4",
|
|
8952
|
+
"audio/aac"
|
|
8953
|
+
],
|
|
8954
|
+
maxBytesPerFile: 5 * 1024 * 1024
|
|
8955
|
+
}]
|
|
8956
|
+
},
|
|
8957
|
+
notes: ["Outputs an ordinary video Variant. Provider routing remains internal."]
|
|
8958
|
+
};
|
|
8959
|
+
}
|
|
8960
|
+
function audioGenerator(input_) {
|
|
8961
|
+
const inputs = [
|
|
8962
|
+
SPACE_INPUT,
|
|
8963
|
+
fixedInput("generator_id", input_.id, "Selects this audio generator and mode."),
|
|
8964
|
+
NAME_INPUT,
|
|
8965
|
+
PROMPT_INPUT
|
|
8966
|
+
];
|
|
8967
|
+
if (input_.provider === "elevenlabs" && (input_.assetType === "speech" || input_.assetType === "dialogue")) inputs.push(input("model", "string", false, "Optional ElevenLabs model override.", { defaultValue: input_.modelId }));
|
|
8968
|
+
if (input_.assetType === "speech") inputs.push(input("voice_id", "string", true, "Voice ID returned by list_voices."));
|
|
8969
|
+
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 }));
|
|
8970
|
+
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."];
|
|
8971
|
+
return {
|
|
8972
|
+
id: input_.id,
|
|
8973
|
+
label: input_.label,
|
|
8974
|
+
mediaKind: "audio",
|
|
8975
|
+
modelIds: [input_.modelId],
|
|
8976
|
+
defaultModelId: input_.modelId,
|
|
8977
|
+
operations: [{
|
|
8978
|
+
operation: "generate",
|
|
8979
|
+
tool: "generate_audio",
|
|
8980
|
+
description: `Create a new ${input_.assetType} audio asset.`,
|
|
8981
|
+
inputs
|
|
8982
|
+
}],
|
|
8983
|
+
referenceRules: {
|
|
8984
|
+
mediaKind: null,
|
|
8985
|
+
completedOnly: false,
|
|
8986
|
+
maxCount: 0
|
|
8987
|
+
},
|
|
8988
|
+
notes
|
|
8989
|
+
};
|
|
8990
|
+
}
|
|
8991
|
+
function getGeneratorCatalog(overrides = {}) {
|
|
8992
|
+
const elevenLabsSpeech = overrides.elevenLabsSpeech ?? "eleven_v3";
|
|
8993
|
+
const elevenLabsMusic = overrides.elevenLabsMusic ?? "music_v1";
|
|
8994
|
+
const elevenLabsSfx = overrides.elevenLabsSfx ?? "eleven_text_to_sound_v2";
|
|
8995
|
+
const lyria = overrides.lyria ?? "lyria-3-clip-preview";
|
|
8996
|
+
return [
|
|
8997
|
+
...Object.values(IMAGE_MODEL_CAPABILITIES).map(imageGenerator),
|
|
8998
|
+
...VIDEO_MODEL_SELECTIONS.map(videoGenerator),
|
|
8999
|
+
...SEEDANCE_2_SELECTIONS.map((selection) => seedanceVideoGenerator(SEEDANCE_2_CAPABILITIES[selection])),
|
|
9000
|
+
...AVATAR_MODEL_IDS.map(avatarVideoGenerator),
|
|
9001
|
+
audioGenerator({
|
|
9002
|
+
id: "audio/elevenlabs-speech",
|
|
9003
|
+
label: "ElevenLabs Speech",
|
|
9004
|
+
provider: "elevenlabs",
|
|
9005
|
+
assetType: "speech",
|
|
9006
|
+
modelId: elevenLabsSpeech
|
|
9007
|
+
}),
|
|
9008
|
+
audioGenerator({
|
|
9009
|
+
id: "audio/elevenlabs-dialogue",
|
|
9010
|
+
label: "ElevenLabs Dialogue",
|
|
9011
|
+
provider: "elevenlabs",
|
|
9012
|
+
assetType: "dialogue",
|
|
9013
|
+
modelId: elevenLabsSpeech
|
|
9014
|
+
}),
|
|
9015
|
+
audioGenerator({
|
|
9016
|
+
id: "audio/elevenlabs-music",
|
|
9017
|
+
label: "ElevenLabs Music",
|
|
9018
|
+
provider: "elevenlabs",
|
|
9019
|
+
assetType: "music",
|
|
9020
|
+
modelId: elevenLabsMusic
|
|
9021
|
+
}),
|
|
9022
|
+
audioGenerator({
|
|
9023
|
+
id: "audio/elevenlabs-sfx",
|
|
9024
|
+
label: "ElevenLabs Sound Effects",
|
|
9025
|
+
provider: "elevenlabs",
|
|
9026
|
+
assetType: "sfx",
|
|
9027
|
+
modelId: elevenLabsSfx
|
|
9028
|
+
}),
|
|
9029
|
+
audioGenerator({
|
|
9030
|
+
id: "audio/lyria-music",
|
|
9031
|
+
label: "Lyria Music",
|
|
9032
|
+
provider: "lyria",
|
|
9033
|
+
assetType: "music",
|
|
9034
|
+
modelId: lyria
|
|
9035
|
+
})
|
|
9036
|
+
];
|
|
9037
|
+
}
|
|
9038
|
+
function getGeneratorDefinition(id, overrides = {}) {
|
|
9039
|
+
return getGeneratorCatalog(overrides).find((generator) => generator.id === id);
|
|
9040
|
+
}
|
|
9041
|
+
//#endregion
|
|
9042
|
+
//#region src/shared/generationReferences.ts
|
|
9043
|
+
function isGenerationReference(value) {
|
|
9044
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
9045
|
+
const reference = value;
|
|
9046
|
+
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");
|
|
9047
|
+
}
|
|
9048
|
+
function areGenerationReferencesIndexed(value) {
|
|
9049
|
+
if (!Array.isArray(value)) return false;
|
|
9050
|
+
const modalityCounts = {
|
|
9051
|
+
image: 0,
|
|
9052
|
+
video: 0,
|
|
9053
|
+
audio: 0
|
|
9054
|
+
};
|
|
9055
|
+
return value.every((reference, sequenceIndex) => {
|
|
9056
|
+
if (!isGenerationReference(reference) || reference.sequenceIndex !== sequenceIndex) return false;
|
|
9057
|
+
const expectedModalityIndex = modalityCounts[reference.mediaKind]++;
|
|
9058
|
+
return reference.modalityIndex === expectedModalityIndex;
|
|
9059
|
+
});
|
|
9060
|
+
}
|
|
9061
|
+
//#endregion
|
|
9062
|
+
//#region src/shared/draftMapping.ts
|
|
9063
|
+
/** Generator input names map to the canonical camel-case keys stored in recipes. */
|
|
9064
|
+
var DRAFT_RECIPE_INPUT_KEYS = {
|
|
9065
|
+
asset_type: "assetType",
|
|
9066
|
+
prompt: "prompt",
|
|
9067
|
+
aspect_ratio: "aspectRatio",
|
|
9068
|
+
image_size: "imageSize",
|
|
9069
|
+
model: "model",
|
|
9070
|
+
voice_id: "voiceId",
|
|
9071
|
+
dialogue_voice_ids: "dialogueVoiceIds",
|
|
9072
|
+
generate_audio: "generateAudio",
|
|
9073
|
+
video_resolution: "videoResolution",
|
|
9074
|
+
resolution: "videoResolution",
|
|
9075
|
+
video_duration_seconds: "videoDurationSeconds",
|
|
9076
|
+
video_tier: "videoTier",
|
|
9077
|
+
duration: "seedanceDuration",
|
|
9078
|
+
bitrate_mode: "seedanceBitrateMode"
|
|
9079
|
+
};
|
|
9080
|
+
function draftRecipeInputKey(inputName, generatorId) {
|
|
9081
|
+
if (generatorId === "video/p-video-avatar" && inputName === "resolution") return "avatarResolution";
|
|
9082
|
+
if (generatorId === "video/kling-avatar-v2" && inputName === "mode") return "avatarMode";
|
|
9083
|
+
return DRAFT_RECIPE_INPUT_KEYS[inputName];
|
|
9084
|
+
}
|
|
9085
|
+
var DRAFT_REFERENCE_FIELD = /(?:_variant_refs?|VariantRefs?)$/;
|
|
9086
|
+
/**
|
|
9087
|
+
* The one slot-naming convention used while authoring and resolving Bindings.
|
|
9088
|
+
* Unknown reference slots inherit the Draft output kind.
|
|
9089
|
+
*/
|
|
9090
|
+
function mediaKindForDraftSlot(slot, fallback) {
|
|
9091
|
+
if (slot.startsWith("image_") || slot === "start_frame_variant_ref" || slot === "end_frame_variant_ref" || slot === "reference_variant_refs") return "image";
|
|
9092
|
+
if (slot.startsWith("video_")) return "video";
|
|
9093
|
+
if (slot.startsWith("audio_")) return "audio";
|
|
9094
|
+
return fallback;
|
|
9095
|
+
}
|
|
9096
|
+
function generatorIdForDraftRecipe(mediaMode, recipe) {
|
|
9097
|
+
if (mediaMode === "image") {
|
|
9098
|
+
if (recipe.modelProvider === "custom") throw new Error("Custom-provider image Recipes do not map to a Draft generator");
|
|
9099
|
+
const model = typeof recipe.model === "string" ? recipe.model : "pro";
|
|
9100
|
+
if (!isImageModelSelection(model) && !isImageModelId(model)) throw new Error(`Stored image model ${model} does not map to a Draft generator`);
|
|
9101
|
+
return `image/${getImageModelSelection(model)}`;
|
|
9102
|
+
}
|
|
9103
|
+
if (mediaMode === "video") {
|
|
9104
|
+
const model = typeof recipe.model === "string" ? recipe.model : "veo-3.1";
|
|
9105
|
+
if (isAvatarModelId(model)) return `video/${model}`;
|
|
9106
|
+
const seedance = getSeedance2CapabilityByEndpoint(model);
|
|
9107
|
+
if (seedance) return seedance.generatorId;
|
|
9108
|
+
const selection = getVideoModelSelectionForModel(model);
|
|
9109
|
+
if (!selection) throw new Error(`Stored video model ${model} does not map to a Draft generator`);
|
|
9110
|
+
return `video/${selection}`;
|
|
9111
|
+
}
|
|
9112
|
+
if (mediaMode === "speech") return "audio/elevenlabs-speech";
|
|
9113
|
+
if (mediaMode === "dialogue") return "audio/elevenlabs-dialogue";
|
|
9114
|
+
if (mediaMode === "sfx") return "audio/elevenlabs-sfx";
|
|
9115
|
+
return recipe.musicProvider === "lyria" ? "audio/lyria-music" : "audio/elevenlabs-music";
|
|
9116
|
+
}
|
|
9117
|
+
function mediaModeForDraftRecipe(mediaKind, assetType) {
|
|
9118
|
+
if (mediaKind === "image" || mediaKind === "video") return mediaKind;
|
|
9119
|
+
return getForgeModeForAudioAssetType(assetType);
|
|
9120
|
+
}
|
|
9121
|
+
function buildDraftMapping(args) {
|
|
9122
|
+
const { name, mediaMode, generatorId, recipe, references, destinationKind, destinationAssetId, sourceVariantId } = args;
|
|
9123
|
+
const operation = destinationKind === "sibling" ? "refine" : references.length > 0 ? "derive" : "generate";
|
|
9124
|
+
const operationDefinition = getGeneratorDefinition(generatorId)?.operations.find((candidate) => candidate.operation === operation);
|
|
9125
|
+
if (!operationDefinition) throw new Error(`${generatorId} does not support ${operation} drafts`);
|
|
9126
|
+
const recipeTemplate = { operation };
|
|
9127
|
+
for (const input of operationDefinition.inputs) {
|
|
9128
|
+
const key = draftRecipeInputKey(input.name, generatorId);
|
|
9129
|
+
if (!key) continue;
|
|
9130
|
+
const value = recipe[key];
|
|
9131
|
+
if (value !== void 0) recipeTemplate[key] = value;
|
|
9132
|
+
}
|
|
9133
|
+
const availableSlots = operationDefinition.inputs.filter((input) => DRAFT_REFERENCE_FIELD.test(input.name)).map((input) => input.name);
|
|
9134
|
+
const bindings = [];
|
|
9135
|
+
if (destinationKind === "sibling" && sourceVariantId && availableSlots.includes("source_variant_ref")) bindings.push({
|
|
9136
|
+
slot: "source_variant_ref",
|
|
9137
|
+
sourceKind: "variant",
|
|
9138
|
+
sourceVariantId,
|
|
9139
|
+
sortIndex: 0
|
|
9140
|
+
});
|
|
9141
|
+
const outputMediaKind = getMediaKindForForgeMode(mediaMode);
|
|
9142
|
+
const additionalSlots = availableSlots.filter((slot) => slot !== "source_variant_ref");
|
|
9143
|
+
const usedScalarSlots = /* @__PURE__ */ new Set();
|
|
9144
|
+
for (const [index, reference] of references.entries()) {
|
|
9145
|
+
const targetSlot = additionalSlots.filter((slot) => mediaKindForDraftSlot(slot, outputMediaKind) === reference.mediaKind).find((slot) => slot.endsWith("_refs") || !usedScalarSlots.has(slot));
|
|
9146
|
+
if (!targetSlot) throw new Error(`No ${reference.mediaKind} input slot is available for ${generatorId}`);
|
|
9147
|
+
if (!targetSlot.endsWith("_refs")) usedScalarSlots.add(targetSlot);
|
|
9148
|
+
bindings.push({
|
|
9149
|
+
id: reference.id,
|
|
9150
|
+
slot: targetSlot,
|
|
9151
|
+
sourceKind: reference.sourceKind,
|
|
9152
|
+
sourceVariantId: reference.sourceVariantId,
|
|
9153
|
+
sourceAssetId: reference.sourceAssetId,
|
|
9154
|
+
sourceDraftId: reference.sourceDraftId,
|
|
9155
|
+
sortIndex: index
|
|
9156
|
+
});
|
|
9157
|
+
}
|
|
9158
|
+
return {
|
|
9159
|
+
name,
|
|
9160
|
+
mediaMode,
|
|
9161
|
+
generatorId,
|
|
9162
|
+
recipeTemplate,
|
|
9163
|
+
destinationKind,
|
|
9164
|
+
destinationAssetId: destinationKind === "sibling" ? destinationAssetId : null,
|
|
9165
|
+
bindings
|
|
9166
|
+
};
|
|
9167
|
+
}
|
|
9168
|
+
function materializeDraftFromVariant(args) {
|
|
9169
|
+
const storedRecipe = parseStoredRecipe$1(args.recipe);
|
|
9170
|
+
if (!areGenerationReferencesIndexed(storedRecipe.references)) throw new Error("Variant recipe has invalid references");
|
|
9171
|
+
const mediaMode = args.mediaMode ?? mediaModeForDraftRecipe(args.variantMediaKind, args.assetType ?? stringValue(storedRecipe.assetType));
|
|
9172
|
+
const recipe = args.recipeOverride ?? storedRecipe;
|
|
9173
|
+
const generatorId = args.generatorId ?? generatorIdForDraftRecipe(mediaMode, storedRecipe);
|
|
9174
|
+
const storedOperation = stringValue(storedRecipe.operation);
|
|
9175
|
+
const destinationKind = args.destinationKind ?? (storedOperation === "refine" ? "sibling" : "new_asset");
|
|
9176
|
+
const storedReferences = storedRecipe.references;
|
|
9177
|
+
if (storedOperation === "refine" && destinationKind === "sibling" && storedReferences.length === 0) throw new Error("Stored refine Recipe has no source Variant reference");
|
|
9178
|
+
const preservesStoredRefine = storedOperation === "refine" && destinationKind === "sibling";
|
|
9179
|
+
const sourceVariantId = preservesStoredRefine ? storedReferences[0]?.variantId : destinationKind === "sibling" ? args.variantId : void 0;
|
|
9180
|
+
const additionalReferences = preservesStoredRefine ? storedReferences.slice(1) : storedReferences;
|
|
9181
|
+
return buildDraftMapping({
|
|
9182
|
+
name: args.name?.trim() || args.assetName,
|
|
9183
|
+
mediaMode,
|
|
9184
|
+
generatorId,
|
|
9185
|
+
recipe,
|
|
9186
|
+
references: additionalReferences.map((reference) => ({
|
|
9187
|
+
mediaKind: reference.mediaKind,
|
|
9188
|
+
sourceKind: "variant",
|
|
9189
|
+
sourceVariantId: reference.variantId
|
|
9190
|
+
})),
|
|
9191
|
+
destinationKind,
|
|
9192
|
+
destinationAssetId: destinationKind === "sibling" ? args.destinationAssetId ?? args.assetId : null,
|
|
9193
|
+
sourceVariantId
|
|
9194
|
+
});
|
|
9195
|
+
}
|
|
9196
|
+
function parseStoredRecipe$1(value) {
|
|
9197
|
+
let parsed = value;
|
|
9198
|
+
if (typeof value === "string") try {
|
|
9199
|
+
parsed = JSON.parse(value);
|
|
9200
|
+
} catch {
|
|
9201
|
+
throw new Error("Variant recipe is not valid JSON");
|
|
9202
|
+
}
|
|
9203
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("Variant recipe is not a JSON object");
|
|
9204
|
+
return parsed;
|
|
9205
|
+
}
|
|
9206
|
+
function stringValue(value) {
|
|
9207
|
+
return typeof value === "string" && value.trim() ? value : void 0;
|
|
9208
|
+
}
|
|
9209
|
+
//#endregion
|
|
8363
9210
|
//#region src/cli/commands/drafts.ts
|
|
9211
|
+
var CLI_DRAFT_OPTIONS = {
|
|
9212
|
+
list: [],
|
|
9213
|
+
show: [],
|
|
9214
|
+
create: [
|
|
9215
|
+
"from",
|
|
9216
|
+
"name",
|
|
9217
|
+
"media",
|
|
9218
|
+
"generator",
|
|
9219
|
+
"recipe",
|
|
9220
|
+
"destination",
|
|
9221
|
+
"asset",
|
|
9222
|
+
"x",
|
|
9223
|
+
"y"
|
|
9224
|
+
],
|
|
9225
|
+
update: [
|
|
9226
|
+
"name",
|
|
9227
|
+
"media",
|
|
9228
|
+
"generator",
|
|
9229
|
+
"recipe",
|
|
9230
|
+
"destination",
|
|
9231
|
+
"asset",
|
|
9232
|
+
"x",
|
|
9233
|
+
"y"
|
|
9234
|
+
],
|
|
9235
|
+
delete: [],
|
|
9236
|
+
run: ["request-id", "wait"]
|
|
9237
|
+
};
|
|
8364
9238
|
var defaultDeps$7 = {
|
|
8365
9239
|
loadConfig: loadStoredConfig,
|
|
8366
9240
|
loadProjectConfig,
|
|
8367
9241
|
createMutationClient: (env, spaceId) => WebSocketClient.create(env, spaceId),
|
|
8368
9242
|
print: console.log
|
|
8369
9243
|
};
|
|
9244
|
+
var defaultGraphDeps = {
|
|
9245
|
+
loadConfig: loadStoredConfig,
|
|
9246
|
+
loadProjectConfig,
|
|
9247
|
+
createClient: (env, spaceId) => WebSocketClient.create(env, spaceId),
|
|
9248
|
+
print: console.log
|
|
9249
|
+
};
|
|
8370
9250
|
async function handleDrafts(parsed) {
|
|
8371
9251
|
try {
|
|
8372
9252
|
await executeDrafts(parsed);
|
|
@@ -8383,9 +9263,17 @@ async function handleBindings(parsed) {
|
|
|
8383
9263
|
process$1.exitCode = 1;
|
|
8384
9264
|
}
|
|
8385
9265
|
}
|
|
9266
|
+
async function handleGraph(parsed) {
|
|
9267
|
+
try {
|
|
9268
|
+
await executeGraph(parsed);
|
|
9269
|
+
} catch (error) {
|
|
9270
|
+
console.error("Error:", error instanceof Error ? error.message : error);
|
|
9271
|
+
process$1.exitCode = 1;
|
|
9272
|
+
}
|
|
9273
|
+
}
|
|
8386
9274
|
async function executeDrafts(parsed, deps = defaultDeps$7) {
|
|
8387
9275
|
const subcommand = parsed.positionals[0];
|
|
8388
|
-
if (!subcommand) throw new Error("Drafts command is required: list, create, update, or
|
|
9276
|
+
if (!subcommand) throw new Error("Drafts command is required: list, show, create, update, delete, or run");
|
|
8389
9277
|
rejectUnknownOptions("drafts", subcommand, parsed.options);
|
|
8390
9278
|
const ctx = await buildContext$3(parsed, deps);
|
|
8391
9279
|
if (subcommand === "list") {
|
|
@@ -8395,12 +9283,75 @@ async function executeDrafts(parsed, deps = defaultDeps$7) {
|
|
|
8395
9283
|
return drafts;
|
|
8396
9284
|
}
|
|
8397
9285
|
if (subcommand === "create") {
|
|
8398
|
-
const
|
|
9286
|
+
const fromVariantRef = optionValue$2(parsed.options.from);
|
|
9287
|
+
const name = optionValue$2(parsed.options.name) ?? parsed.positionals.slice(1).join(" ").trim();
|
|
9288
|
+
if (fromVariantRef) {
|
|
9289
|
+
const state = await readDraftState(ctx, deps);
|
|
9290
|
+
const sourceVariantId = requireExactVariantRef$1(fromVariantRef, state);
|
|
9291
|
+
const sourceVariant = state.variants.find((variant) => variant.id === sourceVariantId);
|
|
9292
|
+
const sourceAsset = sourceVariant ? state.assets.find((asset) => asset.id === sourceVariant.asset_id) : void 0;
|
|
9293
|
+
if (!sourceVariant || !sourceAsset) throw new Error("Source Variant is unavailable");
|
|
9294
|
+
if (sourceVariant.status !== "completed") throw new Error("Source Variant must be completed");
|
|
9295
|
+
const destinationKind = parseDestination(parsed.options.destination);
|
|
9296
|
+
const destinationAssetRef = optionValue$2(parsed.options.asset);
|
|
9297
|
+
const mapped = materializeDraftFromVariant({
|
|
9298
|
+
variantId: sourceVariant.id,
|
|
9299
|
+
variantMediaKind: sourceVariant.media_kind,
|
|
9300
|
+
recipe: sourceVariant.recipe,
|
|
9301
|
+
assetName: sourceAsset.name,
|
|
9302
|
+
assetType: sourceAsset.type,
|
|
9303
|
+
assetId: sourceAsset.id,
|
|
9304
|
+
name,
|
|
9305
|
+
mediaMode: parseMediaMode(parsed.options.media),
|
|
9306
|
+
generatorId: optionValue$2(parsed.options.generator),
|
|
9307
|
+
recipeOverride: parseRecipe(parsed.options.recipe),
|
|
9308
|
+
destinationKind,
|
|
9309
|
+
destinationAssetId: destinationAssetRef ? requireAssetRef(destinationAssetRef, state.assets) : void 0
|
|
9310
|
+
});
|
|
9311
|
+
for (const binding of mapped.bindings) {
|
|
9312
|
+
const variantId = binding.sourceVariantId;
|
|
9313
|
+
if (variantId && !state.variants.some((variant) => variant.id === variantId)) throw new Error(`Variant recipe reference ${variantId} is unavailable`);
|
|
9314
|
+
}
|
|
9315
|
+
const created = await withClient(ctx, deps, async (client) => {
|
|
9316
|
+
const draft = await client.createDraft({
|
|
9317
|
+
name: mapped.name,
|
|
9318
|
+
mediaMode: mapped.mediaMode,
|
|
9319
|
+
generatorId: mapped.generatorId,
|
|
9320
|
+
recipeTemplate: mapped.recipeTemplate,
|
|
9321
|
+
destinationKind: mapped.destinationKind,
|
|
9322
|
+
destinationAssetId: mapped.destinationAssetId,
|
|
9323
|
+
canvasX: parseNullableFinite(parsed.options.x, "--x"),
|
|
9324
|
+
canvasY: parseNullableFinite(parsed.options.y, "--y")
|
|
9325
|
+
});
|
|
9326
|
+
const bindings = [];
|
|
9327
|
+
try {
|
|
9328
|
+
for (const binding of mapped.bindings) bindings.push(await client.setBinding({
|
|
9329
|
+
draftId: draft.id,
|
|
9330
|
+
...binding
|
|
9331
|
+
}));
|
|
9332
|
+
} catch (error) {
|
|
9333
|
+
await client.deleteDraft(draft.id);
|
|
9334
|
+
throw error;
|
|
9335
|
+
}
|
|
9336
|
+
return {
|
|
9337
|
+
draft,
|
|
9338
|
+
bindings
|
|
9339
|
+
};
|
|
9340
|
+
});
|
|
9341
|
+
const resultState = {
|
|
9342
|
+
...state,
|
|
9343
|
+
drafts: [...state.drafts, created.draft],
|
|
9344
|
+
bindings: [...state.bindings, ...created.bindings]
|
|
9345
|
+
};
|
|
9346
|
+
const result = publicDraft(created.draft, resultState);
|
|
9347
|
+
printJsonOrValue(parsed, deps, result, () => deps.print(`Created Draft ${result.draftRef}`));
|
|
9348
|
+
return created.draft;
|
|
9349
|
+
}
|
|
8399
9350
|
const mediaMode = parseMediaMode(parsed.options.media);
|
|
8400
9351
|
const generatorId = optionValue$2(parsed.options.generator);
|
|
8401
9352
|
const recipeTemplate = parseRecipe(parsed.options.recipe);
|
|
8402
9353
|
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>]");
|
|
9354
|
+
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
9355
|
const state = await readDraftState(ctx, deps);
|
|
8405
9356
|
const destinationAssetRef = optionValue$2(parsed.options.asset);
|
|
8406
9357
|
const destinationAssetId = destinationAssetRef ? requireAssetRef(destinationAssetRef, state.assets) : null;
|
|
@@ -8425,6 +9376,52 @@ async function executeDrafts(parsed, deps = defaultDeps$7) {
|
|
|
8425
9376
|
if (!draftRef) throw new Error(`Usage: makefx drafts ${subcommand} <draft-ref>`);
|
|
8426
9377
|
const state = await readDraftState(ctx, deps);
|
|
8427
9378
|
const draftId = requireDraftRef(draftRef, state.drafts);
|
|
9379
|
+
if (subcommand === "show") {
|
|
9380
|
+
const draft = state.drafts.find((candidate) => candidate.id === draftId);
|
|
9381
|
+
if (!draft) throw new Error("Draft is unavailable");
|
|
9382
|
+
const result = publicDraft(draft, state);
|
|
9383
|
+
printJsonOrValue(parsed, deps, result, () => printDraft(result, deps.print));
|
|
9384
|
+
return result;
|
|
9385
|
+
}
|
|
9386
|
+
if (subcommand === "run") {
|
|
9387
|
+
const requestId = optionValue$2(parsed.options["request-id"]) ?? crypto.randomUUID();
|
|
9388
|
+
const waitSeconds = parsed.options.wait === void 0 ? void 0 : parseGraphWaitSeconds(parsed.options.wait);
|
|
9389
|
+
const run = await withClient(ctx, deps, async (client) => {
|
|
9390
|
+
if (!client.runDraft) throw new Error("The connected client does not support Draft runs");
|
|
9391
|
+
if (waitSeconds !== void 0 && !client.followVariant) throw new Error("The connected client does not support waiting for Draft runs");
|
|
9392
|
+
let outcomePromise;
|
|
9393
|
+
const started = await client.runDraft(draftId, requestId, waitSeconds === void 0 ? void 0 : (runStarted) => {
|
|
9394
|
+
if (runStarted.status !== "completed" && runStarted.status !== "failed") outcomePromise = client.followVariant({
|
|
9395
|
+
variantId: runStarted.variantId,
|
|
9396
|
+
requestId,
|
|
9397
|
+
timeoutMs: waitSeconds * 1e3
|
|
9398
|
+
});
|
|
9399
|
+
});
|
|
9400
|
+
if (waitSeconds === void 0 || started.status === "completed" || started.status === "failed") return {
|
|
9401
|
+
started,
|
|
9402
|
+
terminalStatus: started.status
|
|
9403
|
+
};
|
|
9404
|
+
if (!outcomePromise) throw new Error("Draft run wait was not initialized");
|
|
9405
|
+
return {
|
|
9406
|
+
started,
|
|
9407
|
+
terminalStatus: (await outcomePromise).success ? "completed" : "failed"
|
|
9408
|
+
};
|
|
9409
|
+
});
|
|
9410
|
+
const updatedState = await readDraftState(ctx, deps);
|
|
9411
|
+
const variantRef = variantRefForId(run.started.variantId, updatedState.assets, updatedState.variants);
|
|
9412
|
+
if (!variantRef) throw new Error("Draft run Variant is unavailable");
|
|
9413
|
+
const result = {
|
|
9414
|
+
draftRef,
|
|
9415
|
+
requestId,
|
|
9416
|
+
variantRef,
|
|
9417
|
+
status: run.terminalStatus
|
|
9418
|
+
};
|
|
9419
|
+
printJsonOrValue(parsed, deps, result, () => {
|
|
9420
|
+
deps.print(`${parsed.options.wait === void 0 ? "Started" : "Finished"} ${draftRef} (${run.terminalStatus})`);
|
|
9421
|
+
if (variantRef) deps.print(` Variant: ${variantRef}`);
|
|
9422
|
+
});
|
|
9423
|
+
return result;
|
|
9424
|
+
}
|
|
8428
9425
|
if (subcommand === "update") {
|
|
8429
9426
|
const destinationAssetRef = optionValue$2(parsed.options.asset);
|
|
8430
9427
|
const changes = {
|
|
@@ -8495,6 +9492,47 @@ async function executeBindings(parsed, deps = defaultDeps$7) {
|
|
|
8495
9492
|
printJsonOrValue(parsed, deps, publicBinding(binding, state), () => deps.print(`Set ${slot}[${sortIndex}] on ${draftRef}`));
|
|
8496
9493
|
return binding;
|
|
8497
9494
|
}
|
|
9495
|
+
async function executeGraph(parsed, deps = defaultGraphDeps) {
|
|
9496
|
+
const subcommand = parsed.positionals[0];
|
|
9497
|
+
if (subcommand !== "run" && subcommand !== "status" && subcommand !== "cancel") throw new Error("Graph command is required: run, status, or cancel");
|
|
9498
|
+
rejectGraphUnknownOptions(subcommand, parsed.options);
|
|
9499
|
+
const ctx = await buildContext$3(parsed, deps);
|
|
9500
|
+
const state = await readDraftState(ctx, { createMutationClient: deps.createClient });
|
|
9501
|
+
const client = await deps.createClient(ctx.env, ctx.spaceId);
|
|
9502
|
+
await client.connect();
|
|
9503
|
+
try {
|
|
9504
|
+
if (subcommand === "status" || subcommand === "cancel") {
|
|
9505
|
+
const runRef = parsed.positionals[1];
|
|
9506
|
+
if (!runRef) throw new Error(`Usage: makefx graph ${subcommand} <graph-run-ref>`);
|
|
9507
|
+
const current = await client.getGraphRunStatus(runRef);
|
|
9508
|
+
const status = subcommand === "cancel" ? await client.cancelGraphRun(current.run.id) : current;
|
|
9509
|
+
const result = publicGraphRun(status.run, status.drafts, state);
|
|
9510
|
+
printJsonOrValue(parsed, deps, result, () => {
|
|
9511
|
+
if (subcommand === "cancel") deps.print(`Cancelled pending work in ${runRef}`);
|
|
9512
|
+
printGraphRun(result, deps.print);
|
|
9513
|
+
});
|
|
9514
|
+
return result;
|
|
9515
|
+
}
|
|
9516
|
+
const draftRefs = parsed.positionals.slice(1);
|
|
9517
|
+
if (draftRefs.length === 0) throw new Error("Usage: makefx graph run <draft-ref> [draft-ref...] [--upstream] [--downstream] [--from-scratch] [--wait]");
|
|
9518
|
+
const requestId = optionValue$2(parsed.options["request-id"]) ?? crypto.randomUUID();
|
|
9519
|
+
let status = await client.runGraph({
|
|
9520
|
+
draftIds: draftRefs.map((draftRef) => requireDraftRef(draftRef, state.drafts)),
|
|
9521
|
+
requestId,
|
|
9522
|
+
includeUpstream: parsed.options.upstream === "true",
|
|
9523
|
+
includeDownstream: parsed.options.downstream === "true",
|
|
9524
|
+
fromScratch: parsed.options["from-scratch"] === "true"
|
|
9525
|
+
});
|
|
9526
|
+
const runRef = createGraphRunRef(status.run.id);
|
|
9527
|
+
if (parsed.options.wait !== void 0 && status.run.status === "running") status = await client.waitForGraphRun(runRef, status.run.id, parseGraphWaitSeconds(parsed.options.wait) * 1e3);
|
|
9528
|
+
const freshState = await readDraftState(ctx, { createMutationClient: deps.createClient });
|
|
9529
|
+
const result = publicGraphRun(status.run, status.drafts, freshState);
|
|
9530
|
+
printJsonOrValue(parsed, deps, result, () => printGraphRun(result, deps.print));
|
|
9531
|
+
return result;
|
|
9532
|
+
} finally {
|
|
9533
|
+
client.disconnect();
|
|
9534
|
+
}
|
|
9535
|
+
}
|
|
8498
9536
|
async function buildContext$3(parsed, deps) {
|
|
8499
9537
|
const project = await deps.loadProjectConfig();
|
|
8500
9538
|
const env = resolveCommandEnvironment(parsed, project);
|
|
@@ -8655,29 +9693,7 @@ function rejectUnknownOptions(noun, subcommand, options) {
|
|
|
8655
9693
|
"local",
|
|
8656
9694
|
"json"
|
|
8657
9695
|
];
|
|
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
|
-
} : {
|
|
9696
|
+
const commands = noun === "drafts" ? CLI_DRAFT_OPTIONS : {
|
|
8681
9697
|
set: [
|
|
8682
9698
|
"source",
|
|
8683
9699
|
"ref",
|
|
@@ -8689,6 +9705,50 @@ function rejectUnknownOptions(noun, subcommand, options) {
|
|
|
8689
9705
|
const unknown = Object.keys(options).find((name) => !allowed.has(name));
|
|
8690
9706
|
if (unknown) throw new Error(`Unknown option for ${noun} ${subcommand}: --${unknown}`);
|
|
8691
9707
|
}
|
|
9708
|
+
function rejectGraphUnknownOptions(subcommand, options) {
|
|
9709
|
+
const allowed = new Set([...[
|
|
9710
|
+
"space",
|
|
9711
|
+
"env",
|
|
9712
|
+
"local",
|
|
9713
|
+
"json"
|
|
9714
|
+
], ...subcommand === "run" ? [
|
|
9715
|
+
"upstream",
|
|
9716
|
+
"downstream",
|
|
9717
|
+
"from-scratch",
|
|
9718
|
+
"wait",
|
|
9719
|
+
"request-id"
|
|
9720
|
+
] : []]);
|
|
9721
|
+
const unknown = Object.keys(options).find((name) => !allowed.has(name));
|
|
9722
|
+
if (unknown) throw new Error(`Unknown option for graph ${subcommand}: --${unknown}`);
|
|
9723
|
+
}
|
|
9724
|
+
function parseGraphWaitSeconds(value) {
|
|
9725
|
+
if (value === void 0 || value === "true") return 1800;
|
|
9726
|
+
const seconds = Number(value);
|
|
9727
|
+
if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 3600) throw new Error("--wait must be between 1 and 3600 seconds");
|
|
9728
|
+
return seconds;
|
|
9729
|
+
}
|
|
9730
|
+
function publicGraphRun(run, drafts, state) {
|
|
9731
|
+
return {
|
|
9732
|
+
runRef: createGraphRunRef(run.id),
|
|
9733
|
+
requestId: run.request_id,
|
|
9734
|
+
status: run.status,
|
|
9735
|
+
drafts: drafts.map((item) => {
|
|
9736
|
+
const draft = state.drafts.find((candidate) => candidate.id === item.draft_id);
|
|
9737
|
+
const ancestor = state.drafts.find((candidate) => candidate.id === item.failing_ancestor_draft_id);
|
|
9738
|
+
return {
|
|
9739
|
+
draftRef: draft ? createDraftRef(draft.name, draft.id) : null,
|
|
9740
|
+
status: item.status,
|
|
9741
|
+
variantRef: item.variant_id ? variantRefForId(item.variant_id, state.assets, state.variants) : null,
|
|
9742
|
+
reused: item.reused,
|
|
9743
|
+
failingAncestorDraftRef: ancestor ? createDraftRef(ancestor.name, ancestor.id) : null
|
|
9744
|
+
};
|
|
9745
|
+
})
|
|
9746
|
+
};
|
|
9747
|
+
}
|
|
9748
|
+
function printGraphRun(result, print) {
|
|
9749
|
+
print(`${result.runRef} (${result.status})`);
|
|
9750
|
+
for (const draft of result.drafts) print(` ${draft.draftRef ?? "unavailable draft"}: ${draft.status}${draft.variantRef ? ` → ${draft.variantRef}` : ""}`);
|
|
9751
|
+
}
|
|
8692
9752
|
function printJsonOrValue(parsed, deps, value, printHuman) {
|
|
8693
9753
|
if (parsed.options.json === "true") deps.print(JSON.stringify(value, null, 2));
|
|
8694
9754
|
else printHuman();
|
|
@@ -8700,6 +9760,20 @@ function printDrafts(drafts, print) {
|
|
|
8700
9760
|
}
|
|
8701
9761
|
for (const draft of drafts) print(`${draft.draftRef} ${draft.mediaMode} ${draft.status} ${draft.name}`);
|
|
8702
9762
|
}
|
|
9763
|
+
function printDraft(draft, print) {
|
|
9764
|
+
print(`${draft.draftRef} ${draft.name}`);
|
|
9765
|
+
print(` Media: ${draft.mediaMode} (${draft.generatorId})`);
|
|
9766
|
+
print(` Destination: ${draft.destination}${draft.destinationAssetRef ? ` → ${draft.destinationAssetRef}` : ""}`);
|
|
9767
|
+
print(` Recipe: ${JSON.stringify(draft.recipeTemplate)}`);
|
|
9768
|
+
const bindings = draft.bindings;
|
|
9769
|
+
print(" Bindings:");
|
|
9770
|
+
if (bindings.length === 0) print(" none");
|
|
9771
|
+
else for (const binding of bindings) {
|
|
9772
|
+
const broken = binding.broken ? ` [broken${binding.brokenReason ? `: ${binding.brokenReason}` : ""}]` : "";
|
|
9773
|
+
print(` ${binding.slot}[${binding.sortIndex}]: ${binding.sourceKind} → ${binding.sourceRef ?? "unavailable"}${broken}`);
|
|
9774
|
+
}
|
|
9775
|
+
print(` Last run: ${draft.lastRunVariantRef ?? "none"}`);
|
|
9776
|
+
}
|
|
8703
9777
|
//#endregion
|
|
8704
9778
|
//#region src/cli/commands/image.ts
|
|
8705
9779
|
async function handleImage(parsed) {
|
|
@@ -9240,7 +10314,7 @@ async function executeModels(parsed, deps = defaultDeps$5) {
|
|
|
9240
10314
|
const { models } = await response.json();
|
|
9241
10315
|
if (parsed.options.json === "true") deps.print(JSON.stringify(models, null, 2));
|
|
9242
10316
|
else for (const model of models) {
|
|
9243
|
-
const readiness = model.availability.available ? "ready" : model.availability.reason
|
|
10317
|
+
const readiness = model.availability.available ? "ready" : [model.availability.code, model.availability.reason].filter(Boolean).join(": ") || "unavailable";
|
|
9244
10318
|
deps.print(`${model.id.padEnd(20)} ${model.media_kind.padEnd(6)} ${readiness}`);
|
|
9245
10319
|
}
|
|
9246
10320
|
return models;
|
|
@@ -9263,6 +10337,7 @@ function formatModelDetail(model) {
|
|
|
9263
10337
|
`Availability: ${model.availability.available ? "ready" : model.availability.reason ?? "unavailable"}`,
|
|
9264
10338
|
"Operations:"
|
|
9265
10339
|
];
|
|
10340
|
+
if (!model.availability.available && model.availability.guidance) lines.splice(3, 0, `Next step: ${model.availability.guidance}`);
|
|
9266
10341
|
for (const operation of model.operations) {
|
|
9267
10342
|
if (typeof operation === "string") {
|
|
9268
10343
|
lines.push(` - ${operation}`);
|
|
@@ -9749,6 +10824,33 @@ var defaultDeps$2 = {
|
|
|
9749
10824
|
print: console.log
|
|
9750
10825
|
};
|
|
9751
10826
|
var UploadUsageError = class extends Error {};
|
|
10827
|
+
var LINEAGE_RELATION_TYPES = new Set([
|
|
10828
|
+
"derived",
|
|
10829
|
+
"refined",
|
|
10830
|
+
"forked"
|
|
10831
|
+
]);
|
|
10832
|
+
function parseLineageOption(raw, defaultRelationType) {
|
|
10833
|
+
if (!raw) return [];
|
|
10834
|
+
const entries = raw.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
10835
|
+
if (entries.length === 0) throw new UploadUsageError("--lineage requires at least one compact variant ref");
|
|
10836
|
+
return entries.map((entry) => {
|
|
10837
|
+
const atIndex = entry.lastIndexOf("@");
|
|
10838
|
+
const separator = entry.lastIndexOf(":");
|
|
10839
|
+
let ref = entry;
|
|
10840
|
+
let relationType = defaultRelationType;
|
|
10841
|
+
if (atIndex !== -1 && separator > atIndex) {
|
|
10842
|
+
const suffix = entry.slice(separator + 1);
|
|
10843
|
+
if (!LINEAGE_RELATION_TYPES.has(suffix)) throw new UploadUsageError(`--lineage relation in "${entry}" must be derived, refined, or forked`);
|
|
10844
|
+
ref = entry.slice(0, separator);
|
|
10845
|
+
relationType = suffix;
|
|
10846
|
+
}
|
|
10847
|
+
if (!ref.startsWith("asset:")) throw new UploadUsageError(`--lineage requires compact variant refs, got "${ref}"`);
|
|
10848
|
+
return {
|
|
10849
|
+
ref,
|
|
10850
|
+
relationType
|
|
10851
|
+
};
|
|
10852
|
+
});
|
|
10853
|
+
}
|
|
9752
10854
|
async function handleUpload(parsed) {
|
|
9753
10855
|
try {
|
|
9754
10856
|
await executeUpload(parsed);
|
|
@@ -9773,6 +10875,7 @@ async function executeUpload(parsed, deps = defaultDeps$2) {
|
|
|
9773
10875
|
const jsonOutput = parsed.options.json === "true";
|
|
9774
10876
|
if (!spaceId) throw new UploadUsageError("--space is required, or run: makefx init --space <id>");
|
|
9775
10877
|
if (!assetId && !assetName) throw new UploadUsageError("Either --asset or --name is required");
|
|
10878
|
+
const lineageEntries = parseLineageOption(parsed.options.lineage, assetId ? "refined" : "derived");
|
|
9776
10879
|
const mediaType = resolveMediaType(path.extname(filePath).toLowerCase(), requestedMediaKind);
|
|
9777
10880
|
const config = await deps.loadConfig(env);
|
|
9778
10881
|
if (!config) throw new Error(`Not logged in to ${env} environment. Run: ${loginCommandForEnvironment(env)}`);
|
|
@@ -9780,7 +10883,16 @@ async function executeUpload(parsed, deps = defaultDeps$2) {
|
|
|
9780
10883
|
const baseUrl = deps.resolveBaseUrl(env);
|
|
9781
10884
|
const accessToken = config.token.accessToken;
|
|
9782
10885
|
const createStateClient = () => (deps.createStateClient ?? defaultDeps$2.createStateClient)(env, spaceId);
|
|
9783
|
-
|
|
10886
|
+
let lineage = [];
|
|
10887
|
+
if (assetId || lineageEntries.length > 0) {
|
|
10888
|
+
if (assetId && !assetId.startsWith("asset:")) throw new Error("A compact asset ref is required");
|
|
10889
|
+
const state = await readReferenceSpaceState(createStateClient);
|
|
10890
|
+
if (assetId) assetId = resolveAssetRef(assetId, state.assets);
|
|
10891
|
+
lineage = lineageEntries.map((entry) => ({
|
|
10892
|
+
parentVariantId: resolveVariantRef(entry.ref, state.assets, state.variants),
|
|
10893
|
+
relationType: entry.relationType
|
|
10894
|
+
}));
|
|
10895
|
+
}
|
|
9784
10896
|
if (env === "local") process$1.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
9785
10897
|
try {
|
|
9786
10898
|
const fileStat = await deps.stat(filePath);
|
|
@@ -9798,11 +10910,13 @@ async function executeUpload(parsed, deps = defaultDeps$2) {
|
|
|
9798
10910
|
formData.append("assetName", assetName);
|
|
9799
10911
|
formData.append("assetType", assetType);
|
|
9800
10912
|
}
|
|
10913
|
+
if (lineage.length > 0) formData.append("lineage", JSON.stringify(lineage));
|
|
9801
10914
|
if (!jsonOutput) {
|
|
9802
10915
|
deps.print(`\nUploading "${fileName}" to space ${spaceId}...`);
|
|
9803
10916
|
deps.print(` Media kind: ${mediaType.mediaKind}`);
|
|
9804
10917
|
if (assetId) deps.print(` Target asset: ${requestedAssetRef}`);
|
|
9805
10918
|
else deps.print(` Creating asset: "${assetName}" (${assetType})`);
|
|
10919
|
+
for (const entry of lineageEntries) deps.print(` Lineage: ${entry.relationType} from ${entry.ref}`);
|
|
9806
10920
|
}
|
|
9807
10921
|
const response = await deps.fetch(`${baseUrl}/api/spaces/${spaceId}/upload`, {
|
|
9808
10922
|
method: "POST",
|
|
@@ -9888,6 +11002,7 @@ function rejectUnknownUploadOptions(options) {
|
|
|
9888
11002
|
"name",
|
|
9889
11003
|
"type",
|
|
9890
11004
|
"media-kind",
|
|
11005
|
+
"lineage",
|
|
9891
11006
|
"json"
|
|
9892
11007
|
]);
|
|
9893
11008
|
const unknown = Object.keys(options).find((name) => !allowed.has(name));
|
|
@@ -9905,6 +11020,9 @@ Options:
|
|
|
9905
11020
|
--name <name> New asset name (creates asset + variant)
|
|
9906
11021
|
--type <type> Asset type for new assets (default: character)
|
|
9907
11022
|
--media-kind <k> Optional explicit kind: image, audio, or video
|
|
11023
|
+
--lineage <refs> Source variant refs this upload was made from, comma-separated,
|
|
11024
|
+
each optionally suffixed :derived, :refined, or :forked
|
|
11025
|
+
(default: refined with --asset, derived with --name)
|
|
9908
11026
|
--json Print machine-readable output
|
|
9909
11027
|
--env <env> Environment (production|stage|local)
|
|
9910
11028
|
--local Shortcut for --env local
|
|
@@ -9912,6 +11030,7 @@ Options:
|
|
|
9912
11030
|
Examples:
|
|
9913
11031
|
makefx assets upload hero.png --name "Hero Character"
|
|
9914
11032
|
makefx assets upload paintover.png --asset asset:hero~27f8f176
|
|
11033
|
+
makefx assets upload paintover.png --asset asset:hero~27f8f176 --lineage asset:hero~27f8f176@active
|
|
9915
11034
|
`);
|
|
9916
11035
|
}
|
|
9917
11036
|
//#endregion
|
|
@@ -10317,15 +11436,47 @@ async function handleVideo(parsed) {
|
|
|
10317
11436
|
}
|
|
10318
11437
|
}
|
|
10319
11438
|
//#endregion
|
|
10320
|
-
//#region src/cli/
|
|
10321
|
-
var
|
|
11439
|
+
//#region src/cli/help.ts
|
|
11440
|
+
var TOP_LEVEL_HELP = `Make Effects CLI
|
|
11441
|
+
|
|
11442
|
+
Creative:
|
|
11443
|
+
models list | show
|
|
11444
|
+
image generate | regenerate
|
|
11445
|
+
video generate | regenerate
|
|
11446
|
+
audio speech|dialogue|music|sfx generate|regenerate
|
|
11447
|
+
audio voices
|
|
11448
|
+
audio align
|
|
11449
|
+
|
|
11450
|
+
Assets:
|
|
11451
|
+
assets list | show | update | delete | upload | download
|
|
11452
|
+
variants show | update | activate | retry | delete
|
|
11453
|
+
collections list | show | create | update | delete | add | remove | pin | unpin
|
|
11454
|
+
drafts list | show | create | update | delete | run
|
|
11455
|
+
bindings set | clear
|
|
11456
|
+
graph run | status | cancel
|
|
11457
|
+
|
|
11458
|
+
Workspace:
|
|
11459
|
+
spaces list | show | create | delete | lens
|
|
11460
|
+
init | login | logout
|
|
11461
|
+
usage | spend | billing
|
|
11462
|
+
|
|
11463
|
+
Assets and variants use compact refs:
|
|
11464
|
+
asset:name~prefix
|
|
11465
|
+
asset:name~prefix@variant
|
|
11466
|
+
|
|
11467
|
+
Run makefx help <noun> for details.`;
|
|
10322
11468
|
var HELP = {
|
|
10323
11469
|
image: `Usage:
|
|
10324
|
-
makefx image generate "prompt" --name <name> --type <type> -o <file> [--model pro|flash|flux] [--refs <variant-ref-or-file,...>]
|
|
11470
|
+
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
11471
|
makefx image regenerate <variant-ref> ["prompt"] [--model pro|flash|flux] [--aspect <ratio>] [--size <size>] [--refs <refs>] [--no-activate] [--wait]`,
|
|
10326
11472
|
video: `Usage:
|
|
10327
11473
|
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
|
-
|
|
11474
|
+
[--refs <variant-ref-or-file,...>] [--first-frame <ref>] [--last-frame <ref>] [--image-refs <refs>] [--video-refs <refs>] [--audio-refs <refs>]
|
|
11475
|
+
[--aspect <ratio>] [--resolution 480p|720p|1080p|4k] [--duration <seconds|auto>] [--tier generate|fast|lite] [--bitrate standard|high]
|
|
11476
|
+
[--audio | --no-audio] [--collection <id>] [--space <id>]
|
|
11477
|
+
makefx video generate ["prompt"] --model kling-avatar-v2 --image-refs <portrait-ref> --audio-refs <audio-ref>
|
|
11478
|
+
--name <name> --type <type> -o <file> [--mode standard|pro] [--collection <id>] [--space <id>]
|
|
11479
|
+
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
11480
|
|
|
10330
11481
|
Seedance mode is inferred: first/last frame selects frame mode, image/video/audio refs select reference mode, and no references selects text mode.`,
|
|
10331
11482
|
audio: `Usage:
|
|
@@ -10339,7 +11490,9 @@ Seedance mode is inferred: first/last frame selects frame mode, image/video/audi
|
|
|
10339
11490
|
makefx audio music generate "prompt" --model eleven-music|lyria-3 --name <name> -o <file>
|
|
10340
11491
|
makefx audio music regenerate <variant-ref> ["prompt"] [--model eleven-music|lyria-3] [--no-activate] [--wait]
|
|
10341
11492
|
makefx audio sfx generate "prompt" --name <name> -o <file>
|
|
10342
|
-
makefx audio sfx regenerate <variant-ref> ["prompt"] [--no-activate] [--wait]
|
|
11493
|
+
makefx audio sfx regenerate <variant-ref> ["prompt"] [--no-activate] [--wait]
|
|
11494
|
+
|
|
11495
|
+
Generate commands also accept [--collection <id>] [--space <id>].`,
|
|
10343
11496
|
models: `Usage:
|
|
10344
11497
|
makefx models list [--media image|video|audio] [--available] [--json]
|
|
10345
11498
|
makefx models show <model> [--json]`,
|
|
@@ -10348,8 +11501,12 @@ Seedance mode is inferred: first/last frame selects frame mode, image/video/audi
|
|
|
10348
11501
|
makefx assets show <asset-ref> [--json]
|
|
10349
11502
|
makefx assets update <asset-ref> [--name <name>] [--type <type>] [--tags <tag,...>]
|
|
10350
11503
|
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
|
|
11504
|
+
makefx assets upload <file> (--name <name> | --asset <asset-ref>) [--type <type>] [--lineage <variant-ref[:relation],...>]
|
|
11505
|
+
makefx assets download <variant-ref> -o <file>
|
|
11506
|
+
|
|
11507
|
+
Upload --lineage records which variants the file was made from: comma-separated
|
|
11508
|
+
compact variant refs, each optionally suffixed :derived, :refined, or :forked
|
|
11509
|
+
(default: refined when uploading to --asset, derived when creating with --name).`,
|
|
10353
11510
|
variants: `Usage:
|
|
10354
11511
|
makefx variants show <variant-ref> [--wait <seconds>] [--json]
|
|
10355
11512
|
makefx variants update <variant-ref> [--starred true|false] [--rating approved|rejected|none]
|
|
@@ -10368,9 +11525,15 @@ Seedance mode is inferred: first/last frame selects frame mode, image/video/audi
|
|
|
10368
11525
|
makefx collections unpin <collection-id>`,
|
|
10369
11526
|
drafts: `Usage:
|
|
10370
11527
|
makefx drafts list [--json]
|
|
10371
|
-
makefx drafts
|
|
10372
|
-
makefx drafts
|
|
10373
|
-
makefx drafts
|
|
11528
|
+
makefx drafts show <draft-ref> [--json]
|
|
11529
|
+
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>]
|
|
11530
|
+
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>]
|
|
11531
|
+
makefx drafts delete <draft-ref>
|
|
11532
|
+
makefx drafts run <draft-ref> [--request-id <id>] [--wait [seconds]]`,
|
|
11533
|
+
graph: `Usage:
|
|
11534
|
+
makefx graph run <draft-ref> [draft-ref...] [--upstream] [--downstream] [--from-scratch] [--wait [seconds]]
|
|
11535
|
+
makefx graph status <graph-run-ref> [--json]
|
|
11536
|
+
makefx graph cancel <graph-run-ref> [--json]`,
|
|
10374
11537
|
bindings: `Usage:
|
|
10375
11538
|
makefx bindings set <draft-ref> <slot> --source variant|asset-active|draft-output --ref <ref> [--sort <index>]
|
|
10376
11539
|
makefx bindings clear <draft-ref> <slot> [--sort <index>]`,
|
|
@@ -10391,34 +11554,11 @@ Seedance mode is inferred: first/last frame selects frame mode, image/video/audi
|
|
|
10391
11554
|
makefx billing reconcile
|
|
10392
11555
|
makefx billing retry-failed`
|
|
10393
11556
|
};
|
|
11557
|
+
//#endregion
|
|
11558
|
+
//#region src/cli/index.ts
|
|
11559
|
+
var CLI_VERSION = "1.6.0+e2eab203b853";
|
|
10394
11560
|
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.`);
|
|
11561
|
+
console.log(TOP_LEVEL_HELP);
|
|
10422
11562
|
}
|
|
10423
11563
|
function printCommandHelp(noun) {
|
|
10424
11564
|
if (!noun) {
|
|
@@ -10449,6 +11589,7 @@ async function dispatchCommand(command, parsed) {
|
|
|
10449
11589
|
case "collections": return handleCollections(parsed);
|
|
10450
11590
|
case "drafts": return handleDrafts(parsed);
|
|
10451
11591
|
case "bindings": return handleBindings(parsed);
|
|
11592
|
+
case "graph": return handleGraph(parsed);
|
|
10452
11593
|
case "usage": return handleUsage(parsed);
|
|
10453
11594
|
case "spend": return handleSpend(parsed);
|
|
10454
11595
|
case "variants": return handleVariants(parsed);
|