@qcplay/cli 1.0.0 → 1.0.2
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/bin/qcplay.js
CHANGED
|
@@ -8,11 +8,35 @@ import { fileURLToPath } from "url";
|
|
|
8
8
|
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
10
|
const __dirname = path.dirname(__filename);
|
|
11
|
+
const PACKAGE_JSON = path.resolve(__dirname, "../package.json");
|
|
12
|
+
|
|
13
|
+
function readPackageVersion() {
|
|
14
|
+
try {
|
|
15
|
+
const packageJson = JSON.parse(fs.readFileSync(PACKAGE_JSON, "utf8"));
|
|
16
|
+
return packageJson.version || "0.0.0";
|
|
17
|
+
} catch {
|
|
18
|
+
return "0.0.0";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const PACKAGE_VERSION = readPackageVersion();
|
|
11
23
|
|
|
12
24
|
const QCPLAY_DIR = path.join(os.homedir(), ".qcplay");
|
|
25
|
+
const AGENTS_DIR = path.join(os.homedir(), ".agents");
|
|
13
26
|
const AUTH_FILE = path.join(QCPLAY_DIR, "auth.json");
|
|
14
27
|
const CONFIG_FILE = path.join(QCPLAY_DIR, "config.json");
|
|
15
|
-
|
|
28
|
+
|
|
29
|
+
function getSkillsDir() {
|
|
30
|
+
const agentsSkillsDir = path.join(AGENTS_DIR, "skills");
|
|
31
|
+
|
|
32
|
+
if (fs.existsSync(agentsSkillsDir) || fs.existsSync(AGENTS_DIR)) {
|
|
33
|
+
return agentsSkillsDir;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return path.join(QCPLAY_DIR, "skills");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const SKILLS_DIR = getSkillsDir();
|
|
16
40
|
|
|
17
41
|
const colorsEnabled = process.stdout.isTTY && process.env.NO_COLOR !== "1";
|
|
18
42
|
|
|
@@ -38,6 +62,7 @@ function printRootHelp() {
|
|
|
38
62
|
Usage:
|
|
39
63
|
qcplay-cli install
|
|
40
64
|
qcplay-cli auth [login|status|logout]
|
|
65
|
+
qcplay-cli auth permissions [--key <key>] [--json]
|
|
41
66
|
qcplay-cli article
|
|
42
67
|
qcplay-cli article init [file]
|
|
43
68
|
qcplay-cli article publish <file> [--env <env>] [--url <url>] [--dry-run]
|
|
@@ -56,6 +81,7 @@ function printAuthHelp() {
|
|
|
56
81
|
console.log(" qcplay-cli auth");
|
|
57
82
|
console.log(" qcplay-cli auth status");
|
|
58
83
|
console.log(" qcplay-cli auth logout");
|
|
84
|
+
console.log(" qcplay-cli auth permissions [--key <key>] [--json]");
|
|
59
85
|
}
|
|
60
86
|
|
|
61
87
|
function printArticleHelp() {
|
|
@@ -81,9 +107,34 @@ function getVendorDir() {
|
|
|
81
107
|
throw new Error(`Unsupported platform: ${process.platform}`);
|
|
82
108
|
}
|
|
83
109
|
|
|
110
|
+
function getExeCandidates(name) {
|
|
111
|
+
if (process.platform === "win32") {
|
|
112
|
+
return [`${name}.exe`, name];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (process.platform === "darwin") {
|
|
116
|
+
return [`${name}-darwin-${process.arch}`, name];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (process.platform === "linux") {
|
|
120
|
+
return [`${name}-linux-${process.arch}`, name];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return [name];
|
|
124
|
+
}
|
|
125
|
+
|
|
84
126
|
function getExePath(name) {
|
|
85
127
|
const vendorDir = getVendorDir();
|
|
86
|
-
|
|
128
|
+
const candidates = getExeCandidates(name);
|
|
129
|
+
|
|
130
|
+
for (const candidate of candidates) {
|
|
131
|
+
const exePath = path.join(vendorDir, candidate);
|
|
132
|
+
if (fs.existsSync(exePath)) {
|
|
133
|
+
return exePath;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return path.join(vendorDir, candidates[0]);
|
|
87
138
|
}
|
|
88
139
|
|
|
89
140
|
function runNative(name, args = []) {
|
|
@@ -114,6 +165,20 @@ function runNative(name, args = []) {
|
|
|
114
165
|
});
|
|
115
166
|
}
|
|
116
167
|
|
|
168
|
+
async function runAuthLogin() {
|
|
169
|
+
try {
|
|
170
|
+
await runNative("qcplay-auth", []);
|
|
171
|
+
} catch (err) {
|
|
172
|
+
const message = String(err?.message || err);
|
|
173
|
+
|
|
174
|
+
if (!message.includes("退出码")) {
|
|
175
|
+
throw err;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
await runNative("qcplay-auth", ["login"]);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
117
182
|
async function pathExists(targetPath) {
|
|
118
183
|
try {
|
|
119
184
|
await fs.promises.access(targetPath);
|
|
@@ -176,7 +241,7 @@ async function installSkills() {
|
|
|
176
241
|
async function saveConfig() {
|
|
177
242
|
await writeJson(CONFIG_FILE, {
|
|
178
243
|
cli: "qcplay-cli",
|
|
179
|
-
version:
|
|
244
|
+
version: PACKAGE_VERSION,
|
|
180
245
|
auth_file: AUTH_FILE,
|
|
181
246
|
skills_dir: SKILLS_DIR,
|
|
182
247
|
configured_at: Date.now()
|
|
@@ -252,6 +317,11 @@ function printFeatures() {
|
|
|
252
317
|
console.log(" qcplay-cli auth");
|
|
253
318
|
console.log("");
|
|
254
319
|
|
|
320
|
+
console.log(chalk.cyan("2. 查看权限"));
|
|
321
|
+
console.log(" qcplay-cli auth permissions");
|
|
322
|
+
console.log(" qcplay-cli auth permissions --key www-article-list.store");
|
|
323
|
+
console.log("");
|
|
324
|
+
|
|
255
325
|
console.log(chalk.cyan("4. 发布官网文章"));
|
|
256
326
|
console.log(" qcplay-cli www-article-list.store article.md");
|
|
257
327
|
console.log(chalk.gray(" 文章标题、分类、缩略图、标签等信息写在 article.md 顶部 Front Matter 中。"));
|
|
@@ -266,6 +336,37 @@ function printWhere() {
|
|
|
266
336
|
console.log(QCPLAY_DIR);
|
|
267
337
|
}
|
|
268
338
|
|
|
339
|
+
function parsePermissionsOptions(args) {
|
|
340
|
+
const options = {
|
|
341
|
+
key: undefined,
|
|
342
|
+
json: false
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
346
|
+
const current = args[index];
|
|
347
|
+
|
|
348
|
+
if (current === "--json") {
|
|
349
|
+
options.json = true;
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (current === "--key") {
|
|
354
|
+
const next = args[index + 1];
|
|
355
|
+
if (!next || next.startsWith("--")) {
|
|
356
|
+
throw new Error("--key 缺少参数值");
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
options.key = next;
|
|
360
|
+
index += 1;
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
throw new Error(`未知参数: ${current}`);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return options;
|
|
368
|
+
}
|
|
369
|
+
|
|
269
370
|
async function installCommand() {
|
|
270
371
|
console.log("");
|
|
271
372
|
console.log(chalk.cyan("正在安装 QCPlay CLI..."));
|
|
@@ -277,6 +378,7 @@ async function installCommand() {
|
|
|
277
378
|
const skillsInstalled = await installSkills();
|
|
278
379
|
if (skillsInstalled) {
|
|
279
380
|
console.log(chalk.green("✔ Skills 已安装"));
|
|
381
|
+
console.log(`Skills 目录: ${chalk.gray(SKILLS_DIR)}`);
|
|
280
382
|
} else {
|
|
281
383
|
console.log(chalk.yellow("! 未找到 Skills 模板,已跳过"));
|
|
282
384
|
}
|
|
@@ -289,39 +391,32 @@ async function installCommand() {
|
|
|
289
391
|
console.log(chalk.gray("请在浏览器中完成账号密码登录。"));
|
|
290
392
|
console.log("");
|
|
291
393
|
|
|
292
|
-
await
|
|
394
|
+
await runAuthLogin();
|
|
293
395
|
|
|
294
396
|
const loginStatus = await getLoginStatus();
|
|
295
397
|
if (!loginStatus.ok) {
|
|
296
398
|
throw new Error(`登录流程结束,但未检测到有效认证文件。\n原因: ${loginStatus.reason}`);
|
|
297
399
|
}
|
|
298
400
|
|
|
299
|
-
console.log("");
|
|
300
|
-
console.log(chalk.green("✔ 登录成功"));
|
|
301
|
-
console.log(`认证文件: ${chalk.gray(AUTH_FILE)}`);
|
|
302
|
-
|
|
303
401
|
console.log("");
|
|
304
402
|
console.log(chalk.green("✔ QCPlay CLI 安装完成"));
|
|
305
403
|
|
|
306
404
|
printFeatures();
|
|
307
405
|
}
|
|
308
406
|
|
|
309
|
-
async function authCommand(action) {
|
|
407
|
+
async function authCommand(action, args = []) {
|
|
310
408
|
if (!action || action === "login") {
|
|
311
409
|
console.log("");
|
|
312
410
|
console.log(chalk.cyan("正在打开 QCPlay 登录窗口..."));
|
|
313
411
|
console.log("");
|
|
314
412
|
|
|
315
|
-
await
|
|
413
|
+
await runAuthLogin();
|
|
316
414
|
|
|
317
415
|
const loginStatus = await getLoginStatus();
|
|
318
416
|
if (!loginStatus.ok) {
|
|
319
417
|
throw new Error(`登录失败。\n原因: ${loginStatus.reason}`);
|
|
320
418
|
}
|
|
321
419
|
|
|
322
|
-
console.log("");
|
|
323
|
-
console.log(chalk.green("✔ 登录成功"));
|
|
324
|
-
console.log(`认证文件: ${chalk.gray(AUTH_FILE)}`);
|
|
325
420
|
return;
|
|
326
421
|
}
|
|
327
422
|
|
|
@@ -338,7 +433,6 @@ async function authCommand(action) {
|
|
|
338
433
|
}
|
|
339
434
|
|
|
340
435
|
console.log(chalk.green("已登录"));
|
|
341
|
-
console.log(`认证文件: ${AUTH_FILE}`);
|
|
342
436
|
return;
|
|
343
437
|
}
|
|
344
438
|
|
|
@@ -348,6 +442,28 @@ async function authCommand(action) {
|
|
|
348
442
|
return;
|
|
349
443
|
}
|
|
350
444
|
|
|
445
|
+
if (action === "permissions") {
|
|
446
|
+
const loginStatus = await getLoginStatus();
|
|
447
|
+
|
|
448
|
+
if (!loginStatus.ok) {
|
|
449
|
+
throw new Error(`未检测到有效登录状态。\n原因: ${loginStatus.reason}\n请先执行:qcplay-cli auth`);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
const options = parsePermissionsOptions(args);
|
|
453
|
+
const nativeArgs = ["permissions"];
|
|
454
|
+
|
|
455
|
+
if (options.key) {
|
|
456
|
+
nativeArgs.push("--key", options.key);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (options.json) {
|
|
460
|
+
nativeArgs.push("--json");
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
await runNative("qcplay-auth", nativeArgs);
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
|
|
351
467
|
printAuthHelp();
|
|
352
468
|
}
|
|
353
469
|
|
|
@@ -584,7 +700,7 @@ async function main() {
|
|
|
584
700
|
}
|
|
585
701
|
|
|
586
702
|
if (command === "-V" || command === "--version") {
|
|
587
|
-
console.log(
|
|
703
|
+
console.log(PACKAGE_VERSION);
|
|
588
704
|
return;
|
|
589
705
|
}
|
|
590
706
|
|
|
@@ -599,7 +715,7 @@ async function main() {
|
|
|
599
715
|
return;
|
|
600
716
|
}
|
|
601
717
|
|
|
602
|
-
await runWithErrorBanner("认证失败", () => authCommand(subcommand));
|
|
718
|
+
await runWithErrorBanner("认证失败", () => authCommand(subcommand, rest));
|
|
603
719
|
return;
|
|
604
720
|
}
|
|
605
721
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qcplay/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "QCPlay CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"registry": "https://registry.npmjs.org/"
|
|
19
19
|
},
|
|
20
20
|
"engines": {
|
|
21
|
-
"node": ">=16
|
|
21
|
+
"node": ">=16",
|
|
22
22
|
"npm": ">=8"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
@@ -204,6 +204,12 @@ Windows 示例:
|
|
|
204
204
|
C:\Users\Administrator\.qcplay\auth.json
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
+
macOS 示例:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
/Users/<your-name>/.qcplay/auth.json
|
|
211
|
+
```
|
|
212
|
+
|
|
207
213
|
认证文件格式:
|
|
208
214
|
|
|
209
215
|
```json
|
|
@@ -1158,4 +1164,4 @@ Node 只做路由。
|
|
|
1158
1164
|
Go 负责发布。
|
|
1159
1165
|
默认参数程序内部补齐。
|
|
1160
1166
|
发布失败不得伪造成成功。
|
|
1161
|
-
```
|
|
1167
|
+
```
|
|
Binary file
|
|
Binary file
|
|
Binary file
|