@doufunao123/asset-gateway 0.16.1 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +140 -169
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -415,12 +415,11 @@ var SCHEMAS = {
415
415
  "--output-dir": { type: "string", default: "." }
416
416
  }
417
417
  },
418
- audio: {
419
- description: "Generate audio from a text prompt",
418
+ sfx: {
419
+ description: "Generate sound effects (impacts, footsteps, UI sounds, ambience)",
420
420
  params: {
421
421
  "--prompt": { type: "string", required: true },
422
- "--type": { type: "string", description: "bgm | sfx" },
423
- "--duration": { type: "number", description: "Seconds" },
422
+ "--duration": { type: "number", required: true, description: "Duration in seconds (1-5s for short SFX, 5-15s for ambience, max 30s)" },
424
423
  "--output-dir": { type: "string", default: "." }
425
424
  }
426
425
  },
@@ -435,10 +434,11 @@ var SCHEMAS = {
435
434
  }
436
435
  },
437
436
  tts: {
438
- description: "Text-to-speech via MOSS-TTS-Nano (self-hosted)",
437
+ description: "Text-to-speech via Gemini 3.1 Flash TTS",
439
438
  params: {
440
439
  "--prompt": { type: "string", required: true },
441
- "--input": { type: "string", description: "Reference audio file for voice cloning (local path or URL)" },
440
+ "--voice": { type: "string", description: "Prebuilt voice name (default: Kore)" },
441
+ "--speakers": { type: "string", description: `Multi-speaker config JSON, e.g. '{"Name1":"Puck","Name2":"Kore"}'` },
442
442
  "--output-dir": { type: "string", default: "." }
443
443
  }
444
444
  },
@@ -650,22 +650,6 @@ var SCHEMAS = {
650
650
  }
651
651
  }
652
652
  },
653
- voice: {
654
- description: "Qwen3-TTS voice designs (design / list / delete)",
655
- subcommands: {
656
- design: {
657
- description: "Design voice from text",
658
- params: {
659
- "--prompt": { type: "string", required: true },
660
- "--preview-text": { type: "string", required: true },
661
- "--name": { type: "string", required: true },
662
- "--target-model": { type: "string" }
663
- }
664
- },
665
- list: { description: "List designed voices", params: { "--type": { type: "string" } } },
666
- delete: { description: "Delete designed voice", params: { "<voice-id>": { type: "string", required: true }, "--type": { type: "string" } } }
667
- }
668
- },
669
653
  upload: {
670
654
  description: "Upload and list gateway assets",
671
655
  subcommands: {
@@ -739,7 +723,7 @@ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as rea
739
723
  import { dirname as dirname2, extname, join as join2 } from "path";
740
724
  import { Command as Command3 } from "commander";
741
725
  function inferExtension(assetType) {
742
- const map = { image: "png", audio: "mp3", music: "mp3", tts: "mp3", video: "mp4", model3d: "glb", text: "txt", sprite: "png", world: "spz" };
726
+ const map = { image: "png", audio: "mp3", sfx: "mp3", music: "mp3", tts: "mp3", video: "mp4", model3d: "glb", text: "txt", sprite: "png", world: "spz" };
743
727
  return map[assetType] ?? "bin";
744
728
  }
745
729
  function inferExtFromResult(result) {
@@ -909,23 +893,23 @@ function createGenerateCommand() {
909
893
  })
910
894
  );
911
895
  command.addCommand(
912
- new Command3("audio").description("Generate audio from a text prompt").requiredOption("--prompt <text>", "Audio description prompt").option("--type <type>", "Audio type: bgm or sfx").option("--duration <seconds>", "Duration in seconds").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
896
+ new Command3("sfx").description("Generate sound effects (short audio clips: impacts, footsteps, UI sounds, ambience)").requiredOption("--prompt <text>", "Sound effect description").requiredOption("--duration <seconds>", "Duration in seconds (1-5s for short SFX, 5-15s for ambience, max 30s)").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
913
897
  try {
914
898
  const ctx = createContext(this);
899
+ const params = {
900
+ duration_seconds: Number(options.duration)
901
+ };
915
902
  const body = {
916
903
  asset_type: "audio",
917
- prompt: options.prompt
904
+ prompt: options.prompt,
905
+ params
918
906
  };
919
- const params = {};
920
- if (options.type) params.audio_type = options.type;
921
- if (options.duration) params.duration_seconds = Number(options.duration);
922
- if (Object.keys(params).length > 0) body.params = params;
923
907
  const data = await ctx.client.post("/api/generate", body);
924
908
  const localPath = await saveOutput(data, "audio", options.outputDir);
925
909
  if (localPath) data.local_path = localPath;
926
- printSuccess("generate.audio", data, ctx);
910
+ printSuccess("generate.sfx", data, ctx);
927
911
  } catch (error2) {
928
- printError("generate.audio", error2);
912
+ printError("generate.sfx", error2);
929
913
  }
930
914
  })
931
915
  );
@@ -955,23 +939,17 @@ function createGenerateCommand() {
955
939
  })
956
940
  );
957
941
  command.addCommand(
958
- new Command3("tts").description("Text-to-speech via MOSS-TTS-Nano (self-hosted)").requiredOption("--prompt <text>", "Text to synthesize").option("--input <path>", "Reference audio file for voice cloning (local path or URL)").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
942
+ new Command3("tts").description("Text-to-speech via Gemini 3.1 Flash TTS").requiredOption("--prompt <text>", "Text to synthesize").option("--voice <name>", "Prebuilt voice name (default: Kore)").option("--speakers <json>", `Multi-speaker config JSON, e.g. '{"Name1":"Puck","Name2":"Kore"}'`).option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
959
943
  try {
960
944
  const ctx = createContext(this);
961
945
  const body = {
962
946
  asset_type: "tts",
963
947
  prompt: options.prompt
964
948
  };
965
- if (options.input) {
966
- if (existsSync3(options.input)) {
967
- const ext = extname(options.input).toLowerCase();
968
- const mime = ext === ".wav" ? "audio/wav" : ext === ".mp3" ? "audio/mpeg" : "audio/wav";
969
- const b64 = readFileSync2(options.input).toString("base64");
970
- body.input_file = `data:${mime};base64,${b64}`;
971
- } else {
972
- body.input_file = options.input;
973
- }
974
- }
949
+ const params = {};
950
+ if (options.voice) params.voice = options.voice;
951
+ if (options.speakers) params.speakers = JSON.parse(options.speakers);
952
+ if (Object.keys(params).length > 0) body.params = params;
975
953
  const data = await ctx.client.post("/api/generate", body);
976
954
  const localPath = await saveOutput(data, "tts", options.outputDir);
977
955
  if (localPath) data.local_path = localPath;
@@ -1143,11 +1121,101 @@ function createJobCommand() {
1143
1121
  return command;
1144
1122
  }
1145
1123
 
1124
+ // src/commands/library.ts
1125
+ import { Command as Command5 } from "commander";
1126
+ function createLibraryCommand() {
1127
+ const command = new Command5("library").description(
1128
+ "Search and manage the asset library"
1129
+ );
1130
+ command.addCommand(
1131
+ 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) {
1132
+ const ctx = createContext(this);
1133
+ const opts = this.opts();
1134
+ try {
1135
+ const params = new URLSearchParams();
1136
+ if (query) params.set("q", query);
1137
+ if (opts.type) params.set("type", opts.type);
1138
+ if (opts.tags) params.set("tags", opts.tags);
1139
+ if (opts.source) params.set("source", opts.source);
1140
+ params.set("limit", opts.limit);
1141
+ params.set("offset", opts.offset);
1142
+ const data = await ctx.client.get(`/api/library/search?${params}`);
1143
+ printSuccess("library.search", data, ctx);
1144
+ } catch (error2) {
1145
+ printError("library.search", error2, ctx.human);
1146
+ }
1147
+ })
1148
+ );
1149
+ command.addCommand(
1150
+ 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() {
1151
+ const ctx = createContext(this);
1152
+ const opts = this.opts();
1153
+ try {
1154
+ const body = {
1155
+ asset_type: opts.type,
1156
+ name: opts.name,
1157
+ file_url: opts.url,
1158
+ source: opts.source
1159
+ };
1160
+ if (opts.description) body.description = opts.description;
1161
+ if (opts.tags)
1162
+ body.tags = opts.tags.split(",").map((t) => t.trim());
1163
+ if (opts.duration)
1164
+ body.duration_seconds = parseFloat(opts.duration);
1165
+ const data = await ctx.client.post("/api/library", body);
1166
+ printSuccess("library.add", data, ctx);
1167
+ } catch (error2) {
1168
+ printError("library.add", error2, ctx.human);
1169
+ }
1170
+ })
1171
+ );
1172
+ command.addCommand(
1173
+ new Command5("get").description("Get a library item by ID").argument("<id>", "Library item ID").action(async function(id) {
1174
+ const ctx = createContext(this);
1175
+ try {
1176
+ const data = await ctx.client.get(`/api/library/${encodeURIComponent(id)}`);
1177
+ printSuccess("library.get", data, ctx);
1178
+ } catch (error2) {
1179
+ printError("library.get", error2, ctx.human);
1180
+ }
1181
+ })
1182
+ );
1183
+ command.addCommand(
1184
+ new Command5("delete").description("Delete a library item (admin only)").argument("<id>", "Library item ID").action(async function(id) {
1185
+ const ctx = createContext(this);
1186
+ try {
1187
+ const data = await ctx.client.delete(`/api/library/${encodeURIComponent(id)}`);
1188
+ printSuccess("library.delete", data, ctx);
1189
+ } catch (error2) {
1190
+ printError("library.delete", error2, ctx.human);
1191
+ }
1192
+ })
1193
+ );
1194
+ command.addCommand(
1195
+ new Command5("catalog-jobs").description("Catalog completed generation jobs into the library (admin)").option("-t, --type <type>", "Filter jobs by asset type").option("--provider <id>", "Filter jobs by provider ID").option("--after <date>", "Only catalog jobs after this date").option("--dry-run", "Just count, don't actually catalog").action(async function() {
1196
+ const ctx = createContext(this);
1197
+ const opts = this.opts();
1198
+ try {
1199
+ const body = {};
1200
+ if (opts.type) body.asset_type = opts.type;
1201
+ if (opts.provider) body.provider_id = opts.provider;
1202
+ if (opts.after) body.after = opts.after;
1203
+ if (opts.dryRun) body.dry_run = true;
1204
+ const data = await ctx.client.post("/api/library/catalog-jobs", body);
1205
+ printSuccess("library.catalog_jobs", data, ctx);
1206
+ } catch (error2) {
1207
+ printError("library.catalog_jobs", error2, ctx.human);
1208
+ }
1209
+ })
1210
+ );
1211
+ return command;
1212
+ }
1213
+
1146
1214
  // src/commands/process.ts
1147
1215
  import { mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
1148
1216
  import { existsSync as existsSync4 } from "fs";
1149
1217
  import { join as join3 } from "path";
1150
- import { Command as Command5 } from "commander";
1218
+ import { Command as Command6 } from "commander";
1151
1219
  function readInputAsBase64(input) {
1152
1220
  if (existsSync4(input)) {
1153
1221
  const bytes = readFileSync3(input);
@@ -1181,9 +1249,9 @@ function saveProcessOutput(data, outputDir) {
1181
1249
  return filePath;
1182
1250
  }
1183
1251
  function createProcessCommand() {
1184
- const command = new Command5("process").description("Post-process images and video (crop, resize, compose, extract-frames, remove-bg)");
1252
+ const command = new Command6("process").description("Post-process images and video (crop, resize, compose, extract-frames, remove-bg)");
1185
1253
  command.addCommand(
1186
- new Command5("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) {
1254
+ 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) {
1187
1255
  try {
1188
1256
  const ctx = createContext(this);
1189
1257
  const data = await ctx.client.post("/api/process", {
@@ -1199,7 +1267,7 @@ function createProcessCommand() {
1199
1267
  })
1200
1268
  );
1201
1269
  command.addCommand(
1202
- new Command5("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) {
1270
+ 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) {
1203
1271
  try {
1204
1272
  const ctx = createContext(this);
1205
1273
  const data = await ctx.client.post("/api/process", {
@@ -1215,7 +1283,7 @@ function createProcessCommand() {
1215
1283
  })
1216
1284
  );
1217
1285
  command.addCommand(
1218
- new Command5("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) {
1286
+ 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) {
1219
1287
  try {
1220
1288
  const ctx = createContext(this);
1221
1289
  const inputs = Array.isArray(options.input) ? options.input : [options.input];
@@ -1239,7 +1307,7 @@ function createProcessCommand() {
1239
1307
  })
1240
1308
  );
1241
1309
  command.addCommand(
1242
- new Command5("extract-frames").description("Extract evenly-spaced frames from a video using ffmpeg").requiredOption("--input <path>", "Input video (file path or URL)").option("--count <n>", "Number of frames to extract", "8").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1310
+ new Command6("extract-frames").description("Extract evenly-spaced frames from a video using ffmpeg").requiredOption("--input <path>", "Input video (file path or URL)").option("--count <n>", "Number of frames to extract", "8").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1243
1311
  try {
1244
1312
  const ctx = createContext(this);
1245
1313
  const data = await ctx.client.post("/api/process", {
@@ -1255,7 +1323,7 @@ function createProcessCommand() {
1255
1323
  })
1256
1324
  );
1257
1325
  command.addCommand(
1258
- new Command5("remove-bg").description("Remove background from image(s) using rembg or ImageMagick fallback").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) {
1326
+ new Command6("remove-bg").description("Remove background from image(s) using rembg or ImageMagick fallback").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) {
1259
1327
  try {
1260
1328
  const ctx = createContext(this);
1261
1329
  const inputs = Array.isArray(options.input) ? options.input : [options.input];
@@ -1279,7 +1347,7 @@ function createProcessCommand() {
1279
1347
  // src/commands/process3d.ts
1280
1348
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
1281
1349
  import { join as join4 } from "path";
1282
- import { Command as Command6 } from "commander";
1350
+ import { Command as Command7 } from "commander";
1283
1351
  function infer3dExtension(format) {
1284
1352
  const map = {
1285
1353
  fbx: "fbx",
@@ -1349,9 +1417,9 @@ function isRecord2(value) {
1349
1417
  return typeof value === "object" && value !== null && !Array.isArray(value);
1350
1418
  }
1351
1419
  function createProcess3dCommand() {
1352
- const command = new Command6("process3d").description("3D model post-processing via Tripo pipeline");
1420
+ const command = new Command7("process3d").description("3D model post-processing via Tripo pipeline");
1353
1421
  command.addCommand(
1354
- new Command6("convert").description("Convert 3D model format (FBX/USDZ/OBJ/STL/GLTF/3MF)").requiredOption("--task-id <id>", "Tripo task ID from generate model").requiredOption("--format <fmt>", "Target format: FBX, USDZ, OBJ, STL, GLTF, 3MF").option("--quad", "Enable quad remeshing").option("--face-limit <n>", "Max face count").option("--pack-uv", "Pack UVs during export").option("--bake", "Bake textures during export").option("--texture-format <fmt>", "Texture export format override").option("--force-symmetry", "Force symmetry during conversion").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1422
+ new Command7("convert").description("Convert 3D model format (FBX/USDZ/OBJ/STL/GLTF/3MF)").requiredOption("--task-id <id>", "Tripo task ID from generate model").requiredOption("--format <fmt>", "Target format: FBX, USDZ, OBJ, STL, GLTF, 3MF").option("--quad", "Enable quad remeshing").option("--face-limit <n>", "Max face count").option("--pack-uv", "Pack UVs during export").option("--bake", "Bake textures during export").option("--texture-format <fmt>", "Texture export format override").option("--force-symmetry", "Force symmetry during conversion").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1355
1423
  try {
1356
1424
  const ctx = createContext(this);
1357
1425
  const params = {
@@ -1377,7 +1445,7 @@ function createProcess3dCommand() {
1377
1445
  })
1378
1446
  );
1379
1447
  command.addCommand(
1380
- new Command6("texture").description("Re-texture a 3D model with new materials").requiredOption("--task-id <id>", "Tripo task ID").option("--prompt <text>", "Texture description prompt").option("--style-image <input>", "Texture style reference image URL or local file path").option("--pbr", "Enable PBR materials").option("--quality <q>", "Texture quality: standard or detailed").option("--texture-alignment <mode>", "Tripo texture alignment mode").option("--bake", "Bake textures during re-texturing").option("--texture-version <version>", "Tripo texture model version override").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1448
+ new Command7("texture").description("Re-texture a 3D model with new materials").requiredOption("--task-id <id>", "Tripo task ID").option("--prompt <text>", "Texture description prompt").option("--style-image <input>", "Texture style reference image URL or local file path").option("--pbr", "Enable PBR materials").option("--quality <q>", "Texture quality: standard or detailed").option("--texture-alignment <mode>", "Tripo texture alignment mode").option("--bake", "Bake textures during re-texturing").option("--texture-version <version>", "Tripo texture model version override").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1381
1449
  try {
1382
1450
  const ctx = createContext(this);
1383
1451
  const params = {};
@@ -1402,7 +1470,7 @@ function createProcess3dCommand() {
1402
1470
  })
1403
1471
  );
1404
1472
  command.addCommand(
1405
- new Command6("rig").description("Auto-rig a 3D model (add skeleton for animation)").requiredOption("--task-id <id>", "Tripo task ID").option("--format <fmt>", "Output format: glb or fbx", "glb").option("--spec <spec>", "Rig spec: mixamo or tripo", "mixamo").option("--rig-type <type>", "Rig type override passed through to Tripo").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1473
+ new Command7("rig").description("Auto-rig a 3D model (add skeleton for animation)").requiredOption("--task-id <id>", "Tripo task ID").option("--format <fmt>", "Output format: glb or fbx", "glb").option("--spec <spec>", "Rig spec: mixamo or tripo", "mixamo").option("--rig-type <type>", "Rig type override passed through to Tripo").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1406
1474
  try {
1407
1475
  const ctx = createContext(this);
1408
1476
  const params = {
@@ -1424,7 +1492,7 @@ function createProcess3dCommand() {
1424
1492
  })
1425
1493
  );
1426
1494
  command.addCommand(
1427
- new Command6("animate").description("Apply preset animation to a rigged model").requiredOption("--task-id <id>", "Tripo task ID (from rig step)").requiredOption("--animation <preset>", "Animation preset (e.g. preset:walk, preset:idle, preset:run)").option("--format <fmt>", "Output format: glb or fbx", "glb").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1495
+ new Command7("animate").description("Apply preset animation to a rigged model").requiredOption("--task-id <id>", "Tripo task ID (from rig step)").requiredOption("--animation <preset>", "Animation preset (e.g. preset:walk, preset:idle, preset:run)").option("--format <fmt>", "Output format: glb or fbx", "glb").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1428
1496
  try {
1429
1497
  const ctx = createContext(this);
1430
1498
  const data = await ctx.client.post("/api/process3d", {
@@ -1444,7 +1512,7 @@ function createProcess3dCommand() {
1444
1512
  })
1445
1513
  );
1446
1514
  command.addCommand(
1447
- new Command6("render-sprites").description("Render animated 3D model to 2D sprite frames via Blender").requiredOption("--task-id <id>", "Tripo task ID").option("--frame-count <n>", "Number of frames", "8").option("--resolution <n>", "Frame resolution in pixels", "64").option("--camera-angle <angle>", "Camera: front, side, iso, 3/4, top", "front").option("--directions <n>", "Rotation directions: 1, 4, 8", "1").option("--output-dir <dir>", "Output directory", ".").action(async function(options) {
1515
+ new Command7("render-sprites").description("Render animated 3D model to 2D sprite frames via Blender").requiredOption("--task-id <id>", "Tripo task ID").option("--frame-count <n>", "Number of frames", "8").option("--resolution <n>", "Frame resolution in pixels", "64").option("--camera-angle <angle>", "Camera: front, side, iso, 3/4, top", "front").option("--directions <n>", "Rotation directions: 1, 4, 8", "1").option("--output-dir <dir>", "Output directory", ".").action(async function(options) {
1448
1516
  try {
1449
1517
  const ctx = createContext(this);
1450
1518
  const data = await ctx.client.post("/api/process3d", {
@@ -1463,7 +1531,7 @@ function createProcess3dCommand() {
1463
1531
  })
1464
1532
  );
1465
1533
  command.addCommand(
1466
- new Command6("reduce").description("Reduce polygon count (high-poly to low-poly)").requiredOption("--task-id <id>", "Tripo task ID").option("--face-limit <n>", "Target face count").option("--quad", "Use quad topology").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1534
+ new Command7("reduce").description("Reduce polygon count (high-poly to low-poly)").requiredOption("--task-id <id>", "Tripo task ID").option("--face-limit <n>", "Target face count").option("--quad", "Use quad topology").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1467
1535
  try {
1468
1536
  const ctx = createContext(this);
1469
1537
  const params = {};
@@ -1483,7 +1551,7 @@ function createProcess3dCommand() {
1483
1551
  })
1484
1552
  );
1485
1553
  command.addCommand(
1486
- new Command6("stylize").description("Apply artistic style to a model").requiredOption("--task-id <id>", "Tripo task ID").requiredOption("--style <style>", "Style: lego, voxel, voronoi, minecraft").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1554
+ new Command7("stylize").description("Apply artistic style to a model").requiredOption("--task-id <id>", "Tripo task ID").requiredOption("--style <style>", "Style: lego, voxel, voronoi, minecraft").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1487
1555
  try {
1488
1556
  const ctx = createContext(this);
1489
1557
  const data = await ctx.client.post("/api/process3d", {
@@ -1502,7 +1570,7 @@ function createProcess3dCommand() {
1502
1570
  })
1503
1571
  );
1504
1572
  command.addCommand(
1505
- new Command6("segment").description("Segment mesh into logical parts").requiredOption("--task-id <id>", "Tripo task ID").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1573
+ new Command7("segment").description("Segment mesh into logical parts").requiredOption("--task-id <id>", "Tripo task ID").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1506
1574
  try {
1507
1575
  const ctx = createContext(this);
1508
1576
  const data = await ctx.client.post("/api/process3d", {
@@ -1519,7 +1587,7 @@ function createProcess3dCommand() {
1519
1587
  })
1520
1588
  );
1521
1589
  command.addCommand(
1522
- new Command6("prerigcheck").description("Check if a model can be rigged").requiredOption("--task-id <id>", "Tripo task ID").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1590
+ new Command7("prerigcheck").description("Check if a model can be rigged").requiredOption("--task-id <id>", "Tripo task ID").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1523
1591
  try {
1524
1592
  const ctx = createContext(this);
1525
1593
  const data = await ctx.client.post("/api/process3d", {
@@ -1536,7 +1604,7 @@ function createProcess3dCommand() {
1536
1604
  })
1537
1605
  );
1538
1606
  command.addCommand(
1539
- new Command6("refine").description("Refine a draft model to higher quality").requiredOption("--task-id <id>", "Tripo task ID").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1607
+ new Command7("refine").description("Refine a draft model to higher quality").requiredOption("--task-id <id>", "Tripo task ID").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1540
1608
  try {
1541
1609
  const ctx = createContext(this);
1542
1610
  const data = await ctx.client.post("/api/process3d", {
@@ -1553,7 +1621,7 @@ function createProcess3dCommand() {
1553
1621
  })
1554
1622
  );
1555
1623
  command.addCommand(
1556
- new Command6("import").description("Import an external 3D model for post-processing").option("--file-url <url>", "URL of the 3D model to import").option("--file-path <path>", "Local path of the 3D model to import").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1624
+ new Command7("import").description("Import an external 3D model for post-processing").option("--file-url <url>", "URL of the 3D model to import").option("--file-path <path>", "Local path of the 3D model to import").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1557
1625
  try {
1558
1626
  const ctx = createContext(this);
1559
1627
  const params = {};
@@ -1579,11 +1647,11 @@ function createProcess3dCommand() {
1579
1647
  }
1580
1648
 
1581
1649
  // src/commands/provider.ts
1582
- import { Command as Command7 } from "commander";
1650
+ import { Command as Command8 } from "commander";
1583
1651
  function createProviderCommand() {
1584
- const command = new Command7("provider").description("Provider management");
1652
+ const command = new Command8("provider").description("Provider management");
1585
1653
  command.addCommand(
1586
- new Command7("list").description("List available providers").action(async function() {
1654
+ new Command8("list").description("List available providers").action(async function() {
1587
1655
  try {
1588
1656
  const ctx = createContext(this);
1589
1657
  const data = await ctx.client.get("/api/providers");
@@ -1594,7 +1662,7 @@ function createProviderCommand() {
1594
1662
  })
1595
1663
  );
1596
1664
  command.addCommand(
1597
- new Command7("health").description("Check provider health").argument("[name]", "Specific provider name").action(async function(name) {
1665
+ new Command8("health").description("Check provider health").argument("[name]", "Specific provider name").action(async function(name) {
1598
1666
  try {
1599
1667
  const ctx = createContext(this);
1600
1668
  const path = name ? `/api/providers/${encodeURIComponent(name)}/health` : "/api/providers/health";
@@ -1609,11 +1677,11 @@ function createProviderCommand() {
1609
1677
  }
1610
1678
 
1611
1679
  // src/commands/upload.ts
1612
- import { Command as Command8 } from "commander";
1680
+ import { Command as Command9 } from "commander";
1613
1681
  function createUploadCommand() {
1614
- const command = new Command8("upload").description("Upload and manage assets");
1682
+ const command = new Command9("upload").description("Upload and manage assets");
1615
1683
  command.addCommand(
1616
- new Command8("file").description("Upload a file and get a public URL").argument("<path>", "Path to file to upload").action(async function(filePath) {
1684
+ new Command9("file").description("Upload a file and get a public URL").argument("<path>", "Path to file to upload").action(async function(filePath) {
1617
1685
  const ctx = createContext(this);
1618
1686
  try {
1619
1687
  const data = await ctx.client.uploadFile(filePath);
@@ -1624,7 +1692,7 @@ function createUploadCommand() {
1624
1692
  })
1625
1693
  );
1626
1694
  command.addCommand(
1627
- new Command8("list").description("List uploaded assets").action(async function() {
1695
+ new Command9("list").description("List uploaded assets").action(async function() {
1628
1696
  const ctx = createContext(this);
1629
1697
  try {
1630
1698
  const data = await ctx.client.get("/api/assets");
@@ -1635,7 +1703,7 @@ function createUploadCommand() {
1635
1703
  })
1636
1704
  );
1637
1705
  command.addCommand(
1638
- new Command8("delete").description("Delete an uploaded asset (admin only)").argument("<filename>", "Filename to delete").action(async function(filename) {
1706
+ new Command9("delete").description("Delete an uploaded asset (admin only)").argument("<filename>", "Filename to delete").action(async function(filename) {
1639
1707
  const ctx = createContext(this);
1640
1708
  try {
1641
1709
  const data = await ctx.client.delete(`/api/assets/${encodeURIComponent(filename)}`);
@@ -1648,103 +1716,6 @@ function createUploadCommand() {
1648
1716
  return command;
1649
1717
  }
1650
1718
 
1651
- // src/commands/voice.ts
1652
- import { Command as Command9 } from "commander";
1653
- function withVoiceType(path, type) {
1654
- if (!type) {
1655
- return path;
1656
- }
1657
- const params = new URLSearchParams({ type });
1658
- return `${path}?${params.toString()}`;
1659
- }
1660
- function createVoiceCommand() {
1661
- const command = new Command9("voice").description("Manage Qwen3-TTS voice designs");
1662
- command.addCommand(
1663
- new Command9("design").description("Create a synthetic voice and save the preview audio file").requiredOption("--prompt <text>", "Voice description prompt").requiredOption("--preview-text <text>", "Preview text for the generated sample").requiredOption("--name <name>", "Name for the designed voice").option("--target-model <model>", "Voice design model, e.g. qwen3-tts-vd-2026-01-26").option("--output-dir <dir>", "Directory to save preview audio", ".").action(async function(options) {
1664
- try {
1665
- const ctx = createContext(this);
1666
- const body = {
1667
- voice_prompt: options.prompt,
1668
- preview_text: options.previewText,
1669
- name: options.name
1670
- };
1671
- if (options.targetModel) body.target_model = options.targetModel;
1672
- const data = await ctx.client.post("/api/voice/design", body);
1673
- const b64Audio = data?.preview_audio_data;
1674
- if (b64Audio) {
1675
- const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync5 } = await import("fs");
1676
- const { join: join5 } = await import("path");
1677
- mkdirSync5(options.outputDir, { recursive: true });
1678
- const buf = Buffer.from(b64Audio, "base64");
1679
- const outPath = join5(options.outputDir, `${options.name}_preview.wav`);
1680
- writeFileSync5(outPath, buf);
1681
- data.preview_audio_path = outPath;
1682
- }
1683
- printSuccess("voice.design", data, ctx);
1684
- } catch (error2) {
1685
- printError("voice.design", error2);
1686
- }
1687
- })
1688
- );
1689
- command.addCommand(
1690
- new Command9("synthesize").description("Synthesize speech using a designed voice").requiredOption("--voice <name>", "Voice name from voice design").requiredOption("--text <text>", "Text to synthesize").option("--model <model>", "TTS model (default: qwen3-tts-vd-realtime-2025-12-16)").option("--language <lang>", "Language: zh, en, ja, etc. (default: Auto)").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
1691
- try {
1692
- const ctx = createContext(this);
1693
- const body = {
1694
- voice: options.voice,
1695
- text: options.text
1696
- };
1697
- if (options.model) body.model = options.model;
1698
- if (options.language) body.language = options.language;
1699
- const data = await ctx.client.post("/api/voice/synthesize", body);
1700
- const result = data.data;
1701
- const output2 = result?.output;
1702
- const audio = output2?.audio;
1703
- const audioUrl = audio?.url ?? output2?.url;
1704
- if (audioUrl && options.outputDir) {
1705
- const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync5 } = await import("fs");
1706
- const { join: join5 } = await import("path");
1707
- mkdirSync5(options.outputDir, { recursive: true });
1708
- const resp = await fetch(audioUrl);
1709
- if (resp.ok) {
1710
- const buf = Buffer.from(await resp.arrayBuffer());
1711
- const outPath = join5(options.outputDir, `tts_${Date.now()}.wav`);
1712
- writeFileSync5(outPath, buf);
1713
- data.local_path = outPath;
1714
- }
1715
- }
1716
- printSuccess("voice.synthesize", data, ctx);
1717
- } catch (error2) {
1718
- printError("voice.synthesize", error2);
1719
- }
1720
- })
1721
- );
1722
- command.addCommand(
1723
- new Command9("list").description("List custom designed voices").option("--type <type>", "Voice type: vd").action(async function(options) {
1724
- try {
1725
- const ctx = createContext(this);
1726
- const data = await ctx.client.get(withVoiceType("/api/voice/list", options.type));
1727
- printSuccess("voice.list", data, ctx);
1728
- } catch (error2) {
1729
- printError("voice.list", error2);
1730
- }
1731
- })
1732
- );
1733
- command.addCommand(
1734
- new Command9("delete").description("Delete a custom designed voice").argument("<voice-id>", "Voice ID to delete").option("--type <type>", "Voice type: vd").action(async function(voiceId, options) {
1735
- try {
1736
- const ctx = createContext(this);
1737
- const path = withVoiceType(`/api/voice/${encodeURIComponent(voiceId)}`, options.type);
1738
- const data = await ctx.client.delete(path);
1739
- printSuccess("voice.delete", data, ctx);
1740
- } catch (error2) {
1741
- printError("voice.delete", error2);
1742
- }
1743
- })
1744
- );
1745
- return command;
1746
- }
1747
-
1748
1719
  // src/index.ts
1749
1720
  var program = new Command10().name("asset-gateway").description("Universal asset generation gateway CLI").version(CLI_VERSION).option(
1750
1721
  "--gateway-url <url>",
@@ -1752,11 +1723,11 @@ var program = new Command10().name("asset-gateway").description("Universal asset
1752
1723
  ).option("--token <token>", "API token for authentication").option("--human", "Human-readable output instead of JSON").option("--fields <fields>", "Comma-separated list of output fields");
1753
1724
  program.addCommand(createAuthCommand());
1754
1725
  program.addCommand(createGenerateCommand());
1726
+ program.addCommand(createLibraryCommand());
1755
1727
  program.addCommand(createProcessCommand());
1756
1728
  program.addCommand(createProcess3dCommand());
1757
1729
  program.addCommand(createProviderCommand());
1758
1730
  program.addCommand(createUploadCommand());
1759
- program.addCommand(createVoiceCommand());
1760
1731
  program.addCommand(createJobCommand());
1761
1732
  program.addCommand(createDescribeCommand());
1762
1733
  await program.parseAsync(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doufunao123/asset-gateway",
3
- "version": "0.16.1",
3
+ "version": "0.18.0",
4
4
  "description": "Universal asset generation gateway CLI",
5
5
  "type": "module",
6
6
  "bin": {