@doufunao123/asset-gateway 0.2.2 → 0.4.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.
- package/dist/index.js +134 -13
- 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
|
|
4
|
+
import { Command as Command8 } 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.
|
|
73
|
+
var CLI_VERSION = "0.4.0";
|
|
74
74
|
var CLI_DESCRIPTION = "Universal asset generation gateway CLI";
|
|
75
75
|
var DEFAULT_GATEWAY_URL = "https://assets.xiaomao.chat";
|
|
76
76
|
|
|
@@ -490,7 +490,7 @@ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
|
490
490
|
import { join as join2 } from "path";
|
|
491
491
|
import { Command as Command3 } from "commander";
|
|
492
492
|
function inferExtension(assetType) {
|
|
493
|
-
const map = { image: "png", audio: "mp3", video: "mp4", model3d: "glb", text: "txt" };
|
|
493
|
+
const map = { image: "png", audio: "mp3", tts: "mp3", video: "mp4", model3d: "glb", text: "txt" };
|
|
494
494
|
return map[assetType] ?? "bin";
|
|
495
495
|
}
|
|
496
496
|
function stripDataUri(data) {
|
|
@@ -584,6 +584,31 @@ function createGenerateCommand() {
|
|
|
584
584
|
}
|
|
585
585
|
})
|
|
586
586
|
);
|
|
587
|
+
command.addCommand(
|
|
588
|
+
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
|
+
try {
|
|
590
|
+
const ctx = createContext(this);
|
|
591
|
+
const params = {};
|
|
592
|
+
if (options.voiceId) params.voice_id = options.voiceId;
|
|
593
|
+
if (options.speed) params.speed = Number(options.speed);
|
|
594
|
+
if (options.languageBoost) params.language_boost = options.languageBoost;
|
|
595
|
+
if (options.emotion) params.emotion = options.emotion;
|
|
596
|
+
const body = {
|
|
597
|
+
asset_type: "tts",
|
|
598
|
+
prompt: options.prompt,
|
|
599
|
+
params
|
|
600
|
+
};
|
|
601
|
+
if (options.model) body.model = options.model;
|
|
602
|
+
if (options.provider) body.provider = options.provider;
|
|
603
|
+
const data = await ctx.client.post("/api/generate", body);
|
|
604
|
+
const localPath = await saveOutput(data, "tts", options.outputDir);
|
|
605
|
+
if (localPath) data.local_path = localPath;
|
|
606
|
+
printSuccess("generate.tts", data, ctx);
|
|
607
|
+
} catch (error2) {
|
|
608
|
+
printError("generate.tts", error2);
|
|
609
|
+
}
|
|
610
|
+
})
|
|
611
|
+
);
|
|
587
612
|
command.addCommand(
|
|
588
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) {
|
|
589
614
|
try {
|
|
@@ -669,12 +694,107 @@ function createJobCommand() {
|
|
|
669
694
|
return command;
|
|
670
695
|
}
|
|
671
696
|
|
|
672
|
-
// src/commands/
|
|
697
|
+
// src/commands/process.ts
|
|
698
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
699
|
+
import { existsSync as existsSync3 } from "fs";
|
|
700
|
+
import { join as join3 } from "path";
|
|
673
701
|
import { Command as Command5 } from "commander";
|
|
702
|
+
function readInputAsBase64(input) {
|
|
703
|
+
if (existsSync3(input)) {
|
|
704
|
+
const bytes = readFileSync2(input);
|
|
705
|
+
return `data:image/png;base64,${bytes.toString("base64")}`;
|
|
706
|
+
}
|
|
707
|
+
return input;
|
|
708
|
+
}
|
|
709
|
+
function saveProcessOutput(data, outputDir) {
|
|
710
|
+
const outputData = data.output_data;
|
|
711
|
+
if (typeof outputData !== "string" || !outputData) return null;
|
|
712
|
+
mkdirSync3(outputDir, { recursive: true });
|
|
713
|
+
const timestamp = Date.now();
|
|
714
|
+
const filePath = join3(outputDir, `processed_${timestamp}.png`);
|
|
715
|
+
writeFileSync3(filePath, Buffer.from(outputData, "base64"));
|
|
716
|
+
delete data.output_data;
|
|
717
|
+
return filePath;
|
|
718
|
+
}
|
|
719
|
+
function createProcessCommand() {
|
|
720
|
+
const command = new Command5("process").description("Post-process images (remove-bg, crop, resize, upscale)");
|
|
721
|
+
command.addCommand(
|
|
722
|
+
new Command5("remove-bg").description("Remove background from an image (AI-powered, BiRefNet)").requiredOption("--input <path>", "Input image (file path or URL)").option("--smart-crop", "Also crop to power-of-2 after removing background").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
|
|
723
|
+
try {
|
|
724
|
+
const ctx = createContext(this);
|
|
725
|
+
const ops = [{ op: "remove_bg" }];
|
|
726
|
+
if (options.smartCrop) {
|
|
727
|
+
ops.push({ op: "smart_crop", mode: "power_of2" });
|
|
728
|
+
}
|
|
729
|
+
const data = await ctx.client.post("/api/process", {
|
|
730
|
+
input: readInputAsBase64(options.input),
|
|
731
|
+
operations: ops
|
|
732
|
+
});
|
|
733
|
+
const localPath = saveProcessOutput(data, options.outputDir);
|
|
734
|
+
if (localPath) data.local_path = localPath;
|
|
735
|
+
printSuccess("process.remove-bg", data, ctx);
|
|
736
|
+
} catch (error2) {
|
|
737
|
+
printError("process.remove-bg", error2);
|
|
738
|
+
}
|
|
739
|
+
})
|
|
740
|
+
);
|
|
741
|
+
command.addCommand(
|
|
742
|
+
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) {
|
|
743
|
+
try {
|
|
744
|
+
const ctx = createContext(this);
|
|
745
|
+
const data = await ctx.client.post("/api/process", {
|
|
746
|
+
input: readInputAsBase64(options.input),
|
|
747
|
+
operations: [{ op: "smart_crop", mode: options.mode }]
|
|
748
|
+
});
|
|
749
|
+
const localPath = saveProcessOutput(data, options.outputDir);
|
|
750
|
+
if (localPath) data.local_path = localPath;
|
|
751
|
+
printSuccess("process.crop", data, ctx);
|
|
752
|
+
} catch (error2) {
|
|
753
|
+
printError("process.crop", error2);
|
|
754
|
+
}
|
|
755
|
+
})
|
|
756
|
+
);
|
|
757
|
+
command.addCommand(
|
|
758
|
+
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) {
|
|
759
|
+
try {
|
|
760
|
+
const ctx = createContext(this);
|
|
761
|
+
const data = await ctx.client.post("/api/process", {
|
|
762
|
+
input: readInputAsBase64(options.input),
|
|
763
|
+
operations: [{ op: "resize", width: Number(options.width), height: Number(options.height) }]
|
|
764
|
+
});
|
|
765
|
+
const localPath = saveProcessOutput(data, options.outputDir);
|
|
766
|
+
if (localPath) data.local_path = localPath;
|
|
767
|
+
printSuccess("process.resize", data, ctx);
|
|
768
|
+
} catch (error2) {
|
|
769
|
+
printError("process.resize", error2);
|
|
770
|
+
}
|
|
771
|
+
})
|
|
772
|
+
);
|
|
773
|
+
command.addCommand(
|
|
774
|
+
new Command5("upscale").description("AI upscale an image (2x or 4x via Real-ESRGAN)").requiredOption("--input <path>", "Input image (file path or URL)").option("--scale <n>", "Scale factor (2 or 4)", "4").option("--output-dir <dir>", "Directory to save output", ".").action(async function(options) {
|
|
775
|
+
try {
|
|
776
|
+
const ctx = createContext(this);
|
|
777
|
+
const data = await ctx.client.post("/api/process", {
|
|
778
|
+
input: readInputAsBase64(options.input),
|
|
779
|
+
operations: [{ op: "upscale", scale: Number(options.scale) }]
|
|
780
|
+
});
|
|
781
|
+
const localPath = saveProcessOutput(data, options.outputDir);
|
|
782
|
+
if (localPath) data.local_path = localPath;
|
|
783
|
+
printSuccess("process.upscale", data, ctx);
|
|
784
|
+
} catch (error2) {
|
|
785
|
+
printError("process.upscale", error2);
|
|
786
|
+
}
|
|
787
|
+
})
|
|
788
|
+
);
|
|
789
|
+
return command;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// src/commands/provider.ts
|
|
793
|
+
import { Command as Command6 } from "commander";
|
|
674
794
|
function createProviderCommand() {
|
|
675
|
-
const command = new
|
|
795
|
+
const command = new Command6("provider").description("Provider management");
|
|
676
796
|
command.addCommand(
|
|
677
|
-
new
|
|
797
|
+
new Command6("list").description("List available providers").action(async function() {
|
|
678
798
|
try {
|
|
679
799
|
const ctx = createContext(this);
|
|
680
800
|
const data = await ctx.client.get("/api/providers");
|
|
@@ -685,7 +805,7 @@ function createProviderCommand() {
|
|
|
685
805
|
})
|
|
686
806
|
);
|
|
687
807
|
command.addCommand(
|
|
688
|
-
new
|
|
808
|
+
new Command6("health").description("Check provider health").argument("[name]", "Specific provider name").action(async function(name) {
|
|
689
809
|
try {
|
|
690
810
|
const ctx = createContext(this);
|
|
691
811
|
const path = name ? `/api/providers/${encodeURIComponent(name)}/health` : "/api/providers/health";
|
|
@@ -700,11 +820,11 @@ function createProviderCommand() {
|
|
|
700
820
|
}
|
|
701
821
|
|
|
702
822
|
// src/commands/upload.ts
|
|
703
|
-
import { Command as
|
|
823
|
+
import { Command as Command7 } from "commander";
|
|
704
824
|
function createUploadCommand() {
|
|
705
|
-
const command = new
|
|
825
|
+
const command = new Command7("upload").description("Upload and manage assets");
|
|
706
826
|
command.addCommand(
|
|
707
|
-
new
|
|
827
|
+
new Command7("file").description("Upload a file and get a public URL").argument("<path>", "Path to file to upload").action(async function(filePath) {
|
|
708
828
|
const ctx = createContext(this);
|
|
709
829
|
try {
|
|
710
830
|
const data = await ctx.client.uploadFile(filePath);
|
|
@@ -715,7 +835,7 @@ function createUploadCommand() {
|
|
|
715
835
|
})
|
|
716
836
|
);
|
|
717
837
|
command.addCommand(
|
|
718
|
-
new
|
|
838
|
+
new Command7("list").description("List uploaded assets").action(async function() {
|
|
719
839
|
const ctx = createContext(this);
|
|
720
840
|
try {
|
|
721
841
|
const data = await ctx.client.get("/api/assets");
|
|
@@ -726,7 +846,7 @@ function createUploadCommand() {
|
|
|
726
846
|
})
|
|
727
847
|
);
|
|
728
848
|
command.addCommand(
|
|
729
|
-
new
|
|
849
|
+
new Command7("delete").description("Delete an uploaded asset (admin only)").argument("<filename>", "Filename to delete").action(async function(filename) {
|
|
730
850
|
const ctx = createContext(this);
|
|
731
851
|
try {
|
|
732
852
|
const data = await ctx.client.delete(`/api/assets/${encodeURIComponent(filename)}`);
|
|
@@ -740,12 +860,13 @@ function createUploadCommand() {
|
|
|
740
860
|
}
|
|
741
861
|
|
|
742
862
|
// src/index.ts
|
|
743
|
-
var program = new
|
|
863
|
+
var program = new Command8().name("asset-gateway").description("Universal asset generation gateway CLI").version(CLI_VERSION).option(
|
|
744
864
|
"--gateway-url <url>",
|
|
745
865
|
`Gateway URL (default: $ASSET_GATEWAY_URL, auth config, or ${DEFAULT_GATEWAY_URL})`
|
|
746
866
|
).option("--token <token>", "API token for authentication").option("--human", "Human-readable output instead of JSON").option("--fields <fields>", "Comma-separated list of output fields");
|
|
747
867
|
program.addCommand(createAuthCommand());
|
|
748
868
|
program.addCommand(createGenerateCommand());
|
|
869
|
+
program.addCommand(createProcessCommand());
|
|
749
870
|
program.addCommand(createProviderCommand());
|
|
750
871
|
program.addCommand(createUploadCommand());
|
|
751
872
|
program.addCommand(createJobCommand());
|