makefx 0.2.0 → 0.2.2
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 +2 -2
- package/makefx.mjs +356 -881
- package/package.json +1 -1
package/makefx.mjs
CHANGED
|
@@ -839,7 +839,7 @@ function validateProjectConfig(config, configPath) {
|
|
|
839
839
|
* makefx spaces --id <space_id> Show details for a specific space
|
|
840
840
|
* makefx spaces create <name> Create a new space
|
|
841
841
|
*/
|
|
842
|
-
var defaultDeps$
|
|
842
|
+
var defaultDeps$12 = {
|
|
843
843
|
loadConfig: loadStoredConfig,
|
|
844
844
|
resolveBaseUrl,
|
|
845
845
|
saveProjectConfig,
|
|
@@ -854,7 +854,7 @@ async function handleSpaces(parsed) {
|
|
|
854
854
|
process$1.exitCode = 1;
|
|
855
855
|
}
|
|
856
856
|
}
|
|
857
|
-
async function executeSpaces(parsed, deps = defaultDeps$
|
|
857
|
+
async function executeSpaces(parsed, deps = defaultDeps$12) {
|
|
858
858
|
const env = resolveCommandEnvironment(parsed);
|
|
859
859
|
const showDetails = parsed.options.details === "true";
|
|
860
860
|
const spaceId = parsed.options.id;
|
|
@@ -5056,7 +5056,28 @@ var EXT_TO_MEDIA_TYPE = {
|
|
|
5056
5056
|
}
|
|
5057
5057
|
};
|
|
5058
5058
|
var ALLOWED_EXTENSIONS$1 = Object.keys(EXT_TO_MEDIA_TYPE).sort();
|
|
5059
|
-
|
|
5059
|
+
function resolveMediaType(ext, requestedMediaKind) {
|
|
5060
|
+
const mediaType = EXT_TO_MEDIA_TYPE[ext];
|
|
5061
|
+
if (!mediaType) throw new Error(`Invalid file type "${ext}". Allowed types: ${ALLOWED_EXTENSIONS$1.join(", ")}`);
|
|
5062
|
+
if (requestedMediaKind !== void 0 && requestedMediaKind !== "image" && requestedMediaKind !== "audio" && requestedMediaKind !== "video") throw new Error("Invalid --media-kind. Expected image, audio, or video");
|
|
5063
|
+
if (ext === ".webm" && requestedMediaKind === "audio") return {
|
|
5064
|
+
mediaKind: "audio",
|
|
5065
|
+
mimeType: "audio/webm"
|
|
5066
|
+
};
|
|
5067
|
+
if (requestedMediaKind && requestedMediaKind !== mediaType.mediaKind) throw new Error(`--media-kind ${requestedMediaKind} does not match ${ext} (${mediaType.mediaKind})`);
|
|
5068
|
+
return mediaType;
|
|
5069
|
+
}
|
|
5070
|
+
//#endregion
|
|
5071
|
+
//#region src/cli/commands/upload.ts
|
|
5072
|
+
/**
|
|
5073
|
+
* Upload Command - Upload one media file to create variants
|
|
5074
|
+
*
|
|
5075
|
+
* Usage:
|
|
5076
|
+
* makefx upload <file> --space <id> --asset <id> Upload to existing asset
|
|
5077
|
+
* makefx upload <file> --space <id> --name <name> Upload as new asset
|
|
5078
|
+
* makefx upload <file> --space <id> --name <name> --type <type>
|
|
5079
|
+
*/
|
|
5080
|
+
var defaultDeps$11 = {
|
|
5060
5081
|
loadConfig: loadStoredConfig,
|
|
5061
5082
|
loadProjectConfig,
|
|
5062
5083
|
resolveBaseUrl,
|
|
@@ -5071,11 +5092,13 @@ async function handleUpload(parsed) {
|
|
|
5071
5092
|
await executeUpload(parsed);
|
|
5072
5093
|
} catch (error) {
|
|
5073
5094
|
console.error(error instanceof Error ? `Error: ${error.message}` : "Error: Upload failed");
|
|
5074
|
-
if (error instanceof UploadUsageError) printUsage$
|
|
5095
|
+
if (error instanceof UploadUsageError) printUsage$11();
|
|
5075
5096
|
process$1.exitCode = 1;
|
|
5076
5097
|
}
|
|
5077
5098
|
}
|
|
5078
|
-
async function executeUpload(parsed, deps = defaultDeps$
|
|
5099
|
+
async function executeUpload(parsed, deps = defaultDeps$11) {
|
|
5100
|
+
const filePath = parsed.positionals[0];
|
|
5101
|
+
if (!filePath) throw new UploadUsageError("File path is required");
|
|
5079
5102
|
const projectConfig = await deps.loadProjectConfig();
|
|
5080
5103
|
const env = resolveCommandEnvironment(parsed, projectConfig);
|
|
5081
5104
|
const spaceId = resolveCommandSpace(parsed, projectConfig);
|
|
@@ -5083,36 +5106,99 @@ async function executeUpload(parsed, deps = defaultDeps$12) {
|
|
|
5083
5106
|
const assetName = parsed.options.name;
|
|
5084
5107
|
const assetType = parsed.options.type || "character";
|
|
5085
5108
|
const requestedMediaKind = parsed.options["media-kind"] || parsed.options.mediaKind;
|
|
5086
|
-
const
|
|
5087
|
-
|
|
5109
|
+
const prompt = parsed.options.prompt;
|
|
5110
|
+
const model = parsed.options.model;
|
|
5111
|
+
const provider = parsed.options.provider;
|
|
5112
|
+
const rawProviderMetadata = parsed.options["provider-metadata"] ?? parsed.options.providerMetadata ?? parsed.options.provider_metadata;
|
|
5113
|
+
const rawGenerationProvenance = parsed.options["generation-provenance"] ?? parsed.options.generationProvenance ?? parsed.options.generation_provenance;
|
|
5114
|
+
const rawSourceVariantIds = parsed.options["source-variants"] ?? parsed.options.sourceVariants ?? parsed.options.sourceVariantIds ?? parsed.options["source-variant"] ?? parsed.options.sourceVariantId ?? parsed.options.parentVariantId;
|
|
5115
|
+
const rawRelationType = parsed.options["relation-type"] ?? parsed.options.relationType;
|
|
5116
|
+
const rawActiveVariantBehavior = parsed.options["active-variant-behavior"] ?? parsed.options.activeVariantBehavior;
|
|
5117
|
+
const rawCollectionIds = parsed.options.collection ?? parsed.options.collections;
|
|
5118
|
+
const rawCollectionNames = parsed.options["collection-name"] ?? parsed.options.collectionName;
|
|
5119
|
+
const rawCollectionRole = parsed.options["collection-role"] ?? parsed.options.collectionRole;
|
|
5120
|
+
const rawCollectionSubject = parsed.options["collection-subject"] ?? parsed.options.collectionSubject;
|
|
5121
|
+
const rawCollectionPinnedVariant = parsed.options["collection-pinned-variant"] ?? parsed.options.collectionPinnedVariant;
|
|
5122
|
+
const rawManualRelation = parsed.options["manual-relation"] ?? parsed.options.manualRelation;
|
|
5123
|
+
const rawManualRelationSubject = parsed.options["manual-relation-subject"] ?? parsed.options.manualRelationSubject;
|
|
5124
|
+
const rawManualRelationLabel = parsed.options["manual-relation-label"] ?? parsed.options.manualRelationLabel;
|
|
5125
|
+
const rawManualRelationContext = parsed.options["manual-relation-context"] ?? parsed.options.manualRelationContext;
|
|
5126
|
+
const rawManualRelationMetadata = parsed.options["manual-relation-metadata"] ?? parsed.options.manualRelationMetadata;
|
|
5127
|
+
const jsonOutput = parsed.options.json === "true";
|
|
5128
|
+
if (parsed.options["dry-run"] === "true" || parsed.options.dryRun === "true") throw new UploadUsageError("--dry-run is not supported for direct file upload");
|
|
5088
5129
|
if (!spaceId) throw new UploadUsageError("--space is required, or run: makefx init --space <id>");
|
|
5089
5130
|
if (!assetId && !assetName) throw new UploadUsageError("Either --asset or --name is required");
|
|
5131
|
+
const providerMetadata = parseJsonObjectOption(rawProviderMetadata, "--provider-metadata");
|
|
5132
|
+
const generationProvenance = parseJsonObjectOption(rawGenerationProvenance, "--generation-provenance");
|
|
5133
|
+
const sourceVariantIds = parseCsvOption$1(rawSourceVariantIds, "--source-variant");
|
|
5134
|
+
const relationType = normalizeRelationType(rawRelationType);
|
|
5135
|
+
const activeVariantBehavior = normalizeActiveVariantBehavior(rawActiveVariantBehavior);
|
|
5136
|
+
if (sourceVariantIds.length === 0 && (parsed.options["relation-type"] || parsed.options.relationType)) throw new UploadUsageError("--relation-type requires --source-variant or --source-variants");
|
|
5137
|
+
const collectionPlacements = parseCollectionPlacements({
|
|
5138
|
+
collectionIds: rawCollectionIds,
|
|
5139
|
+
collectionNames: rawCollectionNames,
|
|
5140
|
+
role: rawCollectionRole,
|
|
5141
|
+
subjectType: rawCollectionSubject,
|
|
5142
|
+
pinnedVariant: rawCollectionPinnedVariant
|
|
5143
|
+
});
|
|
5144
|
+
const manualRelations = parseManualRelations({
|
|
5145
|
+
relations: rawManualRelation,
|
|
5146
|
+
subjectType: rawManualRelationSubject,
|
|
5147
|
+
label: rawManualRelationLabel,
|
|
5148
|
+
context: rawManualRelationContext,
|
|
5149
|
+
metadata: rawManualRelationMetadata
|
|
5150
|
+
});
|
|
5090
5151
|
const mediaType = resolveMediaType(path.extname(filePath).toLowerCase(), requestedMediaKind);
|
|
5091
5152
|
const config = await deps.loadConfig(env);
|
|
5092
5153
|
if (!config) throw new Error(`Not logged in to ${env} environment. Run: ${loginCommandForEnvironment(env)}`);
|
|
5093
5154
|
if (config.token.expiresAt < Date.now()) throw new Error(`Token expired for ${env} environment. Run: ${loginCommandForEnvironment(env)}`);
|
|
5094
5155
|
const baseUrl = deps.resolveBaseUrl(env);
|
|
5095
5156
|
const accessToken = config.token.accessToken;
|
|
5157
|
+
const ctx = {
|
|
5158
|
+
spaceId,
|
|
5159
|
+
baseUrl,
|
|
5160
|
+
accessToken
|
|
5161
|
+
};
|
|
5096
5162
|
if (env === "local") process$1.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
5097
5163
|
try {
|
|
5098
5164
|
const fileStat = await deps.stat(filePath);
|
|
5099
5165
|
if (!fileStat.isFile()) throw new Error(`"${filePath}" is not a file`);
|
|
5100
5166
|
if (fileStat.size > 10485760) throw new Error(`File too large (${(fileStat.size / 1024 / 1024).toFixed(2)}MB). Maximum size: 10MB`);
|
|
5167
|
+
await preflightUploadOrganization(ctx, deps, {
|
|
5168
|
+
assetId,
|
|
5169
|
+
sourceVariantIds,
|
|
5170
|
+
collectionPlacements,
|
|
5171
|
+
manualRelations
|
|
5172
|
+
});
|
|
5101
5173
|
const fileBuffer = await deps.readFile(filePath);
|
|
5102
5174
|
const fileName = path.basename(filePath);
|
|
5103
5175
|
const formData = new FormData();
|
|
5104
5176
|
const blob = new Blob([fileBuffer], { type: mediaType.mimeType });
|
|
5105
5177
|
formData.append("file", blob, fileName);
|
|
5106
5178
|
formData.append("mediaKind", mediaType.mediaKind);
|
|
5179
|
+
formData.append("activeVariantBehavior", activeVariantBehavior);
|
|
5107
5180
|
if (assetId) formData.append("assetId", assetId);
|
|
5108
5181
|
else {
|
|
5109
5182
|
formData.append("assetName", assetName);
|
|
5110
5183
|
formData.append("assetType", assetType);
|
|
5111
5184
|
}
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
if (
|
|
5115
|
-
|
|
5185
|
+
if (prompt) formData.append("prompt", prompt);
|
|
5186
|
+
if (model) formData.append("model", model);
|
|
5187
|
+
if (provider) formData.append("provider", provider);
|
|
5188
|
+
if (providerMetadata) formData.append("providerMetadata", JSON.stringify(providerMetadata));
|
|
5189
|
+
if (generationProvenance) formData.append("generationProvenance", JSON.stringify(generationProvenance));
|
|
5190
|
+
if (sourceVariantIds.length > 0) formData.append("lineage", JSON.stringify(sourceVariantIds.map((parentVariantId) => ({
|
|
5191
|
+
parentVariantId,
|
|
5192
|
+
relationType
|
|
5193
|
+
}))));
|
|
5194
|
+
if (!jsonOutput) {
|
|
5195
|
+
deps.print(`\nUploading "${fileName}" to space ${spaceId}...`);
|
|
5196
|
+
deps.print(` Media kind: ${mediaType.mediaKind}`);
|
|
5197
|
+
if (assetId) deps.print(` Target asset: ${assetId}`);
|
|
5198
|
+
else deps.print(` Creating asset: "${assetName}" (${assetType})`);
|
|
5199
|
+
if (sourceVariantIds.length === 1) deps.print(` Source variant: ${sourceVariantIds[0]} (${relationType})`);
|
|
5200
|
+
else if (sourceVariantIds.length > 1) deps.print(` Source variants: ${sourceVariantIds.join(", ")} (${relationType})`);
|
|
5201
|
+
}
|
|
5116
5202
|
const response = await deps.fetch(`${baseUrl}/api/spaces/${spaceId}/upload`, {
|
|
5117
5203
|
method: "POST",
|
|
5118
5204
|
headers: { "Authorization": `Bearer ${accessToken}` },
|
|
@@ -5121,6 +5207,29 @@ async function executeUpload(parsed, deps = defaultDeps$12) {
|
|
|
5121
5207
|
const data = await response.json();
|
|
5122
5208
|
if (!response.ok) throw new Error(`Upload failed: ${"error" in data ? data.error : response.statusText}`);
|
|
5123
5209
|
const upload = data;
|
|
5210
|
+
let organization = {
|
|
5211
|
+
collectionItemIds: [],
|
|
5212
|
+
relationIds: []
|
|
5213
|
+
};
|
|
5214
|
+
try {
|
|
5215
|
+
organization = await applyUploadOrganization(ctx, deps, upload, {
|
|
5216
|
+
collectionPlacements,
|
|
5217
|
+
manualRelations
|
|
5218
|
+
});
|
|
5219
|
+
} catch (error) {
|
|
5220
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5221
|
+
throw new Error(`Upload created asset ${upload.variant.asset_id} and variant ${upload.variant.id}, but organization failed: ${message}`);
|
|
5222
|
+
}
|
|
5223
|
+
const result = {
|
|
5224
|
+
asset: upload.asset,
|
|
5225
|
+
variant: upload.variant,
|
|
5226
|
+
lineage: upload.lineage,
|
|
5227
|
+
organization
|
|
5228
|
+
};
|
|
5229
|
+
if (jsonOutput) {
|
|
5230
|
+
deps.print(JSON.stringify(result, null, 2));
|
|
5231
|
+
return result;
|
|
5232
|
+
}
|
|
5124
5233
|
deps.print("\nUpload successful!\n");
|
|
5125
5234
|
if (upload.asset) {
|
|
5126
5235
|
deps.print("New Asset:");
|
|
@@ -5138,6 +5247,11 @@ async function executeUpload(parsed, deps = defaultDeps$12) {
|
|
|
5138
5247
|
if (upload.variant.image_key) deps.print(` Image: ${upload.variant.image_key}`);
|
|
5139
5248
|
if (upload.variant.thumb_key) deps.print(` Thumb: ${upload.variant.thumb_key}`);
|
|
5140
5249
|
if (upload.variant.media_mime_type) deps.print(` MIME: ${upload.variant.media_mime_type}`);
|
|
5250
|
+
if (organization.collectionItemIds.length > 0 || organization.relationIds.length > 0) {
|
|
5251
|
+
deps.print("\nOrganization:");
|
|
5252
|
+
if (organization.collectionItemIds.length > 0) deps.print(` Collection items: ${organization.collectionItemIds.join(", ")}`);
|
|
5253
|
+
if (organization.relationIds.length > 0) deps.print(` Relations: ${organization.relationIds.join(", ")}`);
|
|
5254
|
+
}
|
|
5141
5255
|
if (upload.variant.recipe) try {
|
|
5142
5256
|
const recipe = JSON.parse(upload.variant.recipe);
|
|
5143
5257
|
deps.print("\nRecipe:");
|
|
@@ -5147,429 +5261,45 @@ async function executeUpload(parsed, deps = defaultDeps$12) {
|
|
|
5147
5261
|
} catch {}
|
|
5148
5262
|
deps.print("\nTo inspect:");
|
|
5149
5263
|
deps.print(` makefx assets show ${upload.variant.asset_id} --space ${spaceId}`);
|
|
5150
|
-
return
|
|
5151
|
-
asset: upload.asset,
|
|
5152
|
-
variant: upload.variant
|
|
5153
|
-
};
|
|
5264
|
+
return result;
|
|
5154
5265
|
} catch (error) {
|
|
5155
5266
|
if (error.code === "ENOENT") throw new Error(`File not found: ${filePath}`);
|
|
5156
5267
|
throw error;
|
|
5157
5268
|
}
|
|
5158
5269
|
}
|
|
5159
|
-
function
|
|
5160
|
-
|
|
5161
|
-
if (!mediaType) throw new Error(`Invalid file type "${ext}". Allowed types: ${ALLOWED_EXTENSIONS$1.join(", ")}`);
|
|
5162
|
-
if (requestedMediaKind !== void 0 && requestedMediaKind !== "image" && requestedMediaKind !== "audio" && requestedMediaKind !== "video") throw new Error("Invalid --media-kind. Expected image, audio, or video");
|
|
5163
|
-
if (ext === ".webm" && requestedMediaKind === "audio") return {
|
|
5164
|
-
mediaKind: "audio",
|
|
5165
|
-
mimeType: "audio/webm"
|
|
5166
|
-
};
|
|
5167
|
-
if (requestedMediaKind && requestedMediaKind !== mediaType.mediaKind) throw new Error(`--media-kind ${requestedMediaKind} does not match ${ext} (${mediaType.mediaKind})`);
|
|
5168
|
-
return mediaType;
|
|
5169
|
-
}
|
|
5170
|
-
function printUsage$12() {
|
|
5171
|
-
console.log(`
|
|
5172
|
-
Usage:
|
|
5173
|
-
makefx upload <file> --asset <id> [--space <id>] Upload media to existing asset
|
|
5174
|
-
makefx upload <file> --name <name> [--space <id>] Create new asset
|
|
5175
|
-
|
|
5176
|
-
Options:
|
|
5177
|
-
--space <id> Target space ID; defaults from initialized project
|
|
5178
|
-
--asset <id> Target asset ID (upload as new variant)
|
|
5179
|
-
--name <name> New asset name (creates asset + variant)
|
|
5180
|
-
--type <type> Asset type for new assets (default: character)
|
|
5181
|
-
--media-kind <k> Optional explicit kind: image, audio, or video
|
|
5182
|
-
--env <env> Environment (production|stage|local)
|
|
5183
|
-
--local Shortcut for --env local
|
|
5184
|
-
|
|
5185
|
-
Examples:
|
|
5186
|
-
makefx upload hero.png --space abc123 --name "Hero Character"
|
|
5187
|
-
makefx upload theme.mp3 --space abc123 --name "Theme Music" --type audio
|
|
5188
|
-
makefx upload cutscene.mp4 --space abc123 --name "Opening Cutscene" --type video
|
|
5189
|
-
makefx upload variant.jpg --space abc123 --asset def456
|
|
5190
|
-
`);
|
|
5191
|
-
}
|
|
5192
|
-
//#endregion
|
|
5193
|
-
//#region src/cli/commands/import.ts
|
|
5194
|
-
var defaultDeps$11 = {
|
|
5195
|
-
loadConfig: loadStoredConfig,
|
|
5196
|
-
loadProjectConfig,
|
|
5197
|
-
resolveBaseUrl,
|
|
5198
|
-
fetch,
|
|
5199
|
-
readFile,
|
|
5200
|
-
stat,
|
|
5201
|
-
print: console.log
|
|
5202
|
-
};
|
|
5203
|
-
async function handleImport(parsed) {
|
|
5204
|
-
try {
|
|
5205
|
-
await executeImport(parsed);
|
|
5206
|
-
} catch (error) {
|
|
5207
|
-
console.error(error instanceof Error ? `Error: ${error.message}` : "Error: Import failed");
|
|
5208
|
-
printUsage$11();
|
|
5209
|
-
process$1.exitCode = 1;
|
|
5210
|
-
}
|
|
5211
|
-
}
|
|
5212
|
-
async function executeImport(parsed, deps = defaultDeps$11) {
|
|
5213
|
-
const manifestPath = parsed.positionals[0] || parsed.options.manifest;
|
|
5214
|
-
if (!manifestPath || manifestPath === "true") throw new Error("Manifest path is required: makefx import <manifest.json>");
|
|
5215
|
-
const ctx = await buildContext$8(parsed, deps);
|
|
5216
|
-
const manifest = await readManifest(manifestPath, deps);
|
|
5217
|
-
await validateLocalRecords(manifest.records, deps);
|
|
5218
|
-
const plan = validateManifestPlan(manifest, await fetchSpaceState(ctx, deps));
|
|
5219
|
-
const uploadOrder = buildUploadOrder(manifest.records);
|
|
5220
|
-
if (parsed.options["dry-run"] === "true" || parsed.options.dryRun === "true") {
|
|
5221
|
-
const result = {
|
|
5222
|
-
dryRun: true,
|
|
5223
|
-
records: uploadOrder.map((record) => ({
|
|
5224
|
-
key: record.localKey,
|
|
5225
|
-
file: record.displayPath,
|
|
5226
|
-
target: record.assetId ?? `new:${record.assetName}`,
|
|
5227
|
-
lineageInputs: record.lineage.length
|
|
5228
|
-
})),
|
|
5229
|
-
collections: plan.collections.map((collection) => ({
|
|
5230
|
-
name: collection.name,
|
|
5231
|
-
create: collection.create
|
|
5232
|
-
})),
|
|
5233
|
-
collectionItems: plan.collectionItems.length,
|
|
5234
|
-
relations: plan.relations.length,
|
|
5235
|
-
compositions: plan.compositions.map((composition) => ({
|
|
5236
|
-
name: composition.name,
|
|
5237
|
-
create: composition.create
|
|
5238
|
-
})),
|
|
5239
|
-
compositionItems: plan.compositionItems.length,
|
|
5240
|
-
stylePresets: plan.stylePresets.map((preset) => ({
|
|
5241
|
-
name: preset.name,
|
|
5242
|
-
action: preset.action
|
|
5243
|
-
}))
|
|
5244
|
-
};
|
|
5245
|
-
printResult$1(result, parsed, deps);
|
|
5246
|
-
return result;
|
|
5247
|
-
}
|
|
5248
|
-
const uploadedByKey = /* @__PURE__ */ new Map();
|
|
5249
|
-
const imported = [];
|
|
5250
|
-
const jsonOutput = parsed.options.json === "true";
|
|
5251
|
-
for (const record of uploadOrder) {
|
|
5252
|
-
const lineage = record.lineage.map((input) => ({
|
|
5253
|
-
parentVariantId: input.sourceVariantId ?? uploadedByKey.get(input.sourceFile)?.variantId,
|
|
5254
|
-
relationType: input.relationType
|
|
5255
|
-
}));
|
|
5256
|
-
if (lineage.find((input) => !input.parentVariantId)) throw new Error(`Could not resolve same-batch lineage for ${record.localKey}`);
|
|
5257
|
-
const response = await uploadRecord(ctx, deps, record, lineage, { quiet: jsonOutput });
|
|
5258
|
-
uploadedByKey.set(record.localKey, {
|
|
5259
|
-
assetId: response.variant.asset_id,
|
|
5260
|
-
variantId: response.variant.id
|
|
5261
|
-
});
|
|
5262
|
-
imported.push({
|
|
5263
|
-
key: record.localKey,
|
|
5264
|
-
file: record.displayPath,
|
|
5265
|
-
assetId: response.variant.asset_id,
|
|
5266
|
-
variantId: response.variant.id,
|
|
5267
|
-
lineageIds: (response.lineage ?? []).map((lineageRecord) => lineageRecord.id)
|
|
5268
|
-
});
|
|
5269
|
-
}
|
|
5270
|
-
const result = {
|
|
5271
|
-
dryRun: false,
|
|
5272
|
-
records: imported,
|
|
5273
|
-
...await applyOrganizationPlan(ctx, deps, plan, uploadedByKey)
|
|
5274
|
-
};
|
|
5275
|
-
printResult$1(result, parsed, deps);
|
|
5276
|
-
return result;
|
|
5277
|
-
}
|
|
5278
|
-
async function buildContext$8(parsed, deps) {
|
|
5279
|
-
const projectConfig = await deps.loadProjectConfig();
|
|
5280
|
-
const env = resolveCommandEnvironment(parsed, projectConfig);
|
|
5281
|
-
const spaceId = resolveCommandSpace(parsed, projectConfig);
|
|
5282
|
-
if (!spaceId) throw new Error("--space is required, or run: makefx init --space <id>");
|
|
5283
|
-
const config = await deps.loadConfig(env);
|
|
5284
|
-
if (!config) throw new Error(`Not logged in to ${env} environment. Run: ${loginCommandForEnvironment(env)}`);
|
|
5285
|
-
if (config.token.expiresAt < Date.now()) throw new Error(`Token expired for ${env} environment. Run: ${loginCommandForEnvironment(env)}`);
|
|
5286
|
-
if (env === "local") process$1.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
5287
|
-
return {
|
|
5288
|
-
env,
|
|
5289
|
-
spaceId,
|
|
5290
|
-
baseUrl: deps.resolveBaseUrl(env),
|
|
5291
|
-
accessToken: config.token.accessToken
|
|
5292
|
-
};
|
|
5293
|
-
}
|
|
5294
|
-
async function readManifest(manifestPath, deps) {
|
|
5295
|
-
const manifestText = await deps.readFile(manifestPath, "utf8");
|
|
5296
|
-
const manifestDir = path.dirname(path.resolve(manifestPath));
|
|
5270
|
+
function parseJsonObjectOption(value, optionName) {
|
|
5271
|
+
if (value === void 0) return void 0;
|
|
5297
5272
|
let parsed;
|
|
5298
5273
|
try {
|
|
5299
|
-
parsed = JSON.parse(
|
|
5300
|
-
} catch
|
|
5301
|
-
throw new
|
|
5302
|
-
}
|
|
5303
|
-
const root = Array.isArray(parsed) ? {} : parsed;
|
|
5304
|
-
const rawRecords = Array.isArray(parsed) ? parsed : parsed && typeof parsed === "object" ? root.records ?? root.files : null;
|
|
5305
|
-
if (!Array.isArray(rawRecords)) throw new Error("Manifest must be an array or contain a records/files array");
|
|
5306
|
-
const records = rawRecords.map((raw, index) => normalizeRecord(raw, index, manifestDir));
|
|
5307
|
-
const keys = /* @__PURE__ */ new Set();
|
|
5308
|
-
for (const record of records) {
|
|
5309
|
-
if (keys.has(record.localKey)) throw new Error(`Duplicate local key in manifest: ${record.localKey}`);
|
|
5310
|
-
keys.add(record.localKey);
|
|
5274
|
+
parsed = JSON.parse(value);
|
|
5275
|
+
} catch {
|
|
5276
|
+
throw new UploadUsageError(`${optionName} must be valid JSON`);
|
|
5311
5277
|
}
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
collections: normalizeCollections(readArray(root.collections, "collections"), false),
|
|
5315
|
-
styleCollections: normalizeStyleCollections(readArray(root.styleCollections, "styleCollections")),
|
|
5316
|
-
collectionItems: [...records.flatMap((record) => record.collectionItems), ...normalizeCollectionItems(readArray(root.collectionItems, "collectionItems"), "collectionItems")],
|
|
5317
|
-
relations: [...records.flatMap((record) => record.relations), ...normalizeRelations(readArray(root.relations, "relations"), "relations")],
|
|
5318
|
-
compositions: normalizeCompositions(readArray(root.compositions, "compositions")),
|
|
5319
|
-
compositionItems: [...records.flatMap((record) => record.compositionItems), ...normalizeCompositionItems(readArray(root.compositionItems, "compositionItems"), "compositionItems")],
|
|
5320
|
-
stylePresets: normalizeStylePresets(readArray(root.stylePresets, "stylePresets"))
|
|
5321
|
-
};
|
|
5322
|
-
}
|
|
5323
|
-
function normalizeRecord(raw, index, manifestDir) {
|
|
5324
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) throw new Error(`Record ${index + 1} must be an object`);
|
|
5325
|
-
const record = raw;
|
|
5326
|
-
const displayPath = record.file ?? record.path;
|
|
5327
|
-
if (!displayPath) throw new Error(`Record ${index + 1} is missing file`);
|
|
5328
|
-
const filePath = path.resolve(manifestDir, displayPath);
|
|
5329
|
-
const mediaType = resolveMediaType(path.extname(filePath).toLowerCase(), record.mediaKind);
|
|
5330
|
-
const assetId = record.assetId ?? record.targetAssetId;
|
|
5331
|
-
const assetName = record.assetName ?? record.name;
|
|
5332
|
-
if (assetId && assetName) throw new Error(`Record ${index + 1} must set either assetId or name, not both`);
|
|
5333
|
-
if (!assetId && !assetName) throw new Error(`Record ${index + 1} must set assetId for an existing asset or name for a new asset`);
|
|
5334
|
-
const lineage = normalizeLineage(record.lineage ?? [], index);
|
|
5335
|
-
const activeVariantBehavior = normalizeActiveBehavior(record.activeVariantBehavior, index);
|
|
5336
|
-
const providerMetadata = record.providerMetadata ?? record.provider_metadata;
|
|
5337
|
-
const generationProvenance = record.generationProvenance ?? record.generation_provenance ?? {};
|
|
5338
|
-
validateObjectField(providerMetadata, `Record ${index + 1} providerMetadata`);
|
|
5339
|
-
validateObjectField(generationProvenance, `Record ${index + 1} generationProvenance`);
|
|
5340
|
-
const localKey = record.localKey ?? record.key ?? displayPath;
|
|
5341
|
-
return {
|
|
5342
|
-
index,
|
|
5343
|
-
localKey,
|
|
5344
|
-
filePath,
|
|
5345
|
-
displayPath,
|
|
5346
|
-
fileName: path.basename(filePath),
|
|
5347
|
-
assetName,
|
|
5348
|
-
assetType: record.assetType ?? record.type ?? "character",
|
|
5349
|
-
assetId,
|
|
5350
|
-
mediaKind: mediaType.mediaKind,
|
|
5351
|
-
mimeType: mediaType.mimeType,
|
|
5352
|
-
activeVariantBehavior,
|
|
5353
|
-
prompt: record.prompt,
|
|
5354
|
-
model: record.model,
|
|
5355
|
-
provider: record.provider,
|
|
5356
|
-
providerMetadata,
|
|
5357
|
-
generationProvenance,
|
|
5358
|
-
lineage,
|
|
5359
|
-
collectionItems: normalizeCollectionItems([...readArray(record.collections, `Record ${index + 1} collections`), ...readArray(record.collectionItems, `Record ${index + 1} collectionItems`)], `Record ${index + 1} collections`, localKey),
|
|
5360
|
-
relations: normalizeRelations(readArray(record.relations, `Record ${index + 1} relations`), `Record ${index + 1} relations`, localKey),
|
|
5361
|
-
compositionItems: normalizeCompositionItems(readArray(record.compositionItems, `Record ${index + 1} compositionItems`), `Record ${index + 1} compositionItems`, localKey),
|
|
5362
|
-
styleCollections: normalizeStyleCollections(readArray(record.styleCollections, `Record ${index + 1} styleCollections`), localKey)
|
|
5363
|
-
};
|
|
5364
|
-
}
|
|
5365
|
-
function readArray(value, label) {
|
|
5366
|
-
if (value === void 0) return [];
|
|
5367
|
-
if (!Array.isArray(value)) throw new Error(`${label} must be an array`);
|
|
5368
|
-
return value;
|
|
5369
|
-
}
|
|
5370
|
-
function normalizeLineage(inputs, recordIndex) {
|
|
5371
|
-
if (!Array.isArray(inputs)) throw new Error(`Record ${recordIndex + 1} lineage must be an array`);
|
|
5372
|
-
return inputs.map((input, index) => {
|
|
5373
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) throw new Error(`Record ${recordIndex + 1} lineage[${index}] must be an object`);
|
|
5374
|
-
const sourceVariantId = input.sourceVariantId ?? input.parentVariantId;
|
|
5375
|
-
if (sourceVariantId && input.sourceFile || !sourceVariantId && !input.sourceFile) throw new Error(`Record ${recordIndex + 1} lineage[${index}] must set exactly one of sourceVariantId or sourceFile`);
|
|
5376
|
-
if (input.relationType !== "derived" && input.relationType !== "refined" && input.relationType !== "forked") throw new Error(`Record ${recordIndex + 1} lineage[${index}] relationType must be derived, refined, or forked`);
|
|
5377
|
-
return {
|
|
5378
|
-
relationType: input.relationType,
|
|
5379
|
-
...sourceVariantId ? { sourceVariantId } : { sourceFile: input.sourceFile }
|
|
5380
|
-
};
|
|
5381
|
-
});
|
|
5382
|
-
}
|
|
5383
|
-
function normalizeCollections(inputs, styleOnly) {
|
|
5384
|
-
return inputs.map((input, index) => {
|
|
5385
|
-
const collection = requireObject(input, `collections[${index}]`);
|
|
5386
|
-
const name = collection.name ?? collection.collectionName ?? collection.collection;
|
|
5387
|
-
if (!name || typeof name !== "string") throw new Error(`collections[${index}] name is required`);
|
|
5388
|
-
if (collection.description !== void 0 && collection.description !== null && typeof collection.description !== "string") throw new Error(`collections[${index}] description must be a string or null`);
|
|
5389
|
-
validateSortIndex(collection.sortIndex, `collections[${index}] sortIndex`);
|
|
5390
|
-
return {
|
|
5391
|
-
key: collection.id ?? name,
|
|
5392
|
-
name,
|
|
5393
|
-
description: collection.description,
|
|
5394
|
-
sortIndex: collection.sortIndex,
|
|
5395
|
-
create: styleOnly || collection.create === true || collection.createIfMissing === true
|
|
5396
|
-
};
|
|
5397
|
-
});
|
|
5398
|
-
}
|
|
5399
|
-
function normalizeStyleCollections(inputs, recordKey) {
|
|
5400
|
-
return inputs.map((input, index) => {
|
|
5401
|
-
if (typeof input === "string") return {
|
|
5402
|
-
key: input,
|
|
5403
|
-
name: input,
|
|
5404
|
-
create: false,
|
|
5405
|
-
refs: recordKey ? [recordKey] : []
|
|
5406
|
-
};
|
|
5407
|
-
const collection = requireObject(input, labelFor("styleCollections", index, recordKey));
|
|
5408
|
-
const name = collection.name ?? collection.collectionName ?? collection.collection;
|
|
5409
|
-
if (!name || typeof name !== "string") throw new Error(`${labelFor("styleCollections", index, recordKey)} name is required`);
|
|
5410
|
-
validateSortIndex(collection.sortIndex, `${labelFor("styleCollections", index, recordKey)} sortIndex`);
|
|
5411
|
-
const refs = [
|
|
5412
|
-
...collection.refs ?? [],
|
|
5413
|
-
...collection.records ?? [],
|
|
5414
|
-
...recordKey ? [recordKey] : []
|
|
5415
|
-
];
|
|
5416
|
-
if (!refs.every((ref) => typeof ref === "string" && ref.trim())) throw new Error(`${labelFor("styleCollections", index, recordKey)} refs must be strings`);
|
|
5417
|
-
return {
|
|
5418
|
-
key: collection.id ?? name,
|
|
5419
|
-
name,
|
|
5420
|
-
description: collection.description,
|
|
5421
|
-
sortIndex: collection.sortIndex,
|
|
5422
|
-
create: collection.create === true || collection.createIfMissing === true,
|
|
5423
|
-
refs
|
|
5424
|
-
};
|
|
5425
|
-
});
|
|
5426
|
-
}
|
|
5427
|
-
function normalizeCollectionItems(inputs, label, defaultRecordKey) {
|
|
5428
|
-
return inputs.map((input, index) => {
|
|
5429
|
-
const item = requireObject(input, `${label}[${index}]`);
|
|
5430
|
-
const collectionName = item.collectionName ?? item.collection ?? item.collectionId;
|
|
5431
|
-
if (!collectionName || typeof collectionName !== "string") throw new Error(`${label}[${index}] collection is required`);
|
|
5432
|
-
if (item.role !== void 0 && typeof item.role !== "string") throw new Error(`${label}[${index}] role must be a string`);
|
|
5433
|
-
const subjectType = normalizeSubjectType(item.subjectType ?? (item.variantId ? "variant" : "asset"), `${label}[${index}] subjectType`);
|
|
5434
|
-
const recordKey = item.recordKey ?? item.sourceFile ?? defaultRecordKey;
|
|
5435
|
-
validateSortIndex(item.sortIndex, `${label}[${index}] sortIndex`);
|
|
5436
|
-
if (item.pinnedVariantId !== void 0 && item.pinnedVariantId !== null && typeof item.pinnedVariantId !== "string") throw new Error(`${label}[${index}] pinnedVariantId must be a string or null`);
|
|
5437
|
-
return {
|
|
5438
|
-
id: item.id,
|
|
5439
|
-
collectionName,
|
|
5440
|
-
role: item.role ?? "member",
|
|
5441
|
-
subjectType,
|
|
5442
|
-
assetId: item.assetId,
|
|
5443
|
-
variantId: item.variantId,
|
|
5444
|
-
recordKey,
|
|
5445
|
-
pinnedVariantId: item.pinnedVariantId,
|
|
5446
|
-
pinnedVariantBehavior: normalizePinnedVariantBehavior(item.pinnedVariantBehavior, `${label}[${index}] pinnedVariantBehavior`),
|
|
5447
|
-
sortIndex: item.sortIndex
|
|
5448
|
-
};
|
|
5449
|
-
});
|
|
5450
|
-
}
|
|
5451
|
-
function normalizeRelations(inputs, label, defaultSubjectRecordKey) {
|
|
5452
|
-
return inputs.map((input, index) => {
|
|
5453
|
-
const relation = requireObject(input, `${label}[${index}]`);
|
|
5454
|
-
const subject = relation.subject ? normalizeSubject(relation.subject, `${label}[${index}] subject`) : normalizeSubject({
|
|
5455
|
-
subjectType: relation.subjectType,
|
|
5456
|
-
assetId: relation.subjectAssetId,
|
|
5457
|
-
variantId: relation.subjectVariantId,
|
|
5458
|
-
recordKey: defaultSubjectRecordKey
|
|
5459
|
-
}, `${label}[${index}] subject`);
|
|
5460
|
-
const object = normalizeSubject(relation.object ?? relation.target ?? {
|
|
5461
|
-
subjectType: relation.objectType,
|
|
5462
|
-
assetId: relation.objectAssetId,
|
|
5463
|
-
variantId: relation.objectVariantId
|
|
5464
|
-
}, `${label}[${index}] object`);
|
|
5465
|
-
const relationType = normalizeRelationType(relation.relationType, `${label}[${index}] relationType`);
|
|
5466
|
-
validateObjectField(relation.metadata, `${label}[${index}] metadata`);
|
|
5467
|
-
validateSortIndex(relation.sortIndex, `${label}[${index}] sortIndex`);
|
|
5468
|
-
if (relation.label !== void 0 && relation.label !== null && typeof relation.label !== "string") throw new Error(`${label}[${index}] label must be a string or null`);
|
|
5469
|
-
if (relation.context !== void 0 && relation.context !== null && typeof relation.context !== "string" && (typeof relation.context !== "object" || Array.isArray(relation.context))) throw new Error(`${label}[${index}] context must be a string, object, or null`);
|
|
5470
|
-
return {
|
|
5471
|
-
id: relation.id,
|
|
5472
|
-
subject,
|
|
5473
|
-
object,
|
|
5474
|
-
relationType,
|
|
5475
|
-
label: relation.label,
|
|
5476
|
-
context: relation.context,
|
|
5477
|
-
metadata: relation.metadata,
|
|
5478
|
-
sortIndex: relation.sortIndex
|
|
5479
|
-
};
|
|
5480
|
-
});
|
|
5481
|
-
}
|
|
5482
|
-
function normalizeCompositions(inputs) {
|
|
5483
|
-
return inputs.map((input, index) => {
|
|
5484
|
-
const composition = requireObject(input, `compositions[${index}]`);
|
|
5485
|
-
const name = composition.name ?? composition.compositionName ?? composition.composition;
|
|
5486
|
-
if (!name || typeof name !== "string") throw new Error(`compositions[${index}] name is required`);
|
|
5487
|
-
if (composition.description !== void 0 && composition.description !== null && typeof composition.description !== "string") throw new Error(`compositions[${index}] description must be a string or null`);
|
|
5488
|
-
validateObjectField(composition.metadata, `compositions[${index}] metadata`);
|
|
5489
|
-
validateSortIndex(composition.sortIndex, `compositions[${index}] sortIndex`);
|
|
5490
|
-
const output = composition.output ? normalizeSubject(composition.output, `compositions[${index}] output`) : composition.outputRecordKey || composition.outputAssetId || composition.outputVariantId ? normalizeSubject({
|
|
5491
|
-
subjectType: composition.outputVariantId || composition.outputRecordKey ? "variant" : "asset",
|
|
5492
|
-
assetId: composition.outputAssetId ?? void 0,
|
|
5493
|
-
variantId: composition.outputVariantId ?? void 0,
|
|
5494
|
-
recordKey: composition.outputRecordKey
|
|
5495
|
-
}, `compositions[${index}] output`) : void 0;
|
|
5496
|
-
return {
|
|
5497
|
-
key: composition.id ?? name,
|
|
5498
|
-
name,
|
|
5499
|
-
description: composition.description,
|
|
5500
|
-
status: normalizeCompositionStatus(composition.status, `compositions[${index}] status`),
|
|
5501
|
-
output,
|
|
5502
|
-
metadata: composition.metadata,
|
|
5503
|
-
sortIndex: composition.sortIndex,
|
|
5504
|
-
create: composition.create === true || composition.createIfMissing === true
|
|
5505
|
-
};
|
|
5506
|
-
});
|
|
5278
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new UploadUsageError(`${optionName} must be a JSON object`);
|
|
5279
|
+
return parsed;
|
|
5507
5280
|
}
|
|
5508
|
-
function
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
if (!compositionName || typeof compositionName !== "string") throw new Error(`${label}[${index}] composition is required`);
|
|
5513
|
-
const role = normalizeCompositionItemRole(item.role, `${label}[${index}] role`);
|
|
5514
|
-
validateObjectField(item.metadata, `${label}[${index}] metadata`);
|
|
5515
|
-
validateSortIndex(item.sortIndex, `${label}[${index}] sortIndex`);
|
|
5516
|
-
if (item.label !== void 0 && item.label !== null && typeof item.label !== "string") throw new Error(`${label}[${index}] label must be a string or null`);
|
|
5517
|
-
return {
|
|
5518
|
-
id: item.id,
|
|
5519
|
-
compositionName,
|
|
5520
|
-
role,
|
|
5521
|
-
label: item.label,
|
|
5522
|
-
assetId: item.assetId,
|
|
5523
|
-
variantId: item.variantId,
|
|
5524
|
-
recordKey: item.recordKey ?? item.sourceFile ?? defaultRecordKey,
|
|
5525
|
-
metadata: item.metadata,
|
|
5526
|
-
sortIndex: item.sortIndex
|
|
5527
|
-
};
|
|
5528
|
-
});
|
|
5281
|
+
function parseJsonObjectOrStringOption(value, optionName) {
|
|
5282
|
+
if (value === void 0) return void 0;
|
|
5283
|
+
if (!value.trim().startsWith("{")) return value;
|
|
5284
|
+
return parseJsonObjectOption(value, optionName);
|
|
5529
5285
|
}
|
|
5530
|
-
function
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
if (!name || typeof name !== "string") throw new Error(`stylePresets[${index}] name is required`);
|
|
5535
|
-
const stylePrompt = preset.stylePrompt ?? preset.prompt;
|
|
5536
|
-
if (stylePrompt !== void 0 && typeof stylePrompt !== "string") throw new Error(`stylePresets[${index}] stylePrompt must be a string`);
|
|
5537
|
-
if (preset.description !== void 0 && preset.description !== null && typeof preset.description !== "string") throw new Error(`stylePresets[${index}] description must be a string or null`);
|
|
5538
|
-
if ([
|
|
5539
|
-
preset.create,
|
|
5540
|
-
preset.update,
|
|
5541
|
-
preset.upsert
|
|
5542
|
-
].filter((value) => value === true).length !== 1) throw new Error(`stylePresets[${index}] must set exactly one of create, update, or upsert`);
|
|
5543
|
-
return {
|
|
5544
|
-
id: preset.id,
|
|
5545
|
-
name,
|
|
5546
|
-
description: preset.description,
|
|
5547
|
-
stylePrompt,
|
|
5548
|
-
collectionName: preset.collectionName ?? preset.collection ?? void 0,
|
|
5549
|
-
collectionId: preset.collectionId,
|
|
5550
|
-
enabled: preset.enabled,
|
|
5551
|
-
isDefault: preset.isDefault ?? preset.default,
|
|
5552
|
-
action: preset.create ? "create" : preset.update ? "update" : "upsert"
|
|
5553
|
-
};
|
|
5554
|
-
});
|
|
5286
|
+
function normalizeRelationType(value) {
|
|
5287
|
+
if (!value) return "derived";
|
|
5288
|
+
if (value === "derived" || value === "refined" || value === "forked") return value;
|
|
5289
|
+
throw new UploadUsageError("--relation-type must be derived, refined, or forked");
|
|
5555
5290
|
}
|
|
5556
|
-
function
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
if (
|
|
5560
|
-
|
|
5561
|
-
return {
|
|
5562
|
-
subjectType,
|
|
5563
|
-
assetId: input.assetId,
|
|
5564
|
-
variantId: input.variantId,
|
|
5565
|
-
recordKey
|
|
5566
|
-
};
|
|
5291
|
+
function normalizeActiveVariantBehavior(value) {
|
|
5292
|
+
if (!value || value === "if-missing" || value === "if_missing") return "if-missing";
|
|
5293
|
+
if (value === "set-active" || value === "set_active") return "set-active";
|
|
5294
|
+
if (value === "keep") return "keep";
|
|
5295
|
+
throw new UploadUsageError("--active-variant-behavior must be if-missing, set-active, or keep");
|
|
5567
5296
|
}
|
|
5568
|
-
function
|
|
5297
|
+
function normalizeSpaceSubjectType(value, optionName, defaultValue) {
|
|
5298
|
+
if (!value) return defaultValue;
|
|
5569
5299
|
if (value === "asset" || value === "variant") return value;
|
|
5570
|
-
throw new
|
|
5300
|
+
throw new UploadUsageError(`${optionName} must be asset or variant`);
|
|
5571
5301
|
}
|
|
5572
|
-
function
|
|
5302
|
+
function normalizeManualRelationType(value, optionName) {
|
|
5573
5303
|
if ([
|
|
5574
5304
|
"appears_in",
|
|
5575
5305
|
"background_for",
|
|
@@ -5582,425 +5312,156 @@ function normalizeRelationType(value, label) {
|
|
|
5582
5312
|
"reference_for",
|
|
5583
5313
|
"custom"
|
|
5584
5314
|
].includes(value)) return value;
|
|
5585
|
-
throw new
|
|
5586
|
-
}
|
|
5587
|
-
function normalizeCompositionItemRole(value, label) {
|
|
5588
|
-
if ([
|
|
5589
|
-
"output",
|
|
5590
|
-
"background",
|
|
5591
|
-
"character",
|
|
5592
|
-
"prop",
|
|
5593
|
-
"style_ref",
|
|
5594
|
-
"overlay",
|
|
5595
|
-
"map",
|
|
5596
|
-
"thumbnail",
|
|
5597
|
-
"custom"
|
|
5598
|
-
].includes(value)) return value;
|
|
5599
|
-
throw new Error(`${label} is invalid`);
|
|
5315
|
+
throw new UploadUsageError(`${optionName} relation type is invalid`);
|
|
5600
5316
|
}
|
|
5601
|
-
function
|
|
5602
|
-
if (value
|
|
5603
|
-
if (value === "
|
|
5604
|
-
|
|
5605
|
-
}
|
|
5606
|
-
function normalizePinnedVariantBehavior(value, label) {
|
|
5607
|
-
if (!value || value === "imported") return "imported";
|
|
5608
|
-
if (value === "none" || value === "unpin") return "none";
|
|
5609
|
-
throw new Error(`${label} must be imported or none`);
|
|
5317
|
+
function parseCsvOption$1(value, optionName) {
|
|
5318
|
+
if (!value) return [];
|
|
5319
|
+
if (value === "true") throw new UploadUsageError(`${optionName} requires a value`);
|
|
5320
|
+
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
5610
5321
|
}
|
|
5611
|
-
function
|
|
5612
|
-
|
|
5322
|
+
function parseCollectionPlacements(input) {
|
|
5323
|
+
const collectionIds = parseCsvOption$1(input.collectionIds, "--collection");
|
|
5324
|
+
const collectionNames = parseCsvOption$1(input.collectionNames, "--collection-name");
|
|
5325
|
+
if (collectionIds.length === 0 && collectionNames.length === 0) return [];
|
|
5326
|
+
const subjectType = normalizeSpaceSubjectType(input.subjectType, "--collection-subject", "asset");
|
|
5327
|
+
if (subjectType === "variant" && input.pinnedVariant && input.pinnedVariant !== "true") throw new UploadUsageError("--collection-pinned-variant can only be used when --collection-subject is asset");
|
|
5328
|
+
const pinnedVariantId = normalizeCollectionPinnedVariant(input.pinnedVariant);
|
|
5329
|
+
const placement = {
|
|
5330
|
+
role: input.role && input.role !== "true" ? input.role : "member",
|
|
5331
|
+
subjectType,
|
|
5332
|
+
pinnedVariantId
|
|
5333
|
+
};
|
|
5334
|
+
return [...collectionIds.map((collectionId) => ({
|
|
5335
|
+
...placement,
|
|
5336
|
+
collectionId
|
|
5337
|
+
})), ...collectionNames.map((collectionName) => ({
|
|
5338
|
+
...placement,
|
|
5339
|
+
collectionName
|
|
5340
|
+
}))];
|
|
5341
|
+
}
|
|
5342
|
+
function normalizeCollectionPinnedVariant(value) {
|
|
5343
|
+
if (!value || value === "true" || value === "uploaded") return void 0;
|
|
5344
|
+
if (value === "none" || value === "unpin") return null;
|
|
5613
5345
|
return value;
|
|
5614
5346
|
}
|
|
5615
|
-
function
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
}
|
|
5347
|
+
function parseManualRelations(input) {
|
|
5348
|
+
const relationSpecs = parseCsvOption$1(input.relations, "--manual-relation");
|
|
5349
|
+
if (relationSpecs.length === 0) return [];
|
|
5350
|
+
const subjectType = normalizeSpaceSubjectType(input.subjectType, "--manual-relation-subject", "variant");
|
|
5351
|
+
const context = parseJsonObjectOrStringOption(input.context, "--manual-relation-context");
|
|
5352
|
+
const metadata = parseJsonObjectOption(input.metadata, "--manual-relation-metadata");
|
|
5353
|
+
return relationSpecs.map((spec) => {
|
|
5354
|
+
const parts = spec.split(":");
|
|
5355
|
+
if (parts.length !== 3) throw new UploadUsageError("--manual-relation entries must use <relation-type>:asset:<asset-id> or <relation-type>:variant:<variant-id>");
|
|
5356
|
+
const [relationTypeValue, objectTypeValue, objectId] = parts;
|
|
5357
|
+
const objectType = normalizeSpaceSubjectType(objectTypeValue, "--manual-relation object type", "asset");
|
|
5358
|
+
if (!objectId) throw new UploadUsageError("--manual-relation object id is required");
|
|
5359
|
+
return {
|
|
5360
|
+
relationType: normalizeManualRelationType(relationTypeValue, "--manual-relation"),
|
|
5361
|
+
object: objectType === "asset" ? {
|
|
5362
|
+
subjectType: "asset",
|
|
5363
|
+
assetId: objectId
|
|
5364
|
+
} : {
|
|
5365
|
+
subjectType: "variant",
|
|
5366
|
+
variantId: objectId
|
|
5367
|
+
},
|
|
5368
|
+
subjectType,
|
|
5369
|
+
label: input.label && input.label !== "true" ? input.label : void 0,
|
|
5370
|
+
context,
|
|
5371
|
+
metadata
|
|
5372
|
+
};
|
|
5373
|
+
});
|
|
5643
5374
|
}
|
|
5644
|
-
async function
|
|
5645
|
-
const
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5375
|
+
async function preflightUploadOrganization(ctx, deps, options) {
|
|
5376
|
+
const needsCollections = options.collectionPlacements.length > 0;
|
|
5377
|
+
const needsAssetState = options.sourceVariantIds.length > 0 || options.manualRelations.length > 0 || options.collectionPlacements.some((placement) => placement.pinnedVariantId);
|
|
5378
|
+
const [collections, state] = await Promise.all([needsCollections ? fetchJson$1(ctx, deps, `/api/spaces/${ctx.spaceId}/collections`) : void 0, needsAssetState ? fetchAssetState(ctx, deps) : void 0]);
|
|
5379
|
+
if (collections) {
|
|
5380
|
+
const collectionList = collections.collections ?? [];
|
|
5381
|
+
const collectionIds = new Set(collectionList.map((collection) => collection.id));
|
|
5382
|
+
for (const placement of options.collectionPlacements) {
|
|
5383
|
+
if (placement.collectionId && !collectionIds.has(placement.collectionId)) throw new Error(`Collection not found: ${placement.collectionId}`);
|
|
5384
|
+
if (!placement.collectionName) continue;
|
|
5385
|
+
const matches = collectionList.filter((collection) => collection.name === placement.collectionName);
|
|
5386
|
+
if (matches.length === 0) throw new Error(`Collection not found by exact name: ${placement.collectionName}`);
|
|
5387
|
+
if (matches.length > 1) throw new Error(`Collection name is ambiguous: ${placement.collectionName}; use --collection <id>`);
|
|
5388
|
+
placement.collectionId = matches[0].id;
|
|
5389
|
+
}
|
|
5390
|
+
}
|
|
5391
|
+
if (!state) return;
|
|
5392
|
+
for (const sourceVariantId of options.sourceVariantIds) if (!state.variantsById.has(sourceVariantId)) throw new Error(`Source variant not found in space: ${sourceVariantId}`);
|
|
5393
|
+
for (const placement of options.collectionPlacements) {
|
|
5394
|
+
if (!placement.pinnedVariantId) continue;
|
|
5395
|
+
const pinned = state.variantsById.get(placement.pinnedVariantId);
|
|
5396
|
+
if (!pinned) throw new Error(`Collection pinned variant not found: ${placement.pinnedVariantId}`);
|
|
5397
|
+
if (placement.subjectType === "asset") {
|
|
5398
|
+
if (!options.assetId) throw new Error("--collection-pinned-variant cannot reference an existing variant when creating a new asset");
|
|
5399
|
+
if (pinned.asset_id !== options.assetId) throw new Error("--collection-pinned-variant must reference a variant on the target asset");
|
|
5400
|
+
}
|
|
5401
|
+
}
|
|
5402
|
+
for (const relation of options.manualRelations) if (relation.object.subjectType === "asset") {
|
|
5403
|
+
if (!relation.object.assetId || !state.assetsById.has(relation.object.assetId)) throw new Error(`Manual relation object asset not found: ${relation.object.assetId ?? ""}`);
|
|
5404
|
+
} else if (!relation.object.variantId || !state.variantsById.has(relation.object.variantId)) throw new Error(`Manual relation object variant not found: ${relation.object.variantId ?? ""}`);
|
|
5405
|
+
}
|
|
5406
|
+
async function fetchAssetState(ctx, deps) {
|
|
5407
|
+
const assets = (await fetchJson$1(ctx, deps, `/api/spaces/${ctx.spaceId}/assets`)).assets ?? [];
|
|
5652
5408
|
const variantsById = /* @__PURE__ */ new Map();
|
|
5653
|
-
|
|
5409
|
+
await Promise.all(assets.map(async (asset) => {
|
|
5654
5410
|
const details = await fetchJson$1(ctx, deps, `/api/spaces/${ctx.spaceId}/assets/${encodeURIComponent(asset.id)}`);
|
|
5655
5411
|
for (const variant of details.variants ?? []) variantsById.set(variant.id, variant);
|
|
5656
|
-
}
|
|
5657
|
-
return {
|
|
5658
|
-
assets,
|
|
5659
|
-
variantsById,
|
|
5660
|
-
collections: collectionsData.collections ?? [],
|
|
5661
|
-
compositions: compositionsData.compositions ?? [],
|
|
5662
|
-
stylePresets: stylePresetsData.presets ?? []
|
|
5663
|
-
};
|
|
5664
|
-
}
|
|
5665
|
-
function validateSpaceReferences(records, state) {
|
|
5666
|
-
const assetsById = new Map(state.assets.map((asset) => [asset.id, asset]));
|
|
5667
|
-
const recordsByKey = new Map(records.map((record) => [record.localKey, record]));
|
|
5668
|
-
for (const record of records) {
|
|
5669
|
-
if (record.assetId) {
|
|
5670
|
-
const asset = assetsById.get(record.assetId);
|
|
5671
|
-
if (!asset) throw new Error(`Target asset not found for ${record.localKey}: ${record.assetId}`);
|
|
5672
|
-
if (asset.media_kind && asset.media_kind !== record.mediaKind) throw new Error(`Target asset ${record.assetId} is ${asset.media_kind}, but ${record.localKey} is ${record.mediaKind}`);
|
|
5673
|
-
}
|
|
5674
|
-
for (const lineage of record.lineage) {
|
|
5675
|
-
if (lineage.sourceVariantId && !state.variantsById.has(lineage.sourceVariantId)) throw new Error(`Source variant not found in space for ${record.localKey}: ${lineage.sourceVariantId}`);
|
|
5676
|
-
if (lineage.sourceFile) {
|
|
5677
|
-
const sourceRecord = recordsByKey.get(lineage.sourceFile);
|
|
5678
|
-
if (!sourceRecord) throw new Error(`Source file key not found for ${record.localKey}: ${lineage.sourceFile}`);
|
|
5679
|
-
if (sourceRecord.localKey === record.localKey) throw new Error(`Record ${record.localKey} cannot use itself as a lineage source`);
|
|
5680
|
-
}
|
|
5681
|
-
}
|
|
5682
|
-
}
|
|
5683
|
-
}
|
|
5684
|
-
function validateManifestPlan(manifest, state) {
|
|
5685
|
-
validateSpaceReferences(manifest.records, state);
|
|
5686
|
-
const recordsByKey = new Map(manifest.records.map((record) => [record.localKey, record]));
|
|
5687
|
-
const collectionsByName = new Map(state.collections.map((collection) => [collection.name, collection]));
|
|
5688
|
-
const compositionsByName = new Map(state.compositions.map((composition) => [composition.name, composition]));
|
|
5689
|
-
const stylePresetsByName = new Map(state.stylePresets.map((preset) => [preset.name, preset]));
|
|
5690
|
-
const stylePresetsById = new Map(state.stylePresets.map((preset) => [preset.id, preset]));
|
|
5691
|
-
const collections = dedupeCollections([
|
|
5692
|
-
...manifest.collections,
|
|
5693
|
-
...manifest.styleCollections,
|
|
5694
|
-
...manifest.records.flatMap((record) => record.styleCollections)
|
|
5695
|
-
]);
|
|
5696
|
-
const collectionItems = [
|
|
5697
|
-
...manifest.collectionItems,
|
|
5698
|
-
...manifest.styleCollections.flatMap((collection) => styleCollectionItems(collection)),
|
|
5699
|
-
...manifest.records.flatMap((record) => record.styleCollections.flatMap((collection) => styleCollectionItems(collection)))
|
|
5700
|
-
];
|
|
5701
|
-
const compositions = dedupeCompositions(manifest.compositions);
|
|
5702
|
-
const compositionItems = manifest.compositionItems;
|
|
5703
|
-
for (const collection of collections) if (!collectionsByName.has(collection.name) && !collection.create) throw new Error(`Collection not found: ${collection.name}. Add it to manifest collections with create: true.`);
|
|
5704
|
-
for (const item of collectionItems) {
|
|
5705
|
-
if (!collectionsByName.has(item.collectionName) && !collections.some((collection) => collection.name === item.collectionName && collection.create)) throw new Error(`Collection not found for collection item: ${item.collectionName}`);
|
|
5706
|
-
validateCollectionSubject(item, recordsByKey, state);
|
|
5707
|
-
}
|
|
5708
|
-
for (const relation of manifest.relations) {
|
|
5709
|
-
validateSubjectReference(relation.subject, recordsByKey, state, "Relation subject");
|
|
5710
|
-
validateSubjectReference(relation.object, recordsByKey, state, "Relation object");
|
|
5711
|
-
}
|
|
5712
|
-
for (const composition of compositions) {
|
|
5713
|
-
if (!compositionsByName.has(composition.name) && !composition.create) throw new Error(`Composition not found: ${composition.name}. Add it to manifest compositions with create: true.`);
|
|
5714
|
-
if (composition.output) {
|
|
5715
|
-
validateSubjectReference(composition.output, recordsByKey, state, `Composition ${composition.name} output`);
|
|
5716
|
-
if (composition.output.subjectType !== "variant") throw new Error(`Composition ${composition.name} output must reference a variant`);
|
|
5717
|
-
}
|
|
5718
|
-
}
|
|
5719
|
-
for (const item of compositionItems) {
|
|
5720
|
-
if (!compositionsByName.has(item.compositionName) && !compositions.some((composition) => composition.name === item.compositionName && composition.create)) throw new Error(`Composition not found for composition item: ${item.compositionName}`);
|
|
5721
|
-
if (item.recordKey) {
|
|
5722
|
-
if (!recordsByKey.has(item.recordKey)) throw new Error(`Composition item references unknown same-batch record: ${item.recordKey}`);
|
|
5723
|
-
} else if (!item.variantId) throw new Error(`Composition item for ${item.compositionName} must set variantId or recordKey`);
|
|
5724
|
-
else if (!state.variantsById.has(item.variantId)) throw new Error(`Composition item references unknown variant: ${item.variantId}`);
|
|
5725
|
-
if (item.assetId && !state.assets.some((asset) => asset.id === item.assetId)) throw new Error(`Composition item references unknown asset: ${item.assetId}`);
|
|
5726
|
-
}
|
|
5727
|
-
for (const preset of manifest.stylePresets) {
|
|
5728
|
-
const existingPresetById = preset.id ? stylePresetsById.get(preset.id) : void 0;
|
|
5729
|
-
const existingPresetByName = stylePresetsByName.get(preset.name);
|
|
5730
|
-
const existingPreset = preset.id ? existingPresetById : existingPresetByName;
|
|
5731
|
-
const createConflict = preset.id ? existingPresetById ?? existingPresetByName : existingPresetByName;
|
|
5732
|
-
if (preset.action === "create" && createConflict) throw new Error(`Style preset already exists: ${preset.name}`);
|
|
5733
|
-
if (preset.action === "update" && !existingPreset) throw new Error(`Style preset not found for update: ${preset.id ?? preset.name}`);
|
|
5734
|
-
if (preset.collectionName) {
|
|
5735
|
-
const willCreate = collections.some((collection) => collection.name === preset.collectionName && collection.create);
|
|
5736
|
-
if (!collectionsByName.has(preset.collectionName) && !willCreate) throw new Error(`Style preset ${preset.name} references missing collection: ${preset.collectionName}`);
|
|
5737
|
-
}
|
|
5738
|
-
}
|
|
5739
|
-
return {
|
|
5740
|
-
...manifest,
|
|
5741
|
-
collections,
|
|
5742
|
-
collectionItems,
|
|
5743
|
-
compositions,
|
|
5744
|
-
compositionItems
|
|
5745
|
-
};
|
|
5746
|
-
}
|
|
5747
|
-
function dedupeCollections(collections) {
|
|
5748
|
-
const byName = /* @__PURE__ */ new Map();
|
|
5749
|
-
for (const collection of collections) {
|
|
5750
|
-
const existing = byName.get(collection.name);
|
|
5751
|
-
byName.set(collection.name, {
|
|
5752
|
-
key: collection.key,
|
|
5753
|
-
name: collection.name,
|
|
5754
|
-
description: collection.description ?? existing?.description,
|
|
5755
|
-
sortIndex: collection.sortIndex ?? existing?.sortIndex,
|
|
5756
|
-
create: Boolean(existing?.create || collection.create)
|
|
5757
|
-
});
|
|
5758
|
-
}
|
|
5759
|
-
return [...byName.values()];
|
|
5760
|
-
}
|
|
5761
|
-
function dedupeCompositions(compositions) {
|
|
5762
|
-
const byName = /* @__PURE__ */ new Map();
|
|
5763
|
-
for (const composition of compositions) {
|
|
5764
|
-
const existing = byName.get(composition.name);
|
|
5765
|
-
byName.set(composition.name, {
|
|
5766
|
-
...existing,
|
|
5767
|
-
...composition,
|
|
5768
|
-
create: Boolean(existing?.create || composition.create)
|
|
5769
|
-
});
|
|
5770
|
-
}
|
|
5771
|
-
return [...byName.values()];
|
|
5772
|
-
}
|
|
5773
|
-
function styleCollectionItems(collection) {
|
|
5774
|
-
return collection.refs.map((recordKey, index) => ({
|
|
5775
|
-
collectionName: collection.name,
|
|
5776
|
-
role: "style_ref",
|
|
5777
|
-
subjectType: "asset",
|
|
5778
|
-
recordKey,
|
|
5779
|
-
pinnedVariantBehavior: "imported",
|
|
5780
|
-
sortIndex: index
|
|
5781
5412
|
}));
|
|
5413
|
+
return {
|
|
5414
|
+
assetsById: new Map(assets.map((asset) => [asset.id, asset])),
|
|
5415
|
+
variantsById
|
|
5416
|
+
};
|
|
5782
5417
|
}
|
|
5783
|
-
function
|
|
5784
|
-
if (item.recordKey) {
|
|
5785
|
-
if (!recordsByKey.has(item.recordKey)) throw new Error(`Collection item references unknown same-batch record: ${item.recordKey}`);
|
|
5786
|
-
return;
|
|
5787
|
-
}
|
|
5788
|
-
if (item.subjectType === "asset") {
|
|
5789
|
-
if (!item.assetId) throw new Error(`Collection item for ${item.collectionName} must set assetId or recordKey`);
|
|
5790
|
-
if (!state.assets.some((asset) => asset.id === item.assetId)) throw new Error(`Collection item references unknown asset: ${item.assetId}`);
|
|
5791
|
-
if (item.pinnedVariantId && !state.variantsById.has(item.pinnedVariantId)) throw new Error(`Collection item references unknown pinned variant: ${item.pinnedVariantId}`);
|
|
5792
|
-
return;
|
|
5793
|
-
}
|
|
5794
|
-
if (!item.variantId) throw new Error(`Collection item for ${item.collectionName} must set variantId or recordKey`);
|
|
5795
|
-
if (!state.variantsById.has(item.variantId)) throw new Error(`Collection item references unknown variant: ${item.variantId}`);
|
|
5796
|
-
}
|
|
5797
|
-
function validateSubjectReference(subject, recordsByKey, state, label) {
|
|
5798
|
-
if (subject.recordKey) {
|
|
5799
|
-
if (!recordsByKey.has(subject.recordKey)) throw new Error(`${label} references unknown same-batch record: ${subject.recordKey}`);
|
|
5800
|
-
return;
|
|
5801
|
-
}
|
|
5802
|
-
if (subject.subjectType === "asset") {
|
|
5803
|
-
if (!subject.assetId) throw new Error(`${label} must set assetId or recordKey`);
|
|
5804
|
-
if (!state.assets.some((asset) => asset.id === subject.assetId)) throw new Error(`${label} references unknown asset: ${subject.assetId}`);
|
|
5805
|
-
return;
|
|
5806
|
-
}
|
|
5807
|
-
if (!subject.variantId) throw new Error(`${label} must set variantId or recordKey`);
|
|
5808
|
-
if (!state.variantsById.has(subject.variantId)) throw new Error(`${label} references unknown variant: ${subject.variantId}`);
|
|
5809
|
-
}
|
|
5810
|
-
function buildUploadOrder(records) {
|
|
5811
|
-
const pending = new Map(records.map((record) => [record.localKey, record]));
|
|
5812
|
-
const uploaded = /* @__PURE__ */ new Set();
|
|
5813
|
-
const order = [];
|
|
5814
|
-
while (pending.size > 0) {
|
|
5815
|
-
let progressed = false;
|
|
5816
|
-
for (const [key, record] of pending) {
|
|
5817
|
-
if (!record.lineage.every((lineage) => !lineage.sourceFile || uploaded.has(lineage.sourceFile))) continue;
|
|
5818
|
-
order.push(record);
|
|
5819
|
-
uploaded.add(key);
|
|
5820
|
-
pending.delete(key);
|
|
5821
|
-
progressed = true;
|
|
5822
|
-
}
|
|
5823
|
-
if (!progressed) throw new Error(`Same-batch lineage contains a cycle or unresolved dependency: ${[...pending.keys()].join(", ")}`);
|
|
5824
|
-
}
|
|
5825
|
-
return order;
|
|
5826
|
-
}
|
|
5827
|
-
async function uploadRecord(ctx, deps, record, lineage, options) {
|
|
5828
|
-
const fileBuffer = await deps.readFile(record.filePath);
|
|
5829
|
-
const formData = new FormData();
|
|
5830
|
-
formData.append("file", new Blob([fileBuffer], { type: record.mimeType }), record.fileName);
|
|
5831
|
-
formData.append("operation", "import");
|
|
5832
|
-
formData.append("mediaKind", record.mediaKind);
|
|
5833
|
-
formData.append("assetType", record.assetType);
|
|
5834
|
-
formData.append("activeVariantBehavior", record.activeVariantBehavior);
|
|
5835
|
-
formData.append("generationProvenance", JSON.stringify(record.generationProvenance));
|
|
5836
|
-
if (record.assetId) formData.append("assetId", record.assetId);
|
|
5837
|
-
else formData.append("assetName", record.assetName);
|
|
5838
|
-
if (record.prompt) formData.append("prompt", record.prompt);
|
|
5839
|
-
if (record.model) formData.append("model", record.model);
|
|
5840
|
-
if (record.provider) formData.append("provider", record.provider);
|
|
5841
|
-
if (record.providerMetadata) formData.append("providerMetadata", JSON.stringify(record.providerMetadata));
|
|
5842
|
-
if (lineage.length > 0) formData.append("lineage", JSON.stringify(lineage));
|
|
5843
|
-
if (!options.quiet) deps.print(`Importing ${record.displayPath}...`);
|
|
5844
|
-
const response = await deps.fetch(`${ctx.baseUrl}/api/spaces/${ctx.spaceId}/upload`, {
|
|
5845
|
-
method: "POST",
|
|
5846
|
-
headers: { Authorization: `Bearer ${ctx.accessToken}` },
|
|
5847
|
-
body: formData
|
|
5848
|
-
});
|
|
5849
|
-
const data = await response.json();
|
|
5850
|
-
if (!response.ok) throw new Error(`Import failed for ${record.localKey}: ${"error" in data ? data.error : response.statusText}`);
|
|
5851
|
-
return data;
|
|
5852
|
-
}
|
|
5853
|
-
async function applyOrganizationPlan(ctx, deps, plan, uploadedByKey) {
|
|
5854
|
-
const collectionIds = [];
|
|
5418
|
+
async function applyUploadOrganization(ctx, deps, upload, options) {
|
|
5855
5419
|
const collectionItemIds = [];
|
|
5856
5420
|
const relationIds = [];
|
|
5857
|
-
const
|
|
5858
|
-
|
|
5859
|
-
|
|
5860
|
-
|
|
5861
|
-
const
|
|
5862
|
-
|
|
5863
|
-
const
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
const created = await postJson(ctx, deps, `/api/spaces/${ctx.spaceId}/collections/${encodeURIComponent(collection.id)}/items`, resolveCollectionItemRequest(item, uploadedByKey));
|
|
5421
|
+
const uploadedSubject = {
|
|
5422
|
+
assetId: upload.variant.asset_id,
|
|
5423
|
+
variantId: upload.variant.id
|
|
5424
|
+
};
|
|
5425
|
+
for (const placement of options.collectionPlacements) {
|
|
5426
|
+
if (!placement.collectionId) throw new Error(`Collection name was not resolved: ${placement.collectionName ?? ""}`);
|
|
5427
|
+
const body = placement.subjectType === "asset" ? {
|
|
5428
|
+
subjectType: "asset",
|
|
5429
|
+
assetId: uploadedSubject.assetId,
|
|
5430
|
+
role: placement.role,
|
|
5431
|
+
pinnedVariantId: placement.pinnedVariantId === void 0 ? uploadedSubject.variantId : placement.pinnedVariantId
|
|
5432
|
+
} : {
|
|
5433
|
+
subjectType: "variant",
|
|
5434
|
+
variantId: uploadedSubject.variantId,
|
|
5435
|
+
role: placement.role
|
|
5436
|
+
};
|
|
5437
|
+
const created = await postJson(ctx, deps, `/api/spaces/${ctx.spaceId}/collections/${encodeURIComponent(placement.collectionId)}/items`, body);
|
|
5875
5438
|
collectionItemIds.push(created.item.id);
|
|
5876
5439
|
}
|
|
5877
|
-
for (const relation of
|
|
5440
|
+
for (const relation of options.manualRelations) {
|
|
5878
5441
|
const created = await postJson(ctx, deps, `/api/spaces/${ctx.spaceId}/relations`, {
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5442
|
+
subject: relation.subjectType === "asset" ? {
|
|
5443
|
+
subjectType: "asset",
|
|
5444
|
+
assetId: uploadedSubject.assetId
|
|
5445
|
+
} : {
|
|
5446
|
+
subjectType: "variant",
|
|
5447
|
+
variantId: uploadedSubject.variantId
|
|
5448
|
+
},
|
|
5449
|
+
object: relation.object,
|
|
5882
5450
|
relationType: relation.relationType,
|
|
5883
5451
|
label: relation.label,
|
|
5884
5452
|
context: relation.context,
|
|
5885
|
-
metadata: relation.metadata
|
|
5886
|
-
sortIndex: relation.sortIndex
|
|
5453
|
+
metadata: relation.metadata
|
|
5887
5454
|
});
|
|
5888
5455
|
relationIds.push(created.relation.id);
|
|
5889
5456
|
}
|
|
5890
|
-
const compositions = await fetchJson$1(ctx, deps, `/api/spaces/${ctx.spaceId}/compositions`);
|
|
5891
|
-
const compositionsByName = new Map((compositions.compositions ?? []).map((composition) => [composition.name, composition]));
|
|
5892
|
-
for (const composition of plan.compositions) if (!compositionsByName.has(composition.name) && composition.create) {
|
|
5893
|
-
const output = composition.output ? resolveSubject(composition.output, uploadedByKey) : void 0;
|
|
5894
|
-
const created = await postJson(ctx, deps, `/api/spaces/${ctx.spaceId}/compositions`, {
|
|
5895
|
-
name: composition.name,
|
|
5896
|
-
description: composition.description,
|
|
5897
|
-
status: composition.status,
|
|
5898
|
-
outputAssetId: output?.assetId,
|
|
5899
|
-
outputVariantId: output?.variantId,
|
|
5900
|
-
metadata: composition.metadata,
|
|
5901
|
-
sortIndex: composition.sortIndex
|
|
5902
|
-
});
|
|
5903
|
-
compositionsByName.set(created.composition.name, created.composition);
|
|
5904
|
-
compositionIds.push(created.composition.id);
|
|
5905
|
-
}
|
|
5906
|
-
for (const item of plan.compositionItems) {
|
|
5907
|
-
const composition = compositionsByName.get(item.compositionName);
|
|
5908
|
-
if (!composition) throw new Error(`Composition not found during import: ${item.compositionName}`);
|
|
5909
|
-
const created = await postJson(ctx, deps, `/api/spaces/${ctx.spaceId}/compositions/${encodeURIComponent(composition.id)}/items`, resolveCompositionItemRequest(item, uploadedByKey));
|
|
5910
|
-
compositionItemIds.push(created.item.id);
|
|
5911
|
-
}
|
|
5912
|
-
const presets = await fetchJson$1(ctx, deps, `/api/spaces/${ctx.spaceId}/style-presets`);
|
|
5913
|
-
const presetsByName = new Map((presets.presets ?? []).map((preset) => [preset.name, preset]));
|
|
5914
|
-
const presetsById = new Map((presets.presets ?? []).map((preset) => [preset.id, preset]));
|
|
5915
|
-
for (const preset of plan.stylePresets) {
|
|
5916
|
-
const collectionId = preset.collectionId === null ? null : preset.collectionId ?? (preset.collectionName ? collectionsByName.get(preset.collectionName)?.id : void 0);
|
|
5917
|
-
if (preset.collectionName && collectionId === void 0) throw new Error(`Style preset ${preset.name} references missing collection during import: ${preset.collectionName}`);
|
|
5918
|
-
const request = {
|
|
5919
|
-
id: preset.id,
|
|
5920
|
-
name: preset.name,
|
|
5921
|
-
description: preset.description,
|
|
5922
|
-
stylePrompt: preset.stylePrompt,
|
|
5923
|
-
collectionId,
|
|
5924
|
-
enabled: preset.enabled,
|
|
5925
|
-
isDefault: preset.isDefault
|
|
5926
|
-
};
|
|
5927
|
-
const existing = preset.id ? presetsById.get(preset.id) : presetsByName.get(preset.name);
|
|
5928
|
-
if (preset.action === "update" || preset.action === "upsert" && existing) {
|
|
5929
|
-
const updated = await patchJson(ctx, deps, `/api/spaces/${ctx.spaceId}/style-presets/${encodeURIComponent(existing.id)}`, request);
|
|
5930
|
-
stylePresetIds.push(updated.preset.id);
|
|
5931
|
-
presetsByName.set(updated.preset.name, updated.preset);
|
|
5932
|
-
presetsById.set(updated.preset.id, updated.preset);
|
|
5933
|
-
} else {
|
|
5934
|
-
const created = await postJson(ctx, deps, `/api/spaces/${ctx.spaceId}/style-presets`, request);
|
|
5935
|
-
stylePresetIds.push(created.preset.id);
|
|
5936
|
-
presetsByName.set(created.preset.name, created.preset);
|
|
5937
|
-
presetsById.set(created.preset.id, created.preset);
|
|
5938
|
-
}
|
|
5939
|
-
}
|
|
5940
5457
|
return {
|
|
5941
|
-
collectionIds,
|
|
5942
5458
|
collectionItemIds,
|
|
5943
|
-
relationIds
|
|
5944
|
-
compositionIds,
|
|
5945
|
-
compositionItemIds,
|
|
5946
|
-
stylePresetIds
|
|
5947
|
-
};
|
|
5948
|
-
}
|
|
5949
|
-
function resolveCollectionItemRequest(item, uploadedByKey) {
|
|
5950
|
-
const subject = item.recordKey ? resolveSubject({
|
|
5951
|
-
subjectType: item.subjectType,
|
|
5952
|
-
recordKey: item.recordKey
|
|
5953
|
-
}, uploadedByKey) : {
|
|
5954
|
-
subjectType: item.subjectType,
|
|
5955
|
-
assetId: item.assetId,
|
|
5956
|
-
variantId: item.variantId
|
|
5957
|
-
};
|
|
5958
|
-
return {
|
|
5959
|
-
id: item.id,
|
|
5960
|
-
...subject,
|
|
5961
|
-
role: item.role,
|
|
5962
|
-
pinnedVariantId: item.pinnedVariantBehavior === "none" ? item.pinnedVariantId ?? null : item.pinnedVariantId ?? (item.recordKey ? uploadedByKey.get(item.recordKey).variantId : void 0),
|
|
5963
|
-
sortIndex: item.sortIndex
|
|
5964
|
-
};
|
|
5965
|
-
}
|
|
5966
|
-
function resolveCompositionItemRequest(item, uploadedByKey) {
|
|
5967
|
-
const uploaded = item.recordKey ? uploadedByKey.get(item.recordKey) : void 0;
|
|
5968
|
-
if (item.recordKey && !uploaded) throw new Error(`Could not resolve same-batch composition item: ${item.recordKey}`);
|
|
5969
|
-
return {
|
|
5970
|
-
id: item.id,
|
|
5971
|
-
role: item.role,
|
|
5972
|
-
label: item.label,
|
|
5973
|
-
assetId: item.assetId ?? uploaded?.assetId,
|
|
5974
|
-
variantId: item.variantId ?? uploaded.variantId,
|
|
5975
|
-
metadata: item.metadata,
|
|
5976
|
-
sortIndex: item.sortIndex
|
|
5977
|
-
};
|
|
5978
|
-
}
|
|
5979
|
-
function resolveSubject(subject, uploadedByKey) {
|
|
5980
|
-
if (!subject.recordKey) return {
|
|
5981
|
-
subjectType: subject.subjectType,
|
|
5982
|
-
assetId: subject.assetId,
|
|
5983
|
-
variantId: subject.variantId
|
|
5984
|
-
};
|
|
5985
|
-
const uploaded = uploadedByKey.get(subject.recordKey);
|
|
5986
|
-
if (!uploaded) throw new Error(`Could not resolve same-batch reference: ${subject.recordKey}`);
|
|
5987
|
-
return subject.subjectType === "asset" ? {
|
|
5988
|
-
subjectType: "asset",
|
|
5989
|
-
assetId: uploaded.assetId
|
|
5990
|
-
} : {
|
|
5991
|
-
subjectType: "variant",
|
|
5992
|
-
variantId: uploaded.variantId
|
|
5459
|
+
relationIds
|
|
5993
5460
|
};
|
|
5994
5461
|
}
|
|
5995
5462
|
async function postJson(ctx, deps, requestPath, json) {
|
|
5996
|
-
return sendJson(ctx, deps, "POST", requestPath, json);
|
|
5997
|
-
}
|
|
5998
|
-
async function patchJson(ctx, deps, requestPath, json) {
|
|
5999
|
-
return sendJson(ctx, deps, "PATCH", requestPath, json);
|
|
6000
|
-
}
|
|
6001
|
-
async function sendJson(ctx, deps, method, requestPath, json) {
|
|
6002
5463
|
const response = await deps.fetch(`${ctx.baseUrl}${requestPath}`, {
|
|
6003
|
-
method,
|
|
5464
|
+
method: "POST",
|
|
6004
5465
|
headers: {
|
|
6005
5466
|
Authorization: `Bearer ${ctx.accessToken}`,
|
|
6006
5467
|
Accept: "application/json",
|
|
@@ -6012,9 +5473,6 @@ async function sendJson(ctx, deps, method, requestPath, json) {
|
|
|
6012
5473
|
if (!response.ok) throw new Error("error" in data ? data.error : `Request failed: ${response.status}`);
|
|
6013
5474
|
return data;
|
|
6014
5475
|
}
|
|
6015
|
-
function stripUndefined(value) {
|
|
6016
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
|
|
6017
|
-
}
|
|
6018
5476
|
async function fetchJson$1(ctx, deps, requestPath) {
|
|
6019
5477
|
const response = await deps.fetch(`${ctx.baseUrl}${requestPath}`, { headers: {
|
|
6020
5478
|
Authorization: `Bearer ${ctx.accessToken}`,
|
|
@@ -6024,40 +5482,60 @@ async function fetchJson$1(ctx, deps, requestPath) {
|
|
|
6024
5482
|
if (!response.ok) throw new Error("error" in data ? data.error : `Request failed: ${response.status}`);
|
|
6025
5483
|
return data;
|
|
6026
5484
|
}
|
|
6027
|
-
function
|
|
6028
|
-
|
|
6029
|
-
deps.print(JSON.stringify(result, null, 2));
|
|
6030
|
-
return;
|
|
6031
|
-
}
|
|
6032
|
-
if (result.dryRun) {
|
|
6033
|
-
deps.print(`Dry run passed for ${result.records.length} import records.`);
|
|
6034
|
-
const organizationCount = result.collections.length + result.collectionItems + result.relations + result.compositions.length + result.compositionItems + result.stylePresets.length;
|
|
6035
|
-
if (organizationCount > 0) deps.print(` Organization changes: ${organizationCount}`);
|
|
6036
|
-
return;
|
|
6037
|
-
}
|
|
6038
|
-
deps.print(`Imported ${result.records.length} records.`);
|
|
6039
|
-
for (const record of result.records) deps.print(` ${record.key}: asset ${record.assetId}, variant ${record.variantId}`);
|
|
6040
|
-
const organizationCount = result.collectionIds.length + result.collectionItemIds.length + result.relationIds.length + result.compositionIds.length + result.compositionItemIds.length + result.stylePresetIds.length;
|
|
6041
|
-
if (organizationCount > 0) deps.print(` Organization records: ${organizationCount}`);
|
|
5485
|
+
function stripUndefined(value) {
|
|
5486
|
+
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
|
|
6042
5487
|
}
|
|
6043
5488
|
function printUsage$11() {
|
|
6044
5489
|
console.log(`
|
|
6045
5490
|
Usage:
|
|
6046
|
-
makefx
|
|
6047
|
-
makefx
|
|
5491
|
+
makefx upload <file> --asset <id> [--space <id>] Upload media to existing asset
|
|
5492
|
+
makefx upload <file> --name <name> [--space <id>] Upload media as a new asset
|
|
5493
|
+
|
|
5494
|
+
Options:
|
|
5495
|
+
--space <id> Target space ID; defaults from initialized project
|
|
5496
|
+
--asset <id> Target asset ID (upload as new variant)
|
|
5497
|
+
--name <name> New asset name (creates asset + variant)
|
|
5498
|
+
--type <type> Asset type for new assets (default: character)
|
|
5499
|
+
--media-kind <k> Optional explicit kind: image, audio, or video
|
|
5500
|
+
--prompt <text> Prompt provenance for uploaded media
|
|
5501
|
+
--model <model> Model provenance for uploaded media
|
|
5502
|
+
--provider <name> Provider provenance for uploaded media
|
|
5503
|
+
--provider-metadata <json> Provider metadata JSON object
|
|
5504
|
+
--generation-provenance <json> Extra provenance JSON object
|
|
5505
|
+
--source-variant <ids> Comma-separated source variants for upload lineage
|
|
5506
|
+
--source-variants <ids> Alias for --source-variant
|
|
5507
|
+
--relation-type <type> Lineage type: derived, refined, or forked (default: derived)
|
|
5508
|
+
--active-variant-behavior <b> if-missing, set-active, or keep
|
|
5509
|
+
--collection <ids> Comma-separated collection IDs for the uploaded asset or variant
|
|
5510
|
+
--collection-name <names> Comma-separated exact collection names for lookup
|
|
5511
|
+
--collection-role <role> Collection item role (default: member)
|
|
5512
|
+
--collection-subject <type> Collection subject: asset or variant (default: asset)
|
|
5513
|
+
--collection-pinned-variant <id|uploaded|none>
|
|
5514
|
+
Pin an asset collection item to the uploaded variant by default
|
|
5515
|
+
--manual-relation <spec> Comma-separated <type>:asset:<id> or <type>:variant:<id>
|
|
5516
|
+
--manual-relation-subject <type>
|
|
5517
|
+
Relation subject: uploaded asset or variant (default: variant)
|
|
5518
|
+
--manual-relation-label <text> Optional manual relation label
|
|
5519
|
+
--manual-relation-context <json|string>
|
|
5520
|
+
Optional manual relation context
|
|
5521
|
+
--manual-relation-metadata <json>
|
|
5522
|
+
Optional manual relation metadata object
|
|
5523
|
+
--json Print machine-readable upload output with Space IDs
|
|
5524
|
+
--env <env> Environment (production|stage|local)
|
|
5525
|
+
--local Shortcut for --env local
|
|
6048
5526
|
|
|
6049
|
-
|
|
6050
|
-
|
|
6051
|
-
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
5527
|
+
Examples:
|
|
5528
|
+
makefx upload hero.png --space abc123 --name "Hero Character"
|
|
5529
|
+
makefx upload hero.png --space abc123 --name "Hero" --prompt "external render" --provider blender
|
|
5530
|
+
makefx upload paintover.png --space abc123 --asset def456 --source-variant var123 --relation-type refined
|
|
5531
|
+
makefx upload scene.png --space abc123 --name "Cocina" --type scene --source-variants anna,roman,bg
|
|
5532
|
+
makefx upload hero.png --space abc123 --name "Hero" --collection collection_cast --collection-role character
|
|
5533
|
+
makefx upload hero.png --space abc123 --name "Hero" --collection-name "Cast" --collection-role character
|
|
5534
|
+
makefx upload thumbnail.png --space abc123 --asset asset_thumb --manual-relation thumbnail_for:asset:asset_target
|
|
5535
|
+
makefx upload theme.mp3 --space abc123 --name "Theme Music" --type audio
|
|
5536
|
+
makefx upload cutscene.mp4 --space abc123 --name "Opening Cutscene" --type video
|
|
5537
|
+
makefx upload variant.jpg --space abc123 --asset def456
|
|
5538
|
+
makefx upload hero.png --space abc123 --name "Hero" --json
|
|
6061
5539
|
`);
|
|
6062
5540
|
}
|
|
6063
5541
|
//#endregion
|
|
@@ -19997,6 +19475,7 @@ var UserProfileSchema = object({
|
|
|
19997
19475
|
var SessionConfigSchema = object({
|
|
19998
19476
|
googleClientId: string$1(),
|
|
19999
19477
|
environment: string$1(),
|
|
19478
|
+
mediaCdnBaseUrl: string$1().nullable().optional(),
|
|
20000
19479
|
features: object({ rotation: boolean$1() })
|
|
20001
19480
|
}).openapi("SessionConfig");
|
|
20002
19481
|
var AuthSessionResponseSchema = object({
|
|
@@ -26243,7 +25722,7 @@ Options:
|
|
|
26243
25722
|
}
|
|
26244
25723
|
//#endregion
|
|
26245
25724
|
//#region src/cli/index.ts
|
|
26246
|
-
var CLI_VERSION = "0.2.
|
|
25725
|
+
var CLI_VERSION = "0.2.2+eac63fce1aba";
|
|
26247
25726
|
async function main() {
|
|
26248
25727
|
const argv = process$1.argv.slice(2);
|
|
26249
25728
|
if (argv[0] === "--") argv.shift();
|
|
@@ -26352,9 +25831,6 @@ function printCommandHelp(command, positionals) {
|
|
|
26352
25831
|
case "upload":
|
|
26353
25832
|
printUploadHelp();
|
|
26354
25833
|
return;
|
|
26355
|
-
case "import":
|
|
26356
|
-
printImportHelp();
|
|
26357
|
-
return;
|
|
26358
25834
|
case "generate":
|
|
26359
25835
|
case "refine":
|
|
26360
25836
|
case "derive":
|
|
@@ -26471,8 +25947,10 @@ Listen:
|
|
|
26471
25947
|
|
|
26472
25948
|
Upload:
|
|
26473
25949
|
upload <file> --asset <id> [--space <id>] Upload image, audio, or video to existing asset
|
|
26474
|
-
upload <file> --name <name> [--space <id>] Upload
|
|
26475
|
-
|
|
25950
|
+
upload <file> --name <name> [--space <id>] Upload image, audio, or video as a new asset
|
|
25951
|
+
upload <file> --collection <id> Place uploaded media in a collection
|
|
25952
|
+
upload <file> --collection-name <name> Place uploaded media in an exact-name collection
|
|
25953
|
+
upload <file> --manual-relation <spec> Create a manual relation from uploaded media
|
|
26476
25954
|
|
|
26477
25955
|
Forge:
|
|
26478
25956
|
generate "prompt" --name <name> --type <type> -o <file>
|
|
@@ -26514,8 +25992,9 @@ Examples:
|
|
|
26514
25992
|
makefx audio sfx generate "A short brass victory sting" --name "Victory Sting" -o victory.wav
|
|
26515
25993
|
makefx video generate "A looping idle animation" --name "Idle Animation" --type animation --duration 6 --resolution 1080p --tier fast -o idle.mp4
|
|
26516
25994
|
makefx productions export --production-id s01e01-a2
|
|
26517
|
-
makefx
|
|
26518
|
-
makefx
|
|
25995
|
+
makefx upload hero.png --name "Hero" --collection collection_cast
|
|
25996
|
+
makefx upload hero.png --name "Hero" --collection-name "Cast" --json
|
|
25997
|
+
makefx upload thumbnail.png --asset asset_thumb --manual-relation thumbnail_for:asset:asset_target
|
|
26519
25998
|
makefx assets
|
|
26520
25999
|
makefx usage --from 2026-06-01
|
|
26521
26000
|
makefx spend --from 2026-06-01 --provider gemini
|
|
@@ -26592,7 +26071,7 @@ function printUploadHelp() {
|
|
|
26592
26071
|
console.log(`
|
|
26593
26072
|
Usage:
|
|
26594
26073
|
makefx upload <file> --asset <id> [--space <id>] Upload media to existing asset
|
|
26595
|
-
makefx upload <file> --name <name> [--space <id>]
|
|
26074
|
+
makefx upload <file> --name <name> [--space <id>] Upload media as a new asset
|
|
26596
26075
|
|
|
26597
26076
|
Options:
|
|
26598
26077
|
--space <id> Target space ID; defaults from initialized project
|
|
@@ -26600,35 +26079,34 @@ Options:
|
|
|
26600
26079
|
--name <name> New asset name (creates asset + variant)
|
|
26601
26080
|
--type <type> Asset type for new assets (default: character)
|
|
26602
26081
|
--media-kind <k> Optional explicit kind: image, audio, or video
|
|
26082
|
+
--prompt <text> Prompt provenance for uploaded media
|
|
26083
|
+
--model <model> Model provenance for uploaded media
|
|
26084
|
+
--provider <name> Provider provenance for uploaded media
|
|
26085
|
+
--provider-metadata <json> Provider metadata JSON object
|
|
26086
|
+
--generation-provenance <json> Extra provenance JSON object
|
|
26087
|
+
--source-variant <ids> Comma-separated source variants for upload lineage
|
|
26088
|
+
--source-variants <ids> Alias for --source-variant
|
|
26089
|
+
--relation-type <type> Lineage type: derived, refined, or forked (default: derived)
|
|
26090
|
+
--active-variant-behavior <b> if-missing, set-active, or keep
|
|
26091
|
+
--collection <ids> Comma-separated collection IDs for the uploaded asset or variant
|
|
26092
|
+
--collection-name <names> Comma-separated exact collection names for lookup
|
|
26093
|
+
--collection-role <role> Collection item role (default: member)
|
|
26094
|
+
--collection-subject <type> Collection subject: asset or variant (default: asset)
|
|
26095
|
+
--collection-pinned-variant <id|uploaded|none>
|
|
26096
|
+
Pin an asset collection item to the uploaded variant by default
|
|
26097
|
+
--manual-relation <spec> Comma-separated <type>:asset:<id> or <type>:variant:<id>
|
|
26098
|
+
--manual-relation-subject <type>
|
|
26099
|
+
Relation subject: uploaded asset or variant (default: variant)
|
|
26100
|
+
--manual-relation-label <text> Optional manual relation label
|
|
26101
|
+
--manual-relation-context <json|string>
|
|
26102
|
+
Optional manual relation context
|
|
26103
|
+
--manual-relation-metadata <json>
|
|
26104
|
+
Optional manual relation metadata object
|
|
26105
|
+
--json Print machine-readable upload output with Space IDs
|
|
26603
26106
|
--env <env> Environment (production|stage|local)
|
|
26604
26107
|
--local Shortcut for --env local
|
|
26605
26108
|
`);
|
|
26606
26109
|
}
|
|
26607
|
-
function printImportHelp() {
|
|
26608
|
-
console.log(`
|
|
26609
|
-
Usage:
|
|
26610
|
-
makefx import <manifest.json> [--space <id>]
|
|
26611
|
-
makefx import <manifest.json> --dry-run [--json]
|
|
26612
|
-
|
|
26613
|
-
Options:
|
|
26614
|
-
--space <id> Target space ID; defaults from initialized project
|
|
26615
|
-
--dry-run Validate manifest, files, targets, membership, lineage, and organization references
|
|
26616
|
-
--json Print machine-readable import or dry-run output
|
|
26617
|
-
--env <env> Environment (production|stage|local)
|
|
26618
|
-
--local Shortcut for --env local
|
|
26619
|
-
|
|
26620
|
-
Manifest:
|
|
26621
|
-
Records import files with prompt, model, provider, providerMetadata, and
|
|
26622
|
-
generationProvenance. Lineage entries record immutable source provenance using
|
|
26623
|
-
sourceFile or sourceVariantId; use collections, relations, and compositions
|
|
26624
|
-
for editable organization metadata. Style references are normal assets grouped
|
|
26625
|
-
into collections and selected through style presets.
|
|
26626
|
-
|
|
26627
|
-
Examples:
|
|
26628
|
-
makefx import external-renders.json --dry-run --json
|
|
26629
|
-
makefx import external-renders.json --space space_123
|
|
26630
|
-
`);
|
|
26631
|
-
}
|
|
26632
26110
|
function printForgeHelp(command) {
|
|
26633
26111
|
if (command === "generate") {
|
|
26634
26112
|
console.log(`
|
|
@@ -27044,9 +26522,6 @@ async function dispatchCommand(command, parsed) {
|
|
|
27044
26522
|
case "upload":
|
|
27045
26523
|
await handleUpload(parsed);
|
|
27046
26524
|
break;
|
|
27047
|
-
case "import":
|
|
27048
|
-
await handleImport(parsed);
|
|
27049
|
-
break;
|
|
27050
26525
|
case "generate":
|
|
27051
26526
|
await handleGenerate(parsed);
|
|
27052
26527
|
break;
|