zerocut-cli 0.3.2 → 0.3.4
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/commands/config.js +50 -48
- package/dist/commands/skill.js +10 -6
- package/dist/services/commandLoader.js +3 -1
- package/package.json +1 -1
- package/src/commands/config.ts +50 -51
- package/src/commands/skill.ts +12 -5
- package/src/services/commandLoader.ts +3 -1
package/dist/commands/config.js
CHANGED
|
@@ -17,6 +17,29 @@ async function ask(question, defaults) {
|
|
|
17
17
|
const trimmed = answer.trim();
|
|
18
18
|
return trimmed.length > 0 ? trimmed : (defaults ?? "");
|
|
19
19
|
}
|
|
20
|
+
async function exchangeOttAndSave(ott, region) {
|
|
21
|
+
const base = region === "cn" ? "https://api2.zerocut.cn" : "https://api2.zerocut.art";
|
|
22
|
+
const resp = await fetch(`${base}/api/open/ott/exchange`, {
|
|
23
|
+
method: "POST",
|
|
24
|
+
headers: { "content-type": "application/json" },
|
|
25
|
+
body: JSON.stringify({ ott }),
|
|
26
|
+
});
|
|
27
|
+
if (!resp.ok) {
|
|
28
|
+
process.stderr.write(`OTT exchange failed: HTTP ${resp.status}\n`);
|
|
29
|
+
process.exitCode = 1;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const json = (await resp.json());
|
|
33
|
+
const apiKey = json?.data?.apiKey;
|
|
34
|
+
if (typeof apiKey !== "string" || apiKey.length === 0) {
|
|
35
|
+
process.stderr.write("OTT exchange failed: missing data.apiKey in response\n");
|
|
36
|
+
process.exitCode = 1;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
(0, config_1.setConfigValueSync)("apiKey", apiKey);
|
|
40
|
+
(0, config_1.setConfigValueSync)("region", region);
|
|
41
|
+
process.stdout.write("apiKey set via OTT\n");
|
|
42
|
+
}
|
|
20
43
|
function register(program) {
|
|
21
44
|
const parent = program
|
|
22
45
|
.command("config")
|
|
@@ -24,37 +47,38 @@ function register(program) {
|
|
|
24
47
|
.option("--ott <token>", "One-Time Token (OTT) for fetching API key")
|
|
25
48
|
.option("--region <region>", "Region for OTT exchange: cn|us")
|
|
26
49
|
.action(async function (opts) {
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
50
|
+
const cfg = (0, config_1.readConfigSync)();
|
|
51
|
+
const regionInput = typeof opts.region === "string" ? opts.region.trim().toLowerCase() : "";
|
|
52
|
+
let region;
|
|
53
|
+
if (regionInput === "cn" || regionInput === "us") {
|
|
54
|
+
region = regionInput;
|
|
55
|
+
}
|
|
56
|
+
else if (regionInput.length > 0) {
|
|
57
|
+
process.stderr.write("Invalid --region. Allowed: cn|us\n");
|
|
33
58
|
process.exitCode = 1;
|
|
34
59
|
return;
|
|
35
60
|
}
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (!resp.ok) {
|
|
44
|
-
process.stderr.write(`OTT exchange failed: HTTP ${resp.status}\n`);
|
|
61
|
+
else {
|
|
62
|
+
const defaultRegion = cfg.region === "cn" || cfg.region === "us" ? cfg.region : "us";
|
|
63
|
+
const regionAnswer = (await ask("Choose region (cn/us)", defaultRegion))
|
|
64
|
+
.trim()
|
|
65
|
+
.toLowerCase();
|
|
66
|
+
if (regionAnswer !== "cn" && regionAnswer !== "us") {
|
|
67
|
+
process.stderr.write("Invalid region. Allowed: cn|us\n");
|
|
45
68
|
process.exitCode = 1;
|
|
46
69
|
return;
|
|
47
70
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
71
|
+
region = regionAnswer;
|
|
72
|
+
}
|
|
73
|
+
const ott = typeof opts.ott === "string" ? opts.ott.trim() : "";
|
|
74
|
+
const ottValue = ott.length > 0 ? ott : (await ask("Enter One-Time Token (OTT)")).trim();
|
|
75
|
+
if (!ottValue) {
|
|
76
|
+
process.stderr.write("OTT is required\n");
|
|
77
|
+
process.exitCode = 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
await exchangeOttAndSave(ottValue, region);
|
|
58
82
|
}
|
|
59
83
|
catch (err) {
|
|
60
84
|
process.stderr.write(`OTT exchange failed: ${err.message}\n`);
|
|
@@ -84,29 +108,7 @@ function register(program) {
|
|
|
84
108
|
return;
|
|
85
109
|
}
|
|
86
110
|
try {
|
|
87
|
-
|
|
88
|
-
const resp = await fetch(`${base}/api/open/ott/exchange`, {
|
|
89
|
-
method: "POST",
|
|
90
|
-
headers: {
|
|
91
|
-
"content-type": "application/json",
|
|
92
|
-
},
|
|
93
|
-
body: JSON.stringify({ ott }),
|
|
94
|
-
});
|
|
95
|
-
if (!resp.ok) {
|
|
96
|
-
process.stderr.write(`OTT exchange failed: HTTP ${resp.status}\n`);
|
|
97
|
-
process.exitCode = 1;
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
const json = (await resp.json());
|
|
101
|
-
const apiKey = json?.data?.apiKey;
|
|
102
|
-
if (typeof apiKey !== "string" || apiKey.length === 0) {
|
|
103
|
-
process.stderr.write("OTT exchange failed: missing data.apiKey in response\n");
|
|
104
|
-
process.exitCode = 1;
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
(0, config_1.setConfigValueSync)("apiKey", apiKey);
|
|
108
|
-
(0, config_1.setConfigValueSync)("region", region);
|
|
109
|
-
process.stdout.write("apiKey set via OTT\n");
|
|
111
|
+
await exchangeOttAndSave(ott, region);
|
|
110
112
|
}
|
|
111
113
|
catch (err) {
|
|
112
114
|
process.stderr.write(`OTT exchange failed: ${err.message}\n`);
|
package/dist/commands/skill.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.description = exports.name = void 0;
|
|
7
7
|
exports.register = register;
|
|
8
8
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
9
10
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
11
|
exports.name = "skill";
|
|
11
12
|
exports.description = "Print built-in SKILL.md content";
|
|
@@ -16,13 +17,12 @@ function printSkill(relativePath) {
|
|
|
16
17
|
if (!content.endsWith("\n")) {
|
|
17
18
|
process.stdout.write("\n");
|
|
18
19
|
}
|
|
19
|
-
const outputPath = node_path_1.default.resolve(process.cwd(), "zerocut-cli/SKILL.md");
|
|
20
|
-
node_fs_1.default.mkdirSync(node_path_1.default.dirname(outputPath), { recursive: true });
|
|
21
|
-
node_fs_1.default.writeFileSync(outputPath, content, "utf8");
|
|
22
|
-
process.stderr.write(`Saved skill markdown to ${outputPath}\n`);
|
|
23
20
|
}
|
|
24
21
|
function register(program) {
|
|
25
|
-
const parent = program
|
|
22
|
+
const parent = program
|
|
23
|
+
.command("skill")
|
|
24
|
+
.description("Print built-in skill markdown")
|
|
25
|
+
.option("--claude", "Append Claude skill save hint");
|
|
26
26
|
parent
|
|
27
27
|
.command("one-click-video")
|
|
28
28
|
.description("Print one-click-video skill markdown")
|
|
@@ -35,7 +35,11 @@ function register(program) {
|
|
|
35
35
|
.action(() => {
|
|
36
36
|
printSkill("../skill/edit-video/SKILL.md");
|
|
37
37
|
});
|
|
38
|
-
parent.action(() => {
|
|
38
|
+
parent.action((opts) => {
|
|
39
39
|
printSkill("../skill/SKILL.md");
|
|
40
|
+
if (opts.claude) {
|
|
41
|
+
const savePath = node_path_1.default.join(node_os_1.default.homedir(), ".claude", "skills", "zerocut", "SKILL.md");
|
|
42
|
+
process.stdout.write(`\n⚠️ Please save the markdown above to ${savePath} to create the skill.\n`);
|
|
43
|
+
}
|
|
40
44
|
});
|
|
41
45
|
}
|
|
@@ -49,6 +49,7 @@ const pandoc_1 = require("../commands/pandoc");
|
|
|
49
49
|
const skill_1 = require("../commands/skill");
|
|
50
50
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
51
51
|
const node_path_1 = __importDefault(require("node:path"));
|
|
52
|
+
const node_url_1 = require("node:url");
|
|
52
53
|
function loadBuiltInCommands(program) {
|
|
53
54
|
(0, help_1.register)(program);
|
|
54
55
|
(0, config_1.register)(program);
|
|
@@ -70,7 +71,8 @@ async function loadExternalCommandsAsync(program, dir) {
|
|
|
70
71
|
for (const f of files) {
|
|
71
72
|
const full = node_path_1.default.join(d, f);
|
|
72
73
|
try {
|
|
73
|
-
const
|
|
74
|
+
const moduleSpecifier = (0, node_url_1.pathToFileURL)(full).href;
|
|
75
|
+
const mod = (await Promise.resolve(`${moduleSpecifier}`).then(s => __importStar(require(s))));
|
|
74
76
|
const fn = mod.register ?? mod.default;
|
|
75
77
|
if (typeof fn === "function")
|
|
76
78
|
fn(program);
|
package/package.json
CHANGED
package/src/commands/config.ts
CHANGED
|
@@ -14,6 +14,30 @@ async function ask(question: string, defaults?: string): Promise<string> {
|
|
|
14
14
|
return trimmed.length > 0 ? trimmed : (defaults ?? "");
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
async function exchangeOttAndSave(ott: string, region: "cn" | "us"): Promise<void> {
|
|
18
|
+
const base = region === "cn" ? "https://api2.zerocut.cn" : "https://api2.zerocut.art";
|
|
19
|
+
const resp = await fetch(`${base}/api/open/ott/exchange`, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: { "content-type": "application/json" },
|
|
22
|
+
body: JSON.stringify({ ott }),
|
|
23
|
+
});
|
|
24
|
+
if (!resp.ok) {
|
|
25
|
+
process.stderr.write(`OTT exchange failed: HTTP ${resp.status}\n`);
|
|
26
|
+
process.exitCode = 1;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
const json = (await resp.json()) as { data?: { apiKey?: string } };
|
|
30
|
+
const apiKey = json?.data?.apiKey;
|
|
31
|
+
if (typeof apiKey !== "string" || apiKey.length === 0) {
|
|
32
|
+
process.stderr.write("OTT exchange failed: missing data.apiKey in response\n");
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
setConfigValueSync("apiKey", apiKey);
|
|
37
|
+
setConfigValueSync("region", region);
|
|
38
|
+
process.stdout.write("apiKey set via OTT\n");
|
|
39
|
+
}
|
|
40
|
+
|
|
17
41
|
export function register(program: Command): void {
|
|
18
42
|
const parent = program
|
|
19
43
|
.command("config")
|
|
@@ -21,36 +45,36 @@ export function register(program: Command): void {
|
|
|
21
45
|
.option("--ott <token>", "One-Time Token (OTT) for fetching API key")
|
|
22
46
|
.option("--region <region>", "Region for OTT exchange: cn|us")
|
|
23
47
|
.action(async function (this: Command, opts: { ott?: string; region?: string }) {
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
|
|
48
|
+
const cfg = readConfigSync() as { region?: unknown };
|
|
49
|
+
const regionInput = typeof opts.region === "string" ? opts.region.trim().toLowerCase() : "";
|
|
50
|
+
let region: "cn" | "us";
|
|
51
|
+
if (regionInput === "cn" || regionInput === "us") {
|
|
52
|
+
region = regionInput;
|
|
53
|
+
} else if (regionInput.length > 0) {
|
|
54
|
+
process.stderr.write("Invalid --region. Allowed: cn|us\n");
|
|
29
55
|
process.exitCode = 1;
|
|
30
56
|
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
39
|
-
if (!resp.ok) {
|
|
40
|
-
process.stderr.write(`OTT exchange failed: HTTP ${resp.status}\n`);
|
|
57
|
+
} else {
|
|
58
|
+
const defaultRegion = cfg.region === "cn" || cfg.region === "us" ? cfg.region : "us";
|
|
59
|
+
const regionAnswer = (await ask("Choose region (cn/us)", defaultRegion))
|
|
60
|
+
.trim()
|
|
61
|
+
.toLowerCase();
|
|
62
|
+
if (regionAnswer !== "cn" && regionAnswer !== "us") {
|
|
63
|
+
process.stderr.write("Invalid region. Allowed: cn|us\n");
|
|
41
64
|
process.exitCode = 1;
|
|
42
65
|
return;
|
|
43
66
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
region = regionAnswer;
|
|
68
|
+
}
|
|
69
|
+
const ott = typeof opts.ott === "string" ? opts.ott.trim() : "";
|
|
70
|
+
const ottValue = ott.length > 0 ? ott : (await ask("Enter One-Time Token (OTT)")).trim();
|
|
71
|
+
if (!ottValue) {
|
|
72
|
+
process.stderr.write("OTT is required\n");
|
|
73
|
+
process.exitCode = 1;
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
await exchangeOttAndSave(ottValue, region);
|
|
54
78
|
} catch (err) {
|
|
55
79
|
process.stderr.write(`OTT exchange failed: ${(err as Error).message}\n`);
|
|
56
80
|
process.exitCode = 1;
|
|
@@ -82,32 +106,7 @@ export function register(program: Command): void {
|
|
|
82
106
|
return;
|
|
83
107
|
}
|
|
84
108
|
try {
|
|
85
|
-
|
|
86
|
-
const resp = await fetch(`${base}/api/open/ott/exchange`, {
|
|
87
|
-
method: "POST",
|
|
88
|
-
headers: {
|
|
89
|
-
"content-type": "application/json",
|
|
90
|
-
},
|
|
91
|
-
body: JSON.stringify({ ott }),
|
|
92
|
-
});
|
|
93
|
-
if (!resp.ok) {
|
|
94
|
-
process.stderr.write(`OTT exchange failed: HTTP ${resp.status}\n`);
|
|
95
|
-
process.exitCode = 1;
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
const json = (await resp.json()) as {
|
|
99
|
-
data?: { apiKey?: string };
|
|
100
|
-
[k: string]: unknown;
|
|
101
|
-
};
|
|
102
|
-
const apiKey = json?.data?.apiKey;
|
|
103
|
-
if (typeof apiKey !== "string" || apiKey.length === 0) {
|
|
104
|
-
process.stderr.write("OTT exchange failed: missing data.apiKey in response\n");
|
|
105
|
-
process.exitCode = 1;
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
setConfigValueSync("apiKey", apiKey);
|
|
109
|
-
setConfigValueSync("region", region);
|
|
110
|
-
process.stdout.write("apiKey set via OTT\n");
|
|
109
|
+
await exchangeOttAndSave(ott, region);
|
|
111
110
|
} catch (err) {
|
|
112
111
|
process.stderr.write(`OTT exchange failed: ${(err as Error).message}\n`);
|
|
113
112
|
process.exitCode = 1;
|
package/src/commands/skill.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
|
|
5
6
|
export const name = "skill";
|
|
@@ -15,7 +16,10 @@ function printSkill(relativePath: string): void {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export function register(program: Command): void {
|
|
18
|
-
const parent = program
|
|
19
|
+
const parent = program
|
|
20
|
+
.command("skill")
|
|
21
|
+
.description("Print built-in skill markdown")
|
|
22
|
+
.option("--claude", "Append Claude skill save hint");
|
|
19
23
|
|
|
20
24
|
parent
|
|
21
25
|
.command("one-click-video")
|
|
@@ -31,10 +35,13 @@ export function register(program: Command): void {
|
|
|
31
35
|
printSkill("../skill/edit-video/SKILL.md");
|
|
32
36
|
});
|
|
33
37
|
|
|
34
|
-
parent.action(() => {
|
|
38
|
+
parent.action((opts: { claude?: boolean }) => {
|
|
35
39
|
printSkill("../skill/SKILL.md");
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
if (opts.claude) {
|
|
41
|
+
const savePath = path.join(os.homedir(), ".claude", "skills", "zerocut", "SKILL.md");
|
|
42
|
+
process.stdout.write(
|
|
43
|
+
`\n⚠️ Please save the markdown above to ${savePath} to create the skill.\n`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
39
46
|
});
|
|
40
47
|
}
|
|
@@ -10,6 +10,7 @@ import { register as registerPandoc } from "../commands/pandoc";
|
|
|
10
10
|
import { register as registerSkill } from "../commands/skill";
|
|
11
11
|
import fs from "node:fs";
|
|
12
12
|
import path from "node:path";
|
|
13
|
+
import { pathToFileURL } from "node:url";
|
|
13
14
|
|
|
14
15
|
export function loadBuiltInCommands(program: Command): void {
|
|
15
16
|
registerHelp(program);
|
|
@@ -31,7 +32,8 @@ export async function loadExternalCommandsAsync(program: Command, dir?: string):
|
|
|
31
32
|
for (const f of files) {
|
|
32
33
|
const full = path.join(d, f);
|
|
33
34
|
try {
|
|
34
|
-
const
|
|
35
|
+
const moduleSpecifier = pathToFileURL(full).href;
|
|
36
|
+
const mod = (await import(moduleSpecifier)) as {
|
|
35
37
|
register?: (p: Command) => void;
|
|
36
38
|
default?: (p: Command) => void;
|
|
37
39
|
};
|