@doufunao123/asset-gateway 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +220 -14
  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
 
@@ -527,7 +527,7 @@ async function saveOutput(result, assetType, outputDir) {
527
527
  function createGenerateCommand() {
528
528
  const command = new Command3("generate").description("Generate assets via the gateway");
529
529
  command.addCommand(
530
- 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("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
530
+ 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("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
531
531
  try {
532
532
  const ctx = createContext(this);
533
533
  const body = {
@@ -538,6 +538,7 @@ function createGenerateCommand() {
538
538
  if (options.transparent) body.transparent = true;
539
539
  if (options.model) body.model = options.model;
540
540
  if (options.size) body.size = options.size;
541
+ if (options.input) body.input_file = options.input;
541
542
  const data = await ctx.client.post("/api/generate", body);
542
543
  const localPath = await saveOutput(data, "image", options.outputDir);
543
544
  if (localPath) data.local_path = localPath;
@@ -610,14 +611,25 @@ function createGenerateCommand() {
610
611
  })
611
612
  );
612
613
  command.addCommand(
613
- 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) {
614
615
  try {
615
616
  const ctx = createContext(this);
616
617
  const body = {
617
618
  asset_type: "model3d"
618
619
  };
620
+ const params = {};
619
621
  if (options.image) body.input_file = options.image;
620
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;
621
633
  const data = await ctx.client.post("/api/generate", body);
622
634
  const localPath = await saveOutput(data, "model3d", options.outputDir);
623
635
  if (localPath) data.local_path = localPath;
@@ -789,12 +801,205 @@ function createProcessCommand() {
789
801
  return command;
790
802
  }
791
803
 
792
- // 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";
793
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";
794
999
  function createProviderCommand() {
795
- const command = new Command6("provider").description("Provider management");
1000
+ const command = new Command7("provider").description("Provider management");
796
1001
  command.addCommand(
797
- new Command6("list").description("List available providers").action(async function() {
1002
+ new Command7("list").description("List available providers").action(async function() {
798
1003
  try {
799
1004
  const ctx = createContext(this);
800
1005
  const data = await ctx.client.get("/api/providers");
@@ -805,7 +1010,7 @@ function createProviderCommand() {
805
1010
  })
806
1011
  );
807
1012
  command.addCommand(
808
- 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) {
809
1014
  try {
810
1015
  const ctx = createContext(this);
811
1016
  const path = name ? `/api/providers/${encodeURIComponent(name)}/health` : "/api/providers/health";
@@ -820,11 +1025,11 @@ function createProviderCommand() {
820
1025
  }
821
1026
 
822
1027
  // src/commands/upload.ts
823
- import { Command as Command7 } from "commander";
1028
+ import { Command as Command8 } from "commander";
824
1029
  function createUploadCommand() {
825
- const command = new Command7("upload").description("Upload and manage assets");
1030
+ const command = new Command8("upload").description("Upload and manage assets");
826
1031
  command.addCommand(
827
- 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) {
828
1033
  const ctx = createContext(this);
829
1034
  try {
830
1035
  const data = await ctx.client.uploadFile(filePath);
@@ -835,7 +1040,7 @@ function createUploadCommand() {
835
1040
  })
836
1041
  );
837
1042
  command.addCommand(
838
- new Command7("list").description("List uploaded assets").action(async function() {
1043
+ new Command8("list").description("List uploaded assets").action(async function() {
839
1044
  const ctx = createContext(this);
840
1045
  try {
841
1046
  const data = await ctx.client.get("/api/assets");
@@ -846,7 +1051,7 @@ function createUploadCommand() {
846
1051
  })
847
1052
  );
848
1053
  command.addCommand(
849
- 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) {
850
1055
  const ctx = createContext(this);
851
1056
  try {
852
1057
  const data = await ctx.client.delete(`/api/assets/${encodeURIComponent(filename)}`);
@@ -860,13 +1065,14 @@ function createUploadCommand() {
860
1065
  }
861
1066
 
862
1067
  // src/index.ts
863
- 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(
864
1069
  "--gateway-url <url>",
865
1070
  `Gateway URL (default: $ASSET_GATEWAY_URL, auth config, or ${DEFAULT_GATEWAY_URL})`
866
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");
867
1072
  program.addCommand(createAuthCommand());
868
1073
  program.addCommand(createGenerateCommand());
869
1074
  program.addCommand(createProcessCommand());
1075
+ program.addCommand(createProcess3dCommand());
870
1076
  program.addCommand(createProviderCommand());
871
1077
  program.addCommand(createUploadCommand());
872
1078
  program.addCommand(createJobCommand());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doufunao123/asset-gateway",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Universal asset generation gateway CLI",
5
5
  "type": "module",
6
6
  "bin": {