@doufunao123/asset-gateway 0.22.0 → 0.22.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.
Files changed (2) hide show
  1. package/dist/index.js +404 -55
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command11 } from "commander";
4
+ import { Command as Command12 } from "commander";
5
5
 
6
6
  // src/commands/auth.ts
7
7
  import { existsSync as existsSync2, unlinkSync } from "fs";
@@ -15,7 +15,7 @@ import { AssetForgeError } from "@doufunao123/assetforge-sdk";
15
15
 
16
16
  // src/meta.ts
17
17
  var CLI_NAME = "asset-gateway";
18
- var CLI_VERSION = "0.19.0";
18
+ var CLI_VERSION = "0.22.2";
19
19
  var CLI_DESCRIPTION = "Universal asset generation gateway CLI";
20
20
  var DEFAULT_GATEWAY_URL = "https://asset.origingame.dev";
21
21
 
@@ -599,6 +599,7 @@ function createDescribeCommand() {
599
599
  // src/commands/generate.ts
600
600
  import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
601
601
  import { dirname as dirname2, extname, join as join2 } from "path";
602
+ import { AssetForgeError as AssetForgeError3 } from "@doufunao123/assetforge-sdk";
602
603
  import { Command as Command3 } from "commander";
603
604
  function inferExtension(assetType) {
604
605
  const map = {
@@ -613,7 +614,17 @@ function inferExtension(assetType) {
613
614
  prop: "glb",
614
615
  text: "txt",
615
616
  sprite: "png",
616
- world: "spz"
617
+ world: "spz",
618
+ animation: "glb",
619
+ material: "zip",
620
+ hdri: "hdr",
621
+ vfx: "zip",
622
+ lut: "cube",
623
+ shader: "glsl",
624
+ font_typeface: "json",
625
+ skybox: "png",
626
+ decal: "png",
627
+ heightmap: "png"
617
628
  };
618
629
  return map[assetType] ?? "bin";
619
630
  }
@@ -661,7 +672,9 @@ function inferMimeType(filePath) {
661
672
  ".jpeg": "image/jpeg",
662
673
  ".png": "image/png",
663
674
  ".webp": "image/webp",
664
- ".gif": "image/gif"
675
+ ".gif": "image/gif",
676
+ ".mp4": "video/mp4",
677
+ ".mov": "video/quicktime"
665
678
  };
666
679
  return map[ext] ?? "application/octet-stream";
667
680
  }
@@ -681,6 +694,10 @@ function parseCommaSeparatedValues(raw) {
681
694
  }
682
695
  return String(raw).split(",").map((value) => value.trim()).filter(Boolean);
683
696
  }
697
+ function collectValue(value, previous = []) {
698
+ previous.push(value);
699
+ return previous;
700
+ }
684
701
  async function saveOutput(result, assetType, outputDir, preferredFormat) {
685
702
  const ext = inferExtFromResult(result) ?? infer3dExtension(preferredFormat) ?? inferExtension(assetType);
686
703
  const timestamp = Date.now();
@@ -747,18 +764,66 @@ function assertHas3dInput(prompt, image, images) {
747
764
  function toJsonObject(value) {
748
765
  return value;
749
766
  }
767
+ function isPackOnlyResult(value) {
768
+ return value.ok === false && value.pack_only === true;
769
+ }
770
+ async function runGeneratedAssetCommand(command, sdkMethod, commandName, assetType, options) {
771
+ const ctx = createContext(command);
772
+ const generate = ctx.client[sdkMethod];
773
+ const data = await generate.call(ctx.client, String(options.prompt), {
774
+ provider: options.provider,
775
+ model: options.model,
776
+ size: options.size,
777
+ quality: options.quality,
778
+ background: options.background,
779
+ output_format: options.outputFormat,
780
+ n: options.n ? Number(options.n) : void 0,
781
+ preset: options.preset,
782
+ transparent: options.transparent ? true : void 0,
783
+ input: toInputFile(options.input)
784
+ });
785
+ if (isPackOnlyResult(data)) {
786
+ throw new AssetForgeError3("This asset type requires a library pack. Run: asset-gateway pack list", {
787
+ code: "PACK_ONLY",
788
+ details: data
789
+ });
790
+ }
791
+ const localPath = await saveOutput(data, assetType, String(options.outputDir ?? "."));
792
+ if (localPath) data.local_path = localPath;
793
+ printSuccess(commandName, data, ctx);
794
+ }
795
+ function createGeneratedAssetCommand(name, sdkMethod, assetType, description) {
796
+ const command = new Command3(name).description(description).requiredOption("--prompt <text>", "Asset description prompt").option("--provider <id>", "Provider to use").option("--model <model>", "Model to use").option("--size <size>", "Output size when supported").option("--input <path>", "Input file path or URL when supported").option("--quality <quality>", "Image quality: low, medium, high").option("--background <background>", "Image background: auto, opaque, transparent").option("--output-format <fmt>", "Image output format: png, webp, jpeg").option("--n <num>", "Number of image variants (1-10)").option("--preset <preset>", "Image preset id").option("--transparent", "Request transparent background when supported").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
797
+ const commandName = `generate.${assetType}`;
798
+ try {
799
+ await runGeneratedAssetCommand(this, sdkMethod, commandName, assetType, options);
800
+ } catch (error2) {
801
+ printError(commandName, error2);
802
+ }
803
+ });
804
+ if (name === "font-typeface") {
805
+ command.alias("font_typeface");
806
+ }
807
+ return command;
808
+ }
750
809
  function createGenerateCommand() {
751
810
  const command = new Command3("generate").description("Generate assets via the gateway");
752
811
  command.addCommand(
753
- new Command3("image").description("Generate an image from a text prompt").requiredOption("--prompt <text>", "Image description prompt").option("--provider <id>", "Provider to use").option("--transparent", "Request transparent background").option("--model <model>", "Model to use").option("--size <size>", "Image size (e.g. 1024x1024)").option("--input <url>", "Input image URL for editing (Gemini/Grok)").option("--ref <urls...>", "Reference image URLs for multi-image editing (repeatable)").option("--edit-mode <mode>", "Edit mode: edit, inpaint, restyle, expand").option("--session <id>", "Session ID for multi-turn editing").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
812
+ new Command3("image").description("Generate an image from a text prompt").requiredOption("--prompt <text>", "Image description prompt").option("--provider <id>", "Provider to use").option("--transparent", "Request transparent background").option("--model <model>", "Model to use").option("--size <size>", "Image size (e.g. 1024x1024)").option("--quality <quality>", "Image quality: low, medium, high").option("--background <background>", "Image background: auto, opaque, transparent").option("--output-format <fmt>", "Image output format: png, webp, jpeg").option("--n <num>", "Number of image variants (1-10)").option("--preset <preset>", "Image preset id").option("--mask <path>", "PNG alpha mask path or URL for inpainting").option("--input <url>", "Input image URL for editing (Gemini/Grok)").option("--ref <urls...>", "Reference image URLs for multi-image editing (repeatable)").option("--edit-mode <mode>", "Edit mode: edit, inpaint, restyle, expand").option("--session <id>", "Session ID for multi-turn editing").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
754
813
  try {
755
814
  const ctx = createContext(this);
756
815
  const data = await ctx.client.image(options.prompt, {
757
816
  provider: options.provider,
758
817
  model: options.model,
759
818
  size: options.size,
819
+ quality: options.quality,
820
+ background: options.background,
821
+ output_format: options.outputFormat,
822
+ n: options.n ? Number(options.n) : void 0,
823
+ preset: options.preset,
824
+ mask: toInputFile(options.mask),
760
825
  transparent: options.transparent ? true : void 0,
761
- input: options.input,
826
+ input: toInputFile(options.input),
762
827
  reference_images: options.ref,
763
828
  edit_mode: options.editMode,
764
829
  session_id: options.session
@@ -1012,12 +1077,21 @@ function createGenerateCommand() {
1012
1077
  })
1013
1078
  );
1014
1079
  command.addCommand(
1015
- new Command3("world").description("Generate a 3D world/environment using WorldLabs Marble").requiredOption("--prompt <text>", "Text prompt describing the environment").option("--input <path>", "Input image (local path or URL) for image-to-world").option("--model <model>", "Model: marble-1.0-draft, marble-1.0, marble-1.1, marble-1.1-plus", "marble-1.1").option("--display-name <name>", "Display name for the generated world").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1080
+ new Command3("world").description("Generate a 3D world/environment using WorldLabs Marble").option("--prompt <text>", "Text prompt describing the environment").option("--input <path>", "Input image (local path or URL) for image-to-world").option("--image <path>", "Input image (local path or URL) for image-to-world").option("--panorama <path>", "360 panorama image path or URL").option("--video <path>", "Input video path or URL").option("--multi-image <path>", "Multi-view image path or URL (repeatable)", collectValue, []).option("--quality <quality>", "World quality: low, high").option("--model <model>", "Model: marble-1.0-draft, marble-1.0, marble-1.1, marble-1.1-plus", "marble-1.1").option("--display-name <name>", "Display name for the generated world").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1016
1081
  try {
1082
+ const prompt = options.prompt ?? "";
1083
+ const multiImage = options.multiImage.map((value) => toInputFile(value)).filter((value) => Boolean(value));
1084
+ if (!prompt && !options.input && !options.image && !options.panorama && !options.video && multiImage.length === 0) {
1085
+ throw new Error("Provide at least one of --prompt, --image, --input, --panorama, --video, or --multi-image");
1086
+ }
1017
1087
  const ctx = createContext(this);
1018
- const data = await ctx.client.world(options.prompt, {
1019
- input: toInputFile(options.input),
1088
+ const data = await ctx.client.world(prompt, {
1089
+ input: toInputFile(options.input ?? options.image),
1020
1090
  model: options.model,
1091
+ panorama_url: toInputFile(options.panorama),
1092
+ video_url: toInputFile(options.video),
1093
+ multi_image_url: multiImage.length > 0 ? multiImage : void 0,
1094
+ quality: options.quality,
1021
1095
  display_name: options.displayName
1022
1096
  });
1023
1097
  const localPath = await saveOutput(data, "world", options.outputDir);
@@ -1028,6 +1102,36 @@ function createGenerateCommand() {
1028
1102
  }
1029
1103
  })
1030
1104
  );
1105
+ command.addCommand(
1106
+ createGeneratedAssetCommand("animation", "animation", "animation", "Generate a 3D animation clip with Meshy AI")
1107
+ );
1108
+ command.addCommand(
1109
+ createGeneratedAssetCommand("material", "material", "material", "Resolve a PBR material from library packs")
1110
+ );
1111
+ command.addCommand(
1112
+ createGeneratedAssetCommand("hdri", "hdri", "hdri", "Resolve an HDRI environment from library packs")
1113
+ );
1114
+ command.addCommand(
1115
+ createGeneratedAssetCommand("vfx", "vfx", "vfx", "Resolve a Three.js VFX bundle from library packs")
1116
+ );
1117
+ command.addCommand(
1118
+ createGeneratedAssetCommand("lut", "lut", "lut", "Resolve a LUT cube from library packs")
1119
+ );
1120
+ command.addCommand(
1121
+ createGeneratedAssetCommand("shader", "shader", "shader", "Resolve a GLSL shader from library packs")
1122
+ );
1123
+ command.addCommand(
1124
+ createGeneratedAssetCommand("font-typeface", "fontTypeface", "font_typeface", "Resolve a Three.js typeface font from library packs")
1125
+ );
1126
+ command.addCommand(
1127
+ createGeneratedAssetCommand("skybox", "skybox", "skybox", "Generate an equirectangular skybox image")
1128
+ );
1129
+ command.addCommand(
1130
+ createGeneratedAssetCommand("decal", "decal", "decal", "Generate a transparent decal image")
1131
+ );
1132
+ command.addCommand(
1133
+ createGeneratedAssetCommand("heightmap", "heightmap", "heightmap", "Generate a grayscale terrain heightmap")
1134
+ );
1031
1135
  return command;
1032
1136
  }
1033
1137
 
@@ -1075,21 +1179,34 @@ function createJobCommand() {
1075
1179
  }
1076
1180
 
1077
1181
  // src/commands/library.ts
1182
+ import { readFile, writeFile } from "fs/promises";
1183
+ import { AssetForgeError as AssetForgeError4 } from "@doufunao123/assetforge-sdk";
1078
1184
  import { Command as Command5 } from "commander";
1079
1185
  function createLibraryCommand() {
1080
1186
  const command = new Command5("library").description(
1081
1187
  "Search and manage the asset library"
1082
1188
  );
1083
1189
  command.addCommand(
1084
- new Command5("search").description("Search the asset library").argument("[query]", "Search query").option("-t, --type <type>", "Filter by asset type (audio, music, image, etc.)").option("--tags <tags>", "Filter by tags (comma-separated)").option("--source <source>", "Filter by source (manual, generated, imported)").option("-n, --limit <limit>", "Max results", "20").option("--offset <offset>", "Offset for pagination", "0").action(async function(query) {
1190
+ new Command5("search").description("Search the asset library").argument("[query]", "Search query").option("-q, --query <query>", "Search query").option("-t, --type <type>", "Filter by asset type (audio, music, image, etc.)").option("--tags <tags>", "Filter by tags (comma-separated)").option("--source <source>", "Filter by source (manual, generated, imported)").option("--mode <mode>", "Search mode (fts, vector, hybrid)").option("--style <style>", "Filter by visual style").option("--composition <composition>", "Filter by composition").option("--lighting <lighting>", "Filter by lighting").option("--color-tone <tone>", "Filter by color tone").option("--mood <mood>", "Filter by mood (comma-separated)").option("--theme <theme>", "Filter by theme (comma-separated)").option("--era <era>", "Filter by era").option("--rig-name <rig>", "Filter by exact rig name").option("--compatible-rig <rig>", "Filter by compatible rig").option("--no-rerank", "Disable LLM reranking").option("-n, --limit <limit>", "Max results", "20").option("--offset <offset>", "Offset for pagination", "0").action(async function(query) {
1085
1191
  const ctx = createContext(this);
1086
1192
  const opts = this.opts();
1087
1193
  try {
1088
1194
  const data = await ctx.client.library.search({
1089
- q: query,
1195
+ q: opts.query ?? query,
1090
1196
  type: opts.type,
1091
1197
  tags: opts.tags,
1092
1198
  source: opts.source,
1199
+ mode: opts.mode,
1200
+ style: opts.style,
1201
+ composition: opts.composition,
1202
+ lighting: opts.lighting,
1203
+ color_tone: opts.colorTone,
1204
+ mood: opts.mood,
1205
+ theme: opts.theme,
1206
+ era: opts.era,
1207
+ rig_name: opts.rigName,
1208
+ compatible_rig: opts.compatibleRig,
1209
+ rerank: opts.rerank,
1093
1210
  limit: Number(opts.limit),
1094
1211
  offset: Number(opts.offset)
1095
1212
  });
@@ -1099,6 +1216,88 @@ function createLibraryCommand() {
1099
1216
  }
1100
1217
  })
1101
1218
  );
1219
+ command.addCommand(
1220
+ new Command5("related").description("Find rig-compatible related assets").argument("<id>", "Library item ID").option("-t, --type <type>", "Filter related assets by type").option("-n, --limit <limit>", "Max results", "20").action(async function(id) {
1221
+ const ctx = createContext(this);
1222
+ const opts = this.opts();
1223
+ try {
1224
+ const data = await ctx.client.library.related(id, {
1225
+ type: opts.type,
1226
+ limit: Number(opts.limit)
1227
+ });
1228
+ printSuccess("library.related", data, ctx);
1229
+ } catch (error2) {
1230
+ printError("library.related", error2, ctx.human);
1231
+ }
1232
+ })
1233
+ );
1234
+ command.addCommand(
1235
+ new Command5("bundle").description("Download a zip bundle of library assets").argument("<ids...>", "Library item IDs").requiredOption("-o, --output <path>", "Output zip path").action(async function(ids) {
1236
+ const ctx = createContext(this);
1237
+ const opts = this.opts();
1238
+ try {
1239
+ const blob = await ctx.client.library.bundle({ asset_ids: ids, format: "zip" });
1240
+ const buffer = Buffer.from(await blob.arrayBuffer());
1241
+ await writeFile(opts.output, buffer);
1242
+ printSuccess(
1243
+ "library.bundle",
1244
+ { output: opts.output, bytes: buffer.length, asset_ids: ids },
1245
+ ctx
1246
+ );
1247
+ } catch (error2) {
1248
+ printError("library.bundle", error2, ctx.human);
1249
+ }
1250
+ })
1251
+ );
1252
+ command.addCommand(
1253
+ new Command5("ingest").description("Queue or run a library ingest job (admin only)").requiredOption("--source <source>", "Ingest source (manual, generated, pack, imported)").requiredOption("-t, --type <type>", "Asset type").option("--file-url <url>", "Public asset URL").option("--file <path>", "Local file to encode as base64").option("--thumbnail-url <url>", "Thumbnail URL").option("--name <name>", "Display name").option("--tag <tag>", "User tag (repeatable)", collect, []).option("--source-job-id <id>", "Source generate job ID").option("--pack-id <id>", "Pack ID").option("--pack-asset-key <key>", "Pack asset key").option("--sync", "Run ingest synchronously and return the library result").action(async function() {
1254
+ const ctx = createContext(this);
1255
+ const opts = this.opts();
1256
+ try {
1257
+ const request = {
1258
+ source: opts.source,
1259
+ asset_type: opts.type,
1260
+ file_url: opts.fileUrl,
1261
+ file_data_b64: opts.file ? await readBase64(opts.file) : void 0,
1262
+ thumbnail_url: opts.thumbnailUrl,
1263
+ name: opts.name,
1264
+ user_tags: opts.tag,
1265
+ source_job_id: opts.sourceJobId,
1266
+ pack_id: opts.packId,
1267
+ pack_asset_key: opts.packAssetKey
1268
+ };
1269
+ const data = opts.sync ? await ctx.client.library.ingestSync(request) : await ctx.client.library.ingest(request);
1270
+ printSuccess(opts.sync ? "library.ingest_sync" : "library.ingest", data, ctx);
1271
+ } catch (error2) {
1272
+ printError("library.ingest", error2, ctx.human);
1273
+ }
1274
+ })
1275
+ );
1276
+ command.addCommand(
1277
+ new Command5("ingest-status").description("Get a library ingest job status").argument("<id>", "Ingest job ID").action(async function(id) {
1278
+ const ctx = createContext(this);
1279
+ try {
1280
+ const data = await ctx.client.library.ingestStatus(id);
1281
+ printSuccess("library.ingest_status", data, ctx);
1282
+ } catch (error2) {
1283
+ printError("library.ingest_status", error2, ctx.human);
1284
+ }
1285
+ })
1286
+ );
1287
+ command.addCommand(
1288
+ new Command5("ingest-wait").description("Poll a library ingest job until completion").argument("<id>", "Ingest job ID").option("--interval-ms <ms>", "Polling interval", "1000").action(async function(id) {
1289
+ const ctx = createContext(this);
1290
+ const opts = this.opts();
1291
+ try {
1292
+ const data = await ctx.client.library.ingestWait(id, {
1293
+ intervalMs: Number(opts.intervalMs)
1294
+ });
1295
+ printSuccess("library.ingest_wait", data, ctx);
1296
+ } catch (error2) {
1297
+ printError("library.ingest_wait", error2, ctx.human);
1298
+ }
1299
+ })
1300
+ );
1102
1301
  command.addCommand(
1103
1302
  new Command5("add").description("Add an item to the asset library").requiredOption("--name <name>", "Display name").requiredOption("--url <url>", "File URL (public)").requiredOption("-t, --type <type>", "Asset type (audio, music, image, etc.)").option("-d, --description <desc>", "Description").option("--tags <tags>", "Comma-separated tags").option("--duration <seconds>", "Duration in seconds (for audio/video)").option("--source <source>", "Source (manual, generated, imported)", "manual").action(async function() {
1104
1303
  const ctx = createContext(this);
@@ -1161,20 +1360,169 @@ function createLibraryCommand() {
1161
1360
  }
1162
1361
  })
1163
1362
  );
1363
+ command.addCommand(
1364
+ new Command5("backfill").description("Queue library embedding/enrichment backfill jobs (admin)").option("-t, --asset-type <type>", "Filter by asset type").option("--since <date>", "Only backfill assets created after this RFC3339 date").option("-n, --limit <limit>", "Max items to enqueue", "100").option("--dry-run", "Return matching IDs without enqueueing jobs").action(async function() {
1365
+ const ctx = createContext(this);
1366
+ const opts = this.opts();
1367
+ try {
1368
+ const request = {
1369
+ asset_type: opts.assetType,
1370
+ since: opts.since,
1371
+ limit: Number(opts.limit),
1372
+ dry_run: Boolean(opts.dryRun)
1373
+ };
1374
+ const data = await ctx.client.library.backfill(request);
1375
+ printSuccess("library.backfill", data, ctx);
1376
+ } catch (error2) {
1377
+ printError("library.backfill", error2, ctx.human);
1378
+ }
1379
+ })
1380
+ );
1381
+ command.addCommand(
1382
+ new Command5("reenrich").description("Queue library re-enrichment jobs (admin)").option("--id <id>", "Library item ID (repeatable)", collect, []).option("-t, --asset-type <type>", "Filter by asset type").option("--taxonomy-version-lt <version>", "Only items below this taxonomy version").option("--force-visual", "Force visual/textual analysis", true).option("--no-force-visual", "Do not force visual/textual analysis").option("--recompute-embedding", "Recompute embedding vectors").option("-n, --limit <limit>", "Max items to enqueue", "100").action(async function() {
1383
+ const ctx = createContext(this);
1384
+ const opts = this.opts();
1385
+ try {
1386
+ const request = {
1387
+ ids: opts.id,
1388
+ asset_type: opts.assetType,
1389
+ taxonomy_version_lt: opts.taxonomyVersionLt ? Number(opts.taxonomyVersionLt) : void 0,
1390
+ force_visual: opts.forceVisual,
1391
+ recompute_embedding: Boolean(opts.recomputeEmbedding),
1392
+ limit: Number(opts.limit)
1393
+ };
1394
+ const data = await ctx.client.library.reenrich(request);
1395
+ printSuccess("library.reenrich", data, ctx);
1396
+ } catch (error2) {
1397
+ printError("library.reenrich", error2, ctx.human);
1398
+ }
1399
+ })
1400
+ );
1401
+ return command;
1402
+ }
1403
+ function collect(value, previous) {
1404
+ previous.push(value);
1405
+ return previous;
1406
+ }
1407
+ async function readBase64(filePath) {
1408
+ try {
1409
+ return (await readFile(filePath)).toString("base64");
1410
+ } catch (error2) {
1411
+ throw new AssetForgeError4(
1412
+ `Failed to read file ${filePath}: ${error2 instanceof Error ? error2.message : String(error2)}`,
1413
+ { code: "CONFIG_ERROR" }
1414
+ );
1415
+ }
1416
+ }
1417
+
1418
+ // src/commands/pack.ts
1419
+ import { readFile as readFile2 } from "fs/promises";
1420
+ import { createInterface } from "readline/promises";
1421
+ import { stdin as input, stdout as output2 } from "process";
1422
+ import { AssetForgeError as AssetForgeError5 } from "@doufunao123/assetforge-sdk";
1423
+ import { Command as Command6 } from "commander";
1424
+ function createPackCommand() {
1425
+ const command = new Command6("pack").description("Manage library asset packs");
1426
+ command.addCommand(
1427
+ new Command6("list").description("List installed library packs").action(async function() {
1428
+ const ctx = createContext(this);
1429
+ try {
1430
+ const data = await ctx.client.library.packs();
1431
+ printSuccess("pack.list", data, ctx);
1432
+ } catch (error2) {
1433
+ printError("pack.list", error2, ctx.human);
1434
+ }
1435
+ })
1436
+ );
1437
+ command.addCommand(
1438
+ new Command6("install").description("Install a library pack").argument("[source]", "Pack source (builtin, url, upload)").option("--source <source>", "Pack source (builtin, url, upload)").option("--id <id>", "Builtin pack ID").option("--version <version>", "Pack version").option("--url <url>", "HTTP tarball URL").option("--file <tarball>", "Local tarball to upload as base64").action(async function(sourceArg) {
1439
+ const ctx = createContext(this);
1440
+ const opts = this.opts();
1441
+ try {
1442
+ const source = opts.source ?? sourceArg;
1443
+ if (!source) {
1444
+ throw new AssetForgeError5("Pack source is required", { code: "CONFIG_ERROR" });
1445
+ }
1446
+ const request = {
1447
+ source,
1448
+ id: opts.id,
1449
+ version: opts.version,
1450
+ url: opts.url,
1451
+ tarball_b64: opts.file ? await readBase642(opts.file) : void 0
1452
+ };
1453
+ const data = await ctx.client.library.packsInstall(request);
1454
+ printSuccess("pack.install", data, ctx);
1455
+ } catch (error2) {
1456
+ printError("pack.install", error2, ctx.human);
1457
+ }
1458
+ })
1459
+ );
1460
+ command.addCommand(
1461
+ new Command6("delete").description("Delete a library pack (admin only)").argument("<id>", "Pack ID").option("-y, --yes", "Skip confirmation prompt").action(async function(id) {
1462
+ const ctx = createContext(this);
1463
+ const opts = this.opts();
1464
+ try {
1465
+ if (!opts.yes) {
1466
+ await confirmDelete(id);
1467
+ }
1468
+ const data = await ctx.client.library.packsDelete(id);
1469
+ printSuccess("pack.delete", data, ctx);
1470
+ } catch (error2) {
1471
+ printError("pack.delete", error2, ctx.human);
1472
+ }
1473
+ })
1474
+ );
1475
+ command.addCommand(
1476
+ new Command6("refresh").description("Refresh an installed library pack (admin only)").argument("<id>", "Pack ID").action(async function(id) {
1477
+ const ctx = createContext(this);
1478
+ try {
1479
+ const data = await ctx.client.library.packsRefresh(id);
1480
+ printSuccess("pack.refresh", data, ctx);
1481
+ } catch (error2) {
1482
+ printError("pack.refresh", error2, ctx.human);
1483
+ }
1484
+ })
1485
+ );
1164
1486
  return command;
1165
1487
  }
1488
+ async function readBase642(filePath) {
1489
+ try {
1490
+ return (await readFile2(filePath)).toString("base64");
1491
+ } catch (error2) {
1492
+ throw new AssetForgeError5(
1493
+ `Failed to read file ${filePath}: ${error2 instanceof Error ? error2.message : String(error2)}`,
1494
+ { code: "CONFIG_ERROR" }
1495
+ );
1496
+ }
1497
+ }
1498
+ async function confirmDelete(id) {
1499
+ if (!input.isTTY) {
1500
+ throw new AssetForgeError5("Refusing to delete pack without confirmation. Pass --yes to confirm.", {
1501
+ code: "CONFIG_ERROR"
1502
+ });
1503
+ }
1504
+ const rl = createInterface({ input, output: output2 });
1505
+ try {
1506
+ const answer = await rl.question(`Delete pack ${id}? Type the pack ID to confirm: `);
1507
+ if (answer !== id) {
1508
+ throw new AssetForgeError5("Pack deletion cancelled", { code: "CONFIG_ERROR" });
1509
+ }
1510
+ } finally {
1511
+ rl.close();
1512
+ }
1513
+ }
1166
1514
 
1167
1515
  // src/commands/process.ts
1168
1516
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
1169
1517
  import { existsSync as existsSync4 } from "fs";
1170
1518
  import { join as join3 } from "path";
1171
- import { Command as Command6 } from "commander";
1172
- function readInputAsBase64(input) {
1173
- if (existsSync4(input)) {
1174
- const bytes = readFileSync3(input);
1519
+ import { Command as Command7 } from "commander";
1520
+ function readInputAsBase64(input2) {
1521
+ if (existsSync4(input2)) {
1522
+ const bytes = readFileSync3(input2);
1175
1523
  return `data:image/png;base64,${bytes.toString("base64")}`;
1176
1524
  }
1177
- return input;
1525
+ return input2;
1178
1526
  }
1179
1527
  function saveProcessOutput(data, outputDir) {
1180
1528
  mkdirSync3(outputDir, { recursive: true });
@@ -1202,9 +1550,9 @@ function saveProcessOutput(data, outputDir) {
1202
1550
  return filePath;
1203
1551
  }
1204
1552
  function createProcessCommand() {
1205
- const command = new Command6("process").description("Post-process images (crop, resize, compose, remove-bg)");
1553
+ const command = new Command7("process").description("Post-process images (crop, resize, compose, remove-bg)");
1206
1554
  command.addCommand(
1207
- new Command6("crop").description("Smart crop an image (trim transparent borders)").requiredOption("--input <path>", "Input image (file path or URL)").option("--mode <mode>", "Crop mode: tightest or power_of2", "tightest").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1555
+ new Command7("crop").description("Smart crop an image (trim transparent borders)").requiredOption("--input <path>", "Input image (file path or URL)").option("--mode <mode>", "Crop mode: tightest or power_of2", "tightest").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1208
1556
  try {
1209
1557
  const ctx = createContext(this);
1210
1558
  const data = await ctx.client.process({
@@ -1220,7 +1568,7 @@ function createProcessCommand() {
1220
1568
  })
1221
1569
  );
1222
1570
  command.addCommand(
1223
- new Command6("resize").description("Resize an image to exact dimensions").requiredOption("--input <path>", "Input image (file path or URL)").requiredOption("--width <n>", "Target width").requiredOption("--height <n>", "Target height").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1571
+ new Command7("resize").description("Resize an image to exact dimensions").requiredOption("--input <path>", "Input image (file path or URL)").requiredOption("--width <n>", "Target width").requiredOption("--height <n>", "Target height").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1224
1572
  try {
1225
1573
  const ctx = createContext(this);
1226
1574
  const data = await ctx.client.process({
@@ -1236,7 +1584,7 @@ function createProcessCommand() {
1236
1584
  })
1237
1585
  );
1238
1586
  command.addCommand(
1239
- new Command6("compose").description("Compose multiple images into a sprite sheet").requiredOption("--input <paths...>", "Input images (files or URLs)").option("--direction <dir>", "Layout: horizontal, vertical, grid", "horizontal").option("--columns <n>", "Columns for grid layout").option("--padding <n>", "Padding between frames in px", "0").option("--frame-width <n>", "Normalize each frame to this width").option("--frame-height <n>", "Normalize each frame to this height").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1587
+ new Command7("compose").description("Compose multiple images into a sprite sheet").requiredOption("--input <paths...>", "Input images (files or URLs)").option("--direction <dir>", "Layout: horizontal, vertical, grid", "horizontal").option("--columns <n>", "Columns for grid layout").option("--padding <n>", "Padding between frames in px", "0").option("--frame-width <n>", "Normalize each frame to this width").option("--frame-height <n>", "Normalize each frame to this height").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1240
1588
  try {
1241
1589
  const ctx = createContext(this);
1242
1590
  const inputs = Array.isArray(options.input) ? options.input : [options.input];
@@ -1260,7 +1608,7 @@ function createProcessCommand() {
1260
1608
  })
1261
1609
  );
1262
1610
  command.addCommand(
1263
- new Command6("remove-bg").description("Remove background from image(s)").requiredOption("--input <paths...>", "Input images (files or URLs)").option("--bg-color <color>", "Background color hint for fallback (e.g. white, black)").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1611
+ new Command7("remove-bg").description("Remove background from image(s)").requiredOption("--input <paths...>", "Input images (files or URLs)").option("--bg-color <color>", "Background color hint for fallback (e.g. white, black)").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1264
1612
  try {
1265
1613
  const ctx = createContext(this);
1266
1614
  const inputs = Array.isArray(options.input) ? options.input : [options.input];
@@ -1284,7 +1632,7 @@ function createProcessCommand() {
1284
1632
  // src/commands/process3d.ts
1285
1633
  import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
1286
1634
  import { join as join4 } from "path";
1287
- import { Command as Command7 } from "commander";
1635
+ import { Command as Command8 } from "commander";
1288
1636
  function infer3dExtension2(format) {
1289
1637
  const map = {
1290
1638
  fbx: "fbx",
@@ -1335,9 +1683,9 @@ async function saveProcess3dOutput(data, operation, outputDir, format) {
1335
1683
  return filePath;
1336
1684
  }
1337
1685
  function createProcess3dCommand() {
1338
- const command = new Command7("process3d").description("3D model post-processing via Meshy AI");
1686
+ const command = new Command8("process3d").description("3D model post-processing via Meshy AI");
1339
1687
  command.addCommand(
1340
- new Command7("remesh").description("Remesh a model and optionally change format or polygon count").option("--task-id <id>", "Meshy task ID").option("--model-url <url>", "Model URL to remesh without an existing task").requiredOption("--format <fmt>", "Target format: glb, fbx, obj, usdz, stl, 3mf").option("--polycount <n>", "Target polygon count").option("--topology <type>", "Topology type: triangle or quad").option("--auto-size", "Estimate real-world size automatically").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1688
+ new Command8("remesh").description("Remesh a model and optionally change format or polygon count").option("--task-id <id>", "Meshy task ID").option("--model-url <url>", "Model URL to remesh without an existing task").requiredOption("--format <fmt>", "Target format: glb, fbx, obj, usdz, stl, 3mf").option("--polycount <n>", "Target polygon count").option("--topology <type>", "Topology type: triangle or quad").option("--auto-size", "Estimate real-world size automatically").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1341
1689
  try {
1342
1690
  if (!options.taskId && !options.modelUrl) {
1343
1691
  throw new Error("Either --task-id or --model-url is required");
@@ -1364,7 +1712,7 @@ function createProcess3dCommand() {
1364
1712
  })
1365
1713
  );
1366
1714
  command.addCommand(
1367
- new Command7("retexture").description("Regenerate textures for an existing Meshy model").requiredOption("--task-id <id>", "Meshy task ID").option("--prompt <text>", "Text style prompt for the new material pass").option("--style-image <input>", "Texture style reference image URL or local file path").option("--pbr", "Enable PBR materials").option("--hd-texture", "Request 4K texture output").option("--ai-model <name>", "Meshy model: meshy-5, meshy-6, latest").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1715
+ new Command8("retexture").description("Regenerate textures for an existing Meshy model").requiredOption("--task-id <id>", "Meshy task ID").option("--prompt <text>", "Text style prompt for the new material pass").option("--style-image <input>", "Texture style reference image URL or local file path").option("--pbr", "Enable PBR materials").option("--hd-texture", "Request 4K texture output").option("--ai-model <name>", "Meshy model: meshy-5, meshy-6, latest").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1368
1716
  try {
1369
1717
  const ctx = createContext(this);
1370
1718
  const params = {};
@@ -1387,7 +1735,7 @@ function createProcess3dCommand() {
1387
1735
  })
1388
1736
  );
1389
1737
  command.addCommand(
1390
- new Command7("rig").description("Rig a Meshy model for character animation").option("--task-id <id>", "Meshy task ID").option("--height <meters>", "Estimated character height in meters").option("--model-url <url>", "Model URL to rig without an existing task").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1738
+ new Command8("rig").description("Rig a Meshy model for character animation").option("--task-id <id>", "Meshy task ID").option("--height <meters>", "Estimated character height in meters").option("--model-url <url>", "Model URL to rig without an existing task").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1391
1739
  try {
1392
1740
  if (!options.taskId && !options.modelUrl) {
1393
1741
  throw new Error("Either --task-id or --model-url is required");
@@ -1410,7 +1758,7 @@ function createProcess3dCommand() {
1410
1758
  })
1411
1759
  );
1412
1760
  command.addCommand(
1413
- new Command7("animate").description("Apply a preset animation to a rigged Meshy character").requiredOption("--task-id <id>", "Meshy rigging task ID").requiredOption("--action-id <n>", "Animation preset ID (see docs for full list)").option("--fps <n>", "Target frame rate: 24, 25, 30, or 60").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1761
+ new Command8("animate").description("Apply a preset animation to a rigged Meshy character").requiredOption("--task-id <id>", "Meshy rigging task ID").requiredOption("--action-id <n>", "Animation preset ID (see docs for full list)").option("--fps <n>", "Target frame rate: 24, 25, 30, or 60").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1414
1762
  try {
1415
1763
  const ctx = createContext(this);
1416
1764
  const params = {
@@ -1433,7 +1781,7 @@ function createProcess3dCommand() {
1433
1781
  })
1434
1782
  );
1435
1783
  command.addCommand(
1436
- new Command7("refine").description("Refine a Meshy preview model into a higher quality result").requiredOption("--task-id <id>", "Meshy preview task ID").option("--pbr", "Enable PBR materials").option("--hd-texture", "Request 4K texture output").option("--texture-prompt <text>", "Optional texture prompt for the refinement pass").option("--ai-model <name>", "Meshy model: meshy-5, meshy-6, latest").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1784
+ new Command8("refine").description("Refine a Meshy preview model into a higher quality result").requiredOption("--task-id <id>", "Meshy preview task ID").option("--pbr", "Enable PBR materials").option("--hd-texture", "Request 4K texture output").option("--texture-prompt <text>", "Optional texture prompt for the refinement pass").option("--ai-model <name>", "Meshy model: meshy-5, meshy-6, latest").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1437
1785
  try {
1438
1786
  const ctx = createContext(this);
1439
1787
  const params = {};
@@ -1458,11 +1806,11 @@ function createProcess3dCommand() {
1458
1806
  }
1459
1807
 
1460
1808
  // src/commands/provider.ts
1461
- import { Command as Command8 } from "commander";
1809
+ import { Command as Command9 } from "commander";
1462
1810
  function createProviderCommand() {
1463
- const command = new Command8("provider").description("Provider management");
1811
+ const command = new Command9("provider").description("Provider management");
1464
1812
  command.addCommand(
1465
- new Command8("list").description("List available providers").action(async function() {
1813
+ new Command9("list").description("List available providers").action(async function() {
1466
1814
  try {
1467
1815
  const ctx = createContext(this);
1468
1816
  const data = await ctx.client.providers.list();
@@ -1473,7 +1821,7 @@ function createProviderCommand() {
1473
1821
  })
1474
1822
  );
1475
1823
  command.addCommand(
1476
- new Command8("health").description("Check provider health").argument("[name]", "Specific provider name").action(async function(name) {
1824
+ new Command9("health").description("Check provider health").argument("[name]", "Specific provider name").action(async function(name) {
1477
1825
  try {
1478
1826
  const ctx = createContext(this);
1479
1827
  const data = name ? await ctx.client.providers.health(name) : await ctx.client.providers.health();
@@ -1487,14 +1835,14 @@ function createProviderCommand() {
1487
1835
  }
1488
1836
 
1489
1837
  // src/commands/upload.ts
1490
- import { readFile } from "fs/promises";
1838
+ import { readFile as readFile3 } from "fs/promises";
1491
1839
  import { basename } from "path";
1492
- import { AssetForgeError as AssetForgeError3 } from "@doufunao123/assetforge-sdk";
1493
- import { Command as Command9 } from "commander";
1840
+ import { AssetForgeError as AssetForgeError6 } from "@doufunao123/assetforge-sdk";
1841
+ import { Command as Command10 } from "commander";
1494
1842
  function createUploadCommand() {
1495
- const command = new Command9("upload").description("Upload and manage assets");
1843
+ const command = new Command10("upload").description("Upload and manage assets");
1496
1844
  command.addCommand(
1497
- new Command9("file").description("Upload a file and get a public URL").argument("<path>", "Path to file to upload").action(async function(filePath) {
1845
+ new Command10("file").description("Upload a file and get a public URL").argument("<path>", "Path to file to upload").action(async function(filePath) {
1498
1846
  const ctx = createContext(this);
1499
1847
  try {
1500
1848
  const content = await readLocalFile(filePath);
@@ -1506,7 +1854,7 @@ function createUploadCommand() {
1506
1854
  })
1507
1855
  );
1508
1856
  command.addCommand(
1509
- new Command9("list").description("List uploaded assets").action(async function() {
1857
+ new Command10("list").description("List uploaded assets").action(async function() {
1510
1858
  const ctx = createContext(this);
1511
1859
  try {
1512
1860
  const data = await ctx.client.assets.list();
@@ -1517,7 +1865,7 @@ function createUploadCommand() {
1517
1865
  })
1518
1866
  );
1519
1867
  command.addCommand(
1520
- new Command9("delete").description("Delete an uploaded asset (admin only)").argument("<filename>", "Filename to delete").action(async function(filename) {
1868
+ new Command10("delete").description("Delete an uploaded asset (admin only)").argument("<filename>", "Filename to delete").action(async function(filename) {
1521
1869
  const ctx = createContext(this);
1522
1870
  try {
1523
1871
  const data = await ctx.client.assets.delete(filename);
@@ -1531,9 +1879,9 @@ function createUploadCommand() {
1531
1879
  }
1532
1880
  async function readLocalFile(filePath) {
1533
1881
  try {
1534
- return await readFile(filePath);
1882
+ return await readFile3(filePath);
1535
1883
  } catch (error2) {
1536
- throw new AssetForgeError3(
1884
+ throw new AssetForgeError6(
1537
1885
  `Failed to read file ${filePath}: ${error2 instanceof Error ? error2.message : String(error2)}`,
1538
1886
  { code: "CONFIG_ERROR" }
1539
1887
  );
@@ -1543,11 +1891,11 @@ async function readLocalFile(filePath) {
1543
1891
  // src/commands/voice.ts
1544
1892
  import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
1545
1893
  import { dirname as dirname3, extname as extname2 } from "path";
1546
- import { Command as Command10 } from "commander";
1894
+ import { Command as Command11 } from "commander";
1547
1895
  function createVoiceCommand() {
1548
- const command = new Command10("voice").description("Design, clone, list, and delete voices");
1896
+ const command = new Command11("voice").description("Design, clone, list, and delete voices");
1549
1897
  command.addCommand(
1550
- new Command10("design").description("Generate a MiMo voice from a text description").requiredOption("--voice-prompt <text>", "Voice description / style prompt").requiredOption("--preview-text <text>", "Text to synthesize for preview").option("--style <text>", "Additional director/style instruction").option("--name <name>", "Save generated voice with this name").option("--save-as <name>", "Alias for --name").option("--output <path>", "Write preview WAV to this path").action(async function(options) {
1898
+ new Command11("design").description("Generate a MiMo voice from a text description").requiredOption("--voice-prompt <text>", "Voice description / style prompt").requiredOption("--preview-text <text>", "Text to synthesize for preview").option("--style <text>", "Additional director/style instruction").option("--name <name>", "Save generated voice with this name").option("--save-as <name>", "Alias for --name").option("--output <path>", "Write preview WAV to this path").action(async function(options) {
1551
1899
  const ctx = createContext(this);
1552
1900
  try {
1553
1901
  const request = {
@@ -1567,7 +1915,7 @@ function createVoiceCommand() {
1567
1915
  })
1568
1916
  );
1569
1917
  command.addCommand(
1570
- new Command10("clone").description("Clone a MiMo voice from an mp3/wav sample").requiredOption("--audio <path-or-data-url>", "Voice sample mp3/wav file or data URL").requiredOption("--preview-text <text>", "Text to synthesize for preview").option("--audio-mime <mime>", "Audio MIME type when --audio is raw base64").option("--style <text>", "Director/style instruction").option("--name <name>", "Save cloned voice with this name").option("--save-as <name>", "Alias for --name").option("--output <path>", "Write preview WAV to this path").action(async function(options) {
1918
+ new Command11("clone").description("Clone a MiMo voice from an mp3/wav sample").requiredOption("--audio <path-or-data-url>", "Voice sample mp3/wav file or data URL").requiredOption("--preview-text <text>", "Text to synthesize for preview").option("--audio-mime <mime>", "Audio MIME type when --audio is raw base64").option("--style <text>", "Director/style instruction").option("--name <name>", "Save cloned voice with this name").option("--save-as <name>", "Alias for --name").option("--output <path>", "Write preview WAV to this path").action(async function(options) {
1571
1919
  const ctx = createContext(this);
1572
1920
  try {
1573
1921
  const sample = readVoiceSample(options.audio, options.audioMime);
@@ -1588,7 +1936,7 @@ function createVoiceCommand() {
1588
1936
  })
1589
1937
  );
1590
1938
  command.addCommand(
1591
- new Command10("list").description("List saved voices").option("--type <type>", "Voice type: vc or vd").action(async function(options) {
1939
+ new Command11("list").description("List saved voices").option("--type <type>", "Voice type: vc or vd").action(async function(options) {
1592
1940
  const ctx = createContext(this);
1593
1941
  try {
1594
1942
  const data = await ctx.client.voice.list({ type: options.type });
@@ -1599,7 +1947,7 @@ function createVoiceCommand() {
1599
1947
  })
1600
1948
  );
1601
1949
  command.addCommand(
1602
- new Command10("delete").description("Delete a saved voice").argument("<voice-id>", "Voice ID").option("--type <type>", "Voice type: vc or vd").action(async function(voiceId, options) {
1950
+ new Command11("delete").description("Delete a saved voice").argument("<voice-id>", "Voice ID").option("--type <type>", "Voice type: vc or vd").action(async function(voiceId, options) {
1603
1951
  const ctx = createContext(this);
1604
1952
  try {
1605
1953
  const data = await ctx.client.voice.delete(voiceId, { type: options.type });
@@ -1611,17 +1959,17 @@ function createVoiceCommand() {
1611
1959
  );
1612
1960
  return command;
1613
1961
  }
1614
- function readVoiceSample(input, audioMime) {
1615
- if (input.startsWith("data:")) {
1616
- return { sample_data_url: input };
1962
+ function readVoiceSample(input2, audioMime) {
1963
+ if (input2.startsWith("data:")) {
1964
+ return { sample_data_url: input2 };
1617
1965
  }
1618
- if (existsSync6(input)) {
1966
+ if (existsSync6(input2)) {
1619
1967
  return {
1620
- audio_base64: readFileSync5(input).toString("base64"),
1621
- audio_mime: audioMime ?? inferAudioMime(input)
1968
+ audio_base64: readFileSync5(input2).toString("base64"),
1969
+ audio_mime: audioMime ?? inferAudioMime(input2)
1622
1970
  };
1623
1971
  }
1624
- return { audio_base64: input, audio_mime: audioMime ?? "audio/wav" };
1972
+ return { audio_base64: input2, audio_mime: audioMime ?? "audio/wav" };
1625
1973
  }
1626
1974
  function inferAudioMime(filePath) {
1627
1975
  const ext = extname2(filePath).toLowerCase();
@@ -1647,13 +1995,14 @@ function stripDataUri2(data) {
1647
1995
  }
1648
1996
 
1649
1997
  // src/index.ts
1650
- var program = new Command11().name("asset-gateway").description("Universal asset generation gateway CLI").version(CLI_VERSION).option(
1998
+ var program = new Command12().name("asset-gateway").description("Universal asset generation gateway CLI").version(CLI_VERSION).option(
1651
1999
  "--gateway-url <url>",
1652
2000
  `Gateway URL (default: $ASSET_GATEWAY_URL, auth config, or ${DEFAULT_GATEWAY_URL})`
1653
2001
  ).option("--token <token>", "API token for authentication").option("--human", "Human-readable output instead of JSON").option("--fields <fields>", "Comma-separated list of output fields");
1654
2002
  program.addCommand(createAuthCommand());
1655
2003
  program.addCommand(createGenerateCommand());
1656
2004
  program.addCommand(createLibraryCommand());
2005
+ program.addCommand(createPackCommand());
1657
2006
  program.addCommand(createProcessCommand());
1658
2007
  program.addCommand(createProcess3dCommand());
1659
2008
  program.addCommand(createProviderCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doufunao123/asset-gateway",
3
- "version": "0.22.0",
3
+ "version": "0.22.2",
4
4
  "description": "Universal asset generation gateway CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,7 +27,7 @@
27
27
  "node": ">=20"
28
28
  },
29
29
  "dependencies": {
30
- "@doufunao123/assetforge-sdk": "^0.6.0",
30
+ "@doufunao123/assetforge-sdk": "^0.8.0",
31
31
  "commander": "^13.1.0"
32
32
  },
33
33
  "devDependencies": {