@doufunao123/asset-gateway 0.5.0 → 0.7.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 +225 -20
  2. package/package.json +1 -1
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 Command8 } from "commander";
4
+ import { Command as Command9 } from "commander";
5
5
 
6
6
  // src/commands/auth.ts
7
7
  import { existsSync as existsSync2, unlinkSync } from "fs";
@@ -70,7 +70,7 @@ function normalizeError(error2) {
70
70
 
71
71
  // src/meta.ts
72
72
  var CLI_NAME = "asset-gateway";
73
- var CLI_VERSION = "0.4.0";
73
+ var CLI_VERSION = "0.6.0";
74
74
  var CLI_DESCRIPTION = "Universal asset generation gateway CLI";
75
75
  var DEFAULT_GATEWAY_URL = "https://assets.xiaomao.chat";
76
76
 
@@ -586,20 +586,20 @@ function createGenerateCommand() {
586
586
  })
587
587
  );
588
588
  command.addCommand(
589
- new Command3("tts").description("Text-to-speech synthesis (Chinese/multilingual)").requiredOption("--prompt <text>", "Text to synthesize").option("--voice-id <id>", "Voice ID (e.g. 'Chinese (Mandarin)_Lyrical_Voice')").option("--model <model>", "TTS model (speech-2.6-hd, speech-2.6-turbo)").option("--speed <n>", "Speech speed [0.5, 2.0]").option("--language-boost <lang>", "Language hint: auto, Chinese, English, etc.").option("--emotion <emotion>", "Emotion: happy, sad, angry, calm, etc.").option("--provider <id>", "Provider to use").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
589
+ new Command3("tts").description("Text-to-speech synthesis via Qwen3-TTS").requiredOption("--prompt <text>", "Text to synthesize").option("--voice <name>", "Voice name or custom voice ID", "Cherry").option("--language <lang>", "Language hint: Auto, Chinese, English, Japanese, etc.", "Auto").option("--model <model>", "Qwen3-TTS model", "qwen3-tts-flash").option("--instructions <text>", "Natural language speaking instructions (for instruct models)").option("--provider <id>", "Provider to use").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
590
590
  try {
591
591
  const ctx = createContext(this);
592
- const params = {};
593
- if (options.voiceId) params.voice_id = options.voiceId;
594
- if (options.speed) params.speed = Number(options.speed);
595
- if (options.languageBoost) params.language_boost = options.languageBoost;
596
- if (options.emotion) params.emotion = options.emotion;
592
+ const params = {
593
+ voice: options.voice,
594
+ language_type: options.language
595
+ };
596
+ if (options.instructions) params.instructions = options.instructions;
597
597
  const body = {
598
598
  asset_type: "tts",
599
599
  prompt: options.prompt,
600
+ model: options.model,
600
601
  params
601
602
  };
602
- if (options.model) body.model = options.model;
603
603
  if (options.provider) body.provider = options.provider;
604
604
  const data = await ctx.client.post("/api/generate", body);
605
605
  const localPath = await saveOutput(data, "tts", options.outputDir);
@@ -611,14 +611,25 @@ function createGenerateCommand() {
611
611
  })
612
612
  );
613
613
  command.addCommand(
614
- new Command3("model").description("Generate a 3D model").option("--image <url>", "Reference image URL").option("--prompt <text>", "Model description prompt").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
614
+ new Command3("model").description("Generate a 3D model").option("--image <url>", "Reference image URL").option("--prompt <text>", "Model description prompt").option("--model-version <v>", "Tripo model version (e.g. P1-20260311)").option("--face-limit <n>", "Max face count (48-20000)").option("--pbr", "Enable PBR textures").option("--texture-quality <q>", "Texture quality: standard or detailed").option("--auto-size", "Auto-scale to real-world dimensions").option("--negative-prompt <text>", "Negative prompt").option("--multiview <urls>", "4 image URLs comma-separated: front,left,back,right").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
615
615
  try {
616
616
  const ctx = createContext(this);
617
617
  const body = {
618
618
  asset_type: "model3d"
619
619
  };
620
+ const params = {};
620
621
  if (options.image) body.input_file = options.image;
621
622
  if (options.prompt) body.prompt = options.prompt;
623
+ if (options.modelVersion) params.model_version = options.modelVersion;
624
+ if (options.faceLimit) params.face_limit = Number(options.faceLimit);
625
+ if (options.pbr) params.pbr = true;
626
+ if (options.textureQuality) params.texture_quality = options.textureQuality;
627
+ if (options.autoSize) params.auto_size = true;
628
+ if (options.negativePrompt) params.negative_prompt = options.negativePrompt;
629
+ if (options.multiview) {
630
+ params.multiview = String(options.multiview).split(",").map((value) => value.trim()).filter(Boolean);
631
+ }
632
+ if (Object.keys(params).length > 0) body.params = params;
622
633
  const data = await ctx.client.post("/api/generate", body);
623
634
  const localPath = await saveOutput(data, "model3d", options.outputDir);
624
635
  if (localPath) data.local_path = localPath;
@@ -790,12 +801,205 @@ function createProcessCommand() {
790
801
  return command;
791
802
  }
792
803
 
793
- // src/commands/provider.ts
804
+ // src/commands/process3d.ts
805
+ import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
806
+ import { join as join4 } from "path";
794
807
  import { Command as Command6 } from "commander";
808
+ function infer3dExtension(format) {
809
+ const map = {
810
+ fbx: "fbx",
811
+ usdz: "usdz",
812
+ obj: "obj",
813
+ stl: "stl",
814
+ gltf: "gltf",
815
+ "3mf": "3mf",
816
+ glb: "glb"
817
+ };
818
+ return map[String(format ?? "glb").toLowerCase()] ?? "glb";
819
+ }
820
+ async function saveProcess3dOutput(data, operation, outputDir, format) {
821
+ if (!data.output_url) {
822
+ return null;
823
+ }
824
+ const ext = infer3dExtension(format);
825
+ const timestamp = Date.now();
826
+ const filePath = join4(outputDir, `${operation}_${timestamp}.${ext}`);
827
+ mkdirSync4(outputDir, { recursive: true });
828
+ const response = await fetch(String(data.output_url));
829
+ if (!response.ok) {
830
+ return null;
831
+ }
832
+ const buffer = Buffer.from(await response.arrayBuffer());
833
+ writeFileSync4(filePath, buffer);
834
+ return filePath;
835
+ }
836
+ function createProcess3dCommand() {
837
+ const command = new Command6("process3d").description("3D model post-processing via Tripo pipeline");
838
+ command.addCommand(
839
+ 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("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
840
+ try {
841
+ const ctx = createContext(this);
842
+ const params = {
843
+ format: options.format
844
+ };
845
+ if (options.quad) params.quad = true;
846
+ if (options.faceLimit) params.face_limit = Number(options.faceLimit);
847
+ const data = await ctx.client.post("/api/process3d", {
848
+ task_id: options.taskId,
849
+ operation: "convert",
850
+ params
851
+ });
852
+ const localPath = await saveProcess3dOutput(data, "convert", options.outputDir, options.format);
853
+ if (localPath) data.local_path = localPath;
854
+ printSuccess("process3d.convert", data, ctx);
855
+ } catch (error2) {
856
+ printError("process3d.convert", error2);
857
+ }
858
+ })
859
+ );
860
+ command.addCommand(
861
+ 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("--pbr", "Enable PBR materials").option("--quality <q>", "Texture quality: standard or detailed").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
862
+ try {
863
+ const ctx = createContext(this);
864
+ const params = {};
865
+ if (options.prompt) params.prompt = options.prompt;
866
+ if (options.pbr) params.pbr = true;
867
+ if (options.quality) params.quality = options.quality;
868
+ const data = await ctx.client.post("/api/process3d", {
869
+ task_id: options.taskId,
870
+ operation: "texture",
871
+ params
872
+ });
873
+ const localPath = await saveProcess3dOutput(data, "texture", options.outputDir);
874
+ if (localPath) data.local_path = localPath;
875
+ printSuccess("process3d.texture", data, ctx);
876
+ } catch (error2) {
877
+ printError("process3d.texture", error2);
878
+ }
879
+ })
880
+ );
881
+ command.addCommand(
882
+ 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("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
883
+ try {
884
+ const ctx = createContext(this);
885
+ const data = await ctx.client.post("/api/process3d", {
886
+ task_id: options.taskId,
887
+ operation: "rig",
888
+ params: {
889
+ format: options.format,
890
+ spec: options.spec
891
+ }
892
+ });
893
+ const localPath = await saveProcess3dOutput(data, "rig", options.outputDir, options.format);
894
+ if (localPath) data.local_path = localPath;
895
+ printSuccess("process3d.rig", data, ctx);
896
+ } catch (error2) {
897
+ printError("process3d.rig", error2);
898
+ }
899
+ })
900
+ );
901
+ command.addCommand(
902
+ 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) {
903
+ try {
904
+ const ctx = createContext(this);
905
+ const data = await ctx.client.post("/api/process3d", {
906
+ task_id: options.taskId,
907
+ operation: "animate",
908
+ params: {
909
+ animation: options.animation,
910
+ format: options.format
911
+ }
912
+ });
913
+ const localPath = await saveProcess3dOutput(data, "animate", options.outputDir, options.format);
914
+ if (localPath) data.local_path = localPath;
915
+ printSuccess("process3d.animate", data, ctx);
916
+ } catch (error2) {
917
+ printError("process3d.animate", error2);
918
+ }
919
+ })
920
+ );
921
+ command.addCommand(
922
+ 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) {
923
+ try {
924
+ const ctx = createContext(this);
925
+ const params = {};
926
+ if (options.faceLimit) params.face_limit = Number(options.faceLimit);
927
+ if (options.quad) params.quad = true;
928
+ const data = await ctx.client.post("/api/process3d", {
929
+ task_id: options.taskId,
930
+ operation: "reduce",
931
+ params
932
+ });
933
+ const localPath = await saveProcess3dOutput(data, "reduce", options.outputDir);
934
+ if (localPath) data.local_path = localPath;
935
+ printSuccess("process3d.reduce", data, ctx);
936
+ } catch (error2) {
937
+ printError("process3d.reduce", error2);
938
+ }
939
+ })
940
+ );
941
+ command.addCommand(
942
+ 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) {
943
+ try {
944
+ const ctx = createContext(this);
945
+ const data = await ctx.client.post("/api/process3d", {
946
+ task_id: options.taskId,
947
+ operation: "stylize",
948
+ params: {
949
+ style: options.style
950
+ }
951
+ });
952
+ const localPath = await saveProcess3dOutput(data, "stylize", options.outputDir);
953
+ if (localPath) data.local_path = localPath;
954
+ printSuccess("process3d.stylize", data, ctx);
955
+ } catch (error2) {
956
+ printError("process3d.stylize", error2);
957
+ }
958
+ })
959
+ );
960
+ command.addCommand(
961
+ 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) {
962
+ try {
963
+ const ctx = createContext(this);
964
+ const data = await ctx.client.post("/api/process3d", {
965
+ task_id: options.taskId,
966
+ operation: "segment",
967
+ params: {}
968
+ });
969
+ const localPath = await saveProcess3dOutput(data, "segment", options.outputDir);
970
+ if (localPath) data.local_path = localPath;
971
+ printSuccess("process3d.segment", data, ctx);
972
+ } catch (error2) {
973
+ printError("process3d.segment", error2);
974
+ }
975
+ })
976
+ );
977
+ command.addCommand(
978
+ 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) {
979
+ try {
980
+ const ctx = createContext(this);
981
+ const data = await ctx.client.post("/api/process3d", {
982
+ task_id: options.taskId,
983
+ operation: "prerigcheck",
984
+ params: {}
985
+ });
986
+ const localPath = await saveProcess3dOutput(data, "prerigcheck", options.outputDir);
987
+ if (localPath) data.local_path = localPath;
988
+ printSuccess("process3d.prerigcheck", data, ctx);
989
+ } catch (error2) {
990
+ printError("process3d.prerigcheck", error2);
991
+ }
992
+ })
993
+ );
994
+ return command;
995
+ }
996
+
997
+ // src/commands/provider.ts
998
+ import { Command as Command7 } from "commander";
795
999
  function createProviderCommand() {
796
- const command = new Command6("provider").description("Provider management");
1000
+ const command = new Command7("provider").description("Provider management");
797
1001
  command.addCommand(
798
- new Command6("list").description("List available providers").action(async function() {
1002
+ new Command7("list").description("List available providers").action(async function() {
799
1003
  try {
800
1004
  const ctx = createContext(this);
801
1005
  const data = await ctx.client.get("/api/providers");
@@ -806,7 +1010,7 @@ function createProviderCommand() {
806
1010
  })
807
1011
  );
808
1012
  command.addCommand(
809
- new Command6("health").description("Check provider health").argument("[name]", "Specific provider name").action(async function(name) {
1013
+ new Command7("health").description("Check provider health").argument("[name]", "Specific provider name").action(async function(name) {
810
1014
  try {
811
1015
  const ctx = createContext(this);
812
1016
  const path = name ? `/api/providers/${encodeURIComponent(name)}/health` : "/api/providers/health";
@@ -821,11 +1025,11 @@ function createProviderCommand() {
821
1025
  }
822
1026
 
823
1027
  // src/commands/upload.ts
824
- import { Command as Command7 } from "commander";
1028
+ import { Command as Command8 } from "commander";
825
1029
  function createUploadCommand() {
826
- const command = new Command7("upload").description("Upload and manage assets");
1030
+ const command = new Command8("upload").description("Upload and manage assets");
827
1031
  command.addCommand(
828
- new Command7("file").description("Upload a file and get a public URL").argument("<path>", "Path to file to upload").action(async function(filePath) {
1032
+ new Command8("file").description("Upload a file and get a public URL").argument("<path>", "Path to file to upload").action(async function(filePath) {
829
1033
  const ctx = createContext(this);
830
1034
  try {
831
1035
  const data = await ctx.client.uploadFile(filePath);
@@ -836,7 +1040,7 @@ function createUploadCommand() {
836
1040
  })
837
1041
  );
838
1042
  command.addCommand(
839
- new Command7("list").description("List uploaded assets").action(async function() {
1043
+ new Command8("list").description("List uploaded assets").action(async function() {
840
1044
  const ctx = createContext(this);
841
1045
  try {
842
1046
  const data = await ctx.client.get("/api/assets");
@@ -847,7 +1051,7 @@ function createUploadCommand() {
847
1051
  })
848
1052
  );
849
1053
  command.addCommand(
850
- new Command7("delete").description("Delete an uploaded asset (admin only)").argument("<filename>", "Filename to delete").action(async function(filename) {
1054
+ new Command8("delete").description("Delete an uploaded asset (admin only)").argument("<filename>", "Filename to delete").action(async function(filename) {
851
1055
  const ctx = createContext(this);
852
1056
  try {
853
1057
  const data = await ctx.client.delete(`/api/assets/${encodeURIComponent(filename)}`);
@@ -861,13 +1065,14 @@ function createUploadCommand() {
861
1065
  }
862
1066
 
863
1067
  // src/index.ts
864
- var program = new Command8().name("asset-gateway").description("Universal asset generation gateway CLI").version(CLI_VERSION).option(
1068
+ var program = new Command9().name("asset-gateway").description("Universal asset generation gateway CLI").version(CLI_VERSION).option(
865
1069
  "--gateway-url <url>",
866
1070
  `Gateway URL (default: $ASSET_GATEWAY_URL, auth config, or ${DEFAULT_GATEWAY_URL})`
867
1071
  ).option("--token <token>", "API token for authentication").option("--human", "Human-readable output instead of JSON").option("--fields <fields>", "Comma-separated list of output fields");
868
1072
  program.addCommand(createAuthCommand());
869
1073
  program.addCommand(createGenerateCommand());
870
1074
  program.addCommand(createProcessCommand());
1075
+ program.addCommand(createProcess3dCommand());
871
1076
  program.addCommand(createProviderCommand());
872
1077
  program.addCommand(createUploadCommand());
873
1078
  program.addCommand(createJobCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doufunao123/asset-gateway",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Universal asset generation gateway CLI",
5
5
  "type": "module",
6
6
  "bin": {