@qzhuli/qzhuli-cli 0.1.0 → 0.2.1
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/LICENSE +21 -0
- package/dist/cmd.js +227 -153
- package/package.json +3 -1
- package/skills/qzhuli-cli/SKILL.md +166 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 H
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/cmd.js
CHANGED
|
@@ -11435,14 +11435,191 @@ function tf(key, values) {
|
|
|
11435
11435
|
|
|
11436
11436
|
// src/iostreams.ts
|
|
11437
11437
|
init_cjs_shims();
|
|
11438
|
+
|
|
11439
|
+
// src/internal/config/index.ts
|
|
11440
|
+
init_cjs_shims();
|
|
11441
|
+
|
|
11442
|
+
// src/internal/config/credentials.ts
|
|
11443
|
+
init_cjs_shims();
|
|
11444
|
+
var import_node_fs = require("fs");
|
|
11445
|
+
var import_node_path = require("path");
|
|
11446
|
+
function loadCredentials(configDir) {
|
|
11447
|
+
const path = (0, import_node_path.join)(configDir, "credentials.json");
|
|
11448
|
+
if (!(0, import_node_fs.existsSync)(path)) {
|
|
11449
|
+
return null;
|
|
11450
|
+
}
|
|
11451
|
+
try {
|
|
11452
|
+
const raw = (0, import_node_fs.readFileSync)(path, "utf-8");
|
|
11453
|
+
return JSON.parse(raw);
|
|
11454
|
+
} catch {
|
|
11455
|
+
console.error("[WARN] credentials.json is corrupted, skipping \u2014 please re-authenticate");
|
|
11456
|
+
return null;
|
|
11457
|
+
}
|
|
11458
|
+
}
|
|
11459
|
+
function saveCredentials(configDir, creds) {
|
|
11460
|
+
const path = (0, import_node_path.join)(configDir, "credentials.json");
|
|
11461
|
+
ensureConfigDirectory(configDir);
|
|
11462
|
+
(0, import_node_fs.writeFileSync)(path, JSON.stringify(creds, null, 2), {
|
|
11463
|
+
encoding: "utf-8",
|
|
11464
|
+
mode: 384
|
|
11465
|
+
});
|
|
11466
|
+
}
|
|
11467
|
+
function ensureConfigDirectory(configDir) {
|
|
11468
|
+
if (!(0, import_node_fs.existsSync)(configDir)) {
|
|
11469
|
+
(0, import_node_fs.mkdirSync)(configDir, { recursive: true });
|
|
11470
|
+
}
|
|
11471
|
+
}
|
|
11472
|
+
function clearCredentials(configDir) {
|
|
11473
|
+
const path = (0, import_node_path.join)(configDir, "credentials.json");
|
|
11474
|
+
if ((0, import_node_fs.existsSync)(path)) {
|
|
11475
|
+
(0, import_node_fs.rmSync)(path);
|
|
11476
|
+
}
|
|
11477
|
+
}
|
|
11478
|
+
function hasCredentials(configDir) {
|
|
11479
|
+
const creds = loadCredentials(configDir);
|
|
11480
|
+
return !!(creds?.uid && creds?.tk && creds?.token);
|
|
11481
|
+
}
|
|
11482
|
+
|
|
11483
|
+
// src/internal/config/directory.ts
|
|
11484
|
+
init_cjs_shims();
|
|
11485
|
+
var import_node_os = require("os");
|
|
11486
|
+
var import_node_path2 = require("path");
|
|
11487
|
+
var PROJECT_CONFIG_DIR = (0, import_node_path2.resolve)(process.cwd(), ".qzhuli-cli");
|
|
11488
|
+
var USER_CONFIG_DIR = (0, import_node_path2.resolve)((0, import_node_os.homedir)(), ".qzhuli-cli");
|
|
11489
|
+
function getConfigDirectory(env) {
|
|
11490
|
+
return env === "production" ? USER_CONFIG_DIR : PROJECT_CONFIG_DIR;
|
|
11491
|
+
}
|
|
11492
|
+
|
|
11493
|
+
// src/internal/config/environment.ts
|
|
11494
|
+
init_cjs_shims();
|
|
11495
|
+
var TEST_CONFIG = {
|
|
11496
|
+
name: "test",
|
|
11497
|
+
baseURL: "https://test.client.qzhuli.com",
|
|
11498
|
+
wsURL: "wss://test.im.qzhuli.com/ws"
|
|
11499
|
+
};
|
|
11500
|
+
var PRODUCTION_CONFIG = {
|
|
11501
|
+
name: "production",
|
|
11502
|
+
baseURL: "https://client.qzhuli.com",
|
|
11503
|
+
wsURL: "wss://im.qzhuli.com/ws"
|
|
11504
|
+
};
|
|
11505
|
+
var ENV_MAP = {
|
|
11506
|
+
test: TEST_CONFIG,
|
|
11507
|
+
production: PRODUCTION_CONFIG
|
|
11508
|
+
};
|
|
11509
|
+
function getEnvironmentConfig(name) {
|
|
11510
|
+
return ENV_MAP[name];
|
|
11511
|
+
}
|
|
11512
|
+
function detectEnvironment() {
|
|
11513
|
+
return false ? "test" : "production";
|
|
11514
|
+
}
|
|
11515
|
+
|
|
11516
|
+
// src/internal/config/preferences.ts
|
|
11517
|
+
init_cjs_shims();
|
|
11518
|
+
var import_node_fs2 = require("fs");
|
|
11519
|
+
var import_node_path3 = require("path");
|
|
11520
|
+
var DEFAULTS = {
|
|
11521
|
+
locale: "zh"
|
|
11522
|
+
};
|
|
11523
|
+
function loadPreferences(configDir) {
|
|
11524
|
+
const path = (0, import_node_path3.join)(configDir, "preferences.json");
|
|
11525
|
+
if (!(0, import_node_fs2.existsSync)(path)) {
|
|
11526
|
+
return { ...DEFAULTS };
|
|
11527
|
+
}
|
|
11528
|
+
try {
|
|
11529
|
+
const raw = (0, import_node_fs2.readFileSync)(path, "utf-8");
|
|
11530
|
+
const parsed = JSON.parse(raw);
|
|
11531
|
+
return { ...DEFAULTS, ...parsed };
|
|
11532
|
+
} catch {
|
|
11533
|
+
return { ...DEFAULTS };
|
|
11534
|
+
}
|
|
11535
|
+
}
|
|
11536
|
+
function savePreferences(configDir, updates) {
|
|
11537
|
+
if (isDryRun()) {
|
|
11538
|
+
return;
|
|
11539
|
+
}
|
|
11540
|
+
const current = loadPreferences(configDir);
|
|
11541
|
+
const merged = { ...current, ...updates };
|
|
11542
|
+
const path = (0, import_node_path3.join)(configDir, "preferences.json");
|
|
11543
|
+
ensureConfigDirectory2(configDir);
|
|
11544
|
+
(0, import_node_fs2.writeFileSync)(path, JSON.stringify(merged, null, 2), {
|
|
11545
|
+
encoding: "utf-8",
|
|
11546
|
+
mode: 384
|
|
11547
|
+
});
|
|
11548
|
+
}
|
|
11549
|
+
function ensureConfigDirectory2(configDir) {
|
|
11550
|
+
if (!(0, import_node_fs2.existsSync)(configDir)) {
|
|
11551
|
+
(0, import_node_fs2.mkdirSync)(configDir, { recursive: true });
|
|
11552
|
+
}
|
|
11553
|
+
}
|
|
11554
|
+
function initDefaultPreferences(configDir) {
|
|
11555
|
+
const path = (0, import_node_path3.join)(configDir, "preferences.json");
|
|
11556
|
+
if (!(0, import_node_fs2.existsSync)(path)) {
|
|
11557
|
+
ensureConfigDirectory2(configDir);
|
|
11558
|
+
(0, import_node_fs2.writeFileSync)(path, JSON.stringify(DEFAULTS, null, 2), {
|
|
11559
|
+
encoding: "utf-8",
|
|
11560
|
+
mode: 384
|
|
11561
|
+
});
|
|
11562
|
+
}
|
|
11563
|
+
}
|
|
11564
|
+
|
|
11565
|
+
// src/internal/config/index.ts
|
|
11566
|
+
function loadAppConfig(env) {
|
|
11567
|
+
const envName = env ?? detectEnvironment();
|
|
11568
|
+
const configDir = getConfigDirectory(envName);
|
|
11569
|
+
initDefaultPreferences(configDir);
|
|
11570
|
+
const envConfig = getEnvironmentConfig(envName);
|
|
11571
|
+
const prefs = loadPreferences(configDir);
|
|
11572
|
+
const creds = loadCredentials(configDir);
|
|
11573
|
+
const uid = creds?.uid || null;
|
|
11574
|
+
const tk = creds?.tk || null;
|
|
11575
|
+
const token = creds?.token || null;
|
|
11576
|
+
const cid = creds?.cid || null;
|
|
11577
|
+
return {
|
|
11578
|
+
uid,
|
|
11579
|
+
tk,
|
|
11580
|
+
token,
|
|
11581
|
+
cid,
|
|
11582
|
+
locale: prefs.locale ?? "en",
|
|
11583
|
+
debug: prefs.debug ?? false,
|
|
11584
|
+
baseURL: envConfig.baseURL,
|
|
11585
|
+
wsURL: envConfig.wsURL
|
|
11586
|
+
};
|
|
11587
|
+
}
|
|
11588
|
+
|
|
11589
|
+
// src/internal/config/logs.ts
|
|
11590
|
+
init_cjs_shims();
|
|
11591
|
+
var import_node_fs3 = require("fs");
|
|
11592
|
+
var import_node_path4 = require("path");
|
|
11593
|
+
function appendCliRunLog(configDir, entry, now = /* @__PURE__ */ new Date()) {
|
|
11594
|
+
const logDir = (0, import_node_path4.join)(configDir, "logs");
|
|
11595
|
+
(0, import_node_fs3.mkdirSync)(logDir, { recursive: true });
|
|
11596
|
+
(0, import_node_fs3.appendFileSync)(
|
|
11597
|
+
(0, import_node_path4.join)(logDir, `${formatLocalDate(now)}.log`),
|
|
11598
|
+
`${JSON.stringify(entry)}
|
|
11599
|
+
`,
|
|
11600
|
+
"utf-8"
|
|
11601
|
+
);
|
|
11602
|
+
}
|
|
11603
|
+
function formatLocalDate(value) {
|
|
11604
|
+
const year = value.getFullYear();
|
|
11605
|
+
const month = String(value.getMonth() + 1).padStart(2, "0");
|
|
11606
|
+
const day = String(value.getDate()).padStart(2, "0");
|
|
11607
|
+
return `${year}-${month}-${day}`;
|
|
11608
|
+
}
|
|
11609
|
+
|
|
11610
|
+
// src/iostreams.ts
|
|
11438
11611
|
var jqFilter = null;
|
|
11439
11612
|
var dryRun = false;
|
|
11613
|
+
var logDebug = false;
|
|
11440
11614
|
function setJqFilter(expr) {
|
|
11441
11615
|
jqFilter = expr;
|
|
11442
11616
|
}
|
|
11443
11617
|
function setDryRun(enabled) {
|
|
11444
11618
|
dryRun = enabled;
|
|
11445
11619
|
}
|
|
11620
|
+
function setLogDebug(enabled) {
|
|
11621
|
+
logDebug = enabled;
|
|
11622
|
+
}
|
|
11446
11623
|
function isDryRun() {
|
|
11447
11624
|
return dryRun;
|
|
11448
11625
|
}
|
|
@@ -11473,11 +11650,34 @@ function printStatus(status) {
|
|
|
11473
11650
|
`);
|
|
11474
11651
|
}
|
|
11475
11652
|
function handleCommand(result) {
|
|
11653
|
+
appendStatusLog(result);
|
|
11476
11654
|
printStatus(result);
|
|
11477
11655
|
if (!isDryRun() && result.status === "error") {
|
|
11478
11656
|
process.exit(1);
|
|
11479
11657
|
}
|
|
11480
11658
|
}
|
|
11659
|
+
function appendStatusLog(status) {
|
|
11660
|
+
const argv = process.argv.slice(2);
|
|
11661
|
+
try {
|
|
11662
|
+
appendCliRunLog(getConfigDirectory(detectEnvironment()), {
|
|
11663
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11664
|
+
argv,
|
|
11665
|
+
command: argv.join(" "),
|
|
11666
|
+
status: status.status,
|
|
11667
|
+
code: status.code,
|
|
11668
|
+
message: status.message,
|
|
11669
|
+
data: status.data,
|
|
11670
|
+
dryRun
|
|
11671
|
+
});
|
|
11672
|
+
} catch (error) {
|
|
11673
|
+
if (logDebug) {
|
|
11674
|
+
process.stderr.write(
|
|
11675
|
+
`[DEBUG] Failed to write CLI log: ${error instanceof Error ? error.message : String(error)}
|
|
11676
|
+
`
|
|
11677
|
+
);
|
|
11678
|
+
}
|
|
11679
|
+
}
|
|
11680
|
+
}
|
|
11481
11681
|
|
|
11482
11682
|
// src/commands/auth/login.ts
|
|
11483
11683
|
init_cjs_shims();
|
|
@@ -11914,156 +12114,6 @@ function promptRefresh(controller, onReset) {
|
|
|
11914
12114
|
});
|
|
11915
12115
|
}
|
|
11916
12116
|
|
|
11917
|
-
// src/internal/config/index.ts
|
|
11918
|
-
init_cjs_shims();
|
|
11919
|
-
|
|
11920
|
-
// src/internal/config/credentials.ts
|
|
11921
|
-
init_cjs_shims();
|
|
11922
|
-
var import_node_fs = require("fs");
|
|
11923
|
-
var import_node_path = require("path");
|
|
11924
|
-
function loadCredentials(configDir) {
|
|
11925
|
-
const path = (0, import_node_path.join)(configDir, "credentials.json");
|
|
11926
|
-
if (!(0, import_node_fs.existsSync)(path)) {
|
|
11927
|
-
return null;
|
|
11928
|
-
}
|
|
11929
|
-
try {
|
|
11930
|
-
const raw = (0, import_node_fs.readFileSync)(path, "utf-8");
|
|
11931
|
-
return JSON.parse(raw);
|
|
11932
|
-
} catch {
|
|
11933
|
-
console.error("[WARN] credentials.json is corrupted, skipping \u2014 please re-authenticate");
|
|
11934
|
-
return null;
|
|
11935
|
-
}
|
|
11936
|
-
}
|
|
11937
|
-
function saveCredentials(configDir, creds) {
|
|
11938
|
-
const path = (0, import_node_path.join)(configDir, "credentials.json");
|
|
11939
|
-
ensureConfigDirectory(configDir);
|
|
11940
|
-
(0, import_node_fs.writeFileSync)(path, JSON.stringify(creds, null, 2), {
|
|
11941
|
-
encoding: "utf-8",
|
|
11942
|
-
mode: 384
|
|
11943
|
-
});
|
|
11944
|
-
}
|
|
11945
|
-
function ensureConfigDirectory(configDir) {
|
|
11946
|
-
if (!(0, import_node_fs.existsSync)(configDir)) {
|
|
11947
|
-
(0, import_node_fs.mkdirSync)(configDir, { recursive: true });
|
|
11948
|
-
}
|
|
11949
|
-
}
|
|
11950
|
-
function clearCredentials(configDir) {
|
|
11951
|
-
const path = (0, import_node_path.join)(configDir, "credentials.json");
|
|
11952
|
-
if ((0, import_node_fs.existsSync)(path)) {
|
|
11953
|
-
(0, import_node_fs.rmSync)(path);
|
|
11954
|
-
}
|
|
11955
|
-
}
|
|
11956
|
-
function hasCredentials(configDir) {
|
|
11957
|
-
const creds = loadCredentials(configDir);
|
|
11958
|
-
return !!(creds?.uid && creds?.tk && creds?.token);
|
|
11959
|
-
}
|
|
11960
|
-
|
|
11961
|
-
// src/internal/config/directory.ts
|
|
11962
|
-
init_cjs_shims();
|
|
11963
|
-
var import_node_os = require("os");
|
|
11964
|
-
var import_node_path2 = require("path");
|
|
11965
|
-
var PROJECT_CONFIG_DIR = (0, import_node_path2.resolve)(process.cwd(), ".qzhuli-cli");
|
|
11966
|
-
var USER_CONFIG_DIR = (0, import_node_path2.resolve)((0, import_node_os.homedir)(), ".qzhuli-cli");
|
|
11967
|
-
function getConfigDirectory(env) {
|
|
11968
|
-
return env === "production" ? USER_CONFIG_DIR : PROJECT_CONFIG_DIR;
|
|
11969
|
-
}
|
|
11970
|
-
|
|
11971
|
-
// src/internal/config/environment.ts
|
|
11972
|
-
init_cjs_shims();
|
|
11973
|
-
var TEST_CONFIG = {
|
|
11974
|
-
name: "test",
|
|
11975
|
-
baseURL: "https://test.client.qzhuli.com",
|
|
11976
|
-
wsURL: "wss://test.im.qzhuli.com/ws"
|
|
11977
|
-
};
|
|
11978
|
-
var PRODUCTION_CONFIG = {
|
|
11979
|
-
name: "production",
|
|
11980
|
-
baseURL: "https://client.qzhuli.com",
|
|
11981
|
-
wsURL: "wss://im.qzhuli.com/ws"
|
|
11982
|
-
};
|
|
11983
|
-
var ENV_MAP = {
|
|
11984
|
-
test: TEST_CONFIG,
|
|
11985
|
-
production: PRODUCTION_CONFIG
|
|
11986
|
-
};
|
|
11987
|
-
function getEnvironmentConfig(name) {
|
|
11988
|
-
return ENV_MAP[name];
|
|
11989
|
-
}
|
|
11990
|
-
function detectEnvironment() {
|
|
11991
|
-
return false ? "test" : "production";
|
|
11992
|
-
}
|
|
11993
|
-
|
|
11994
|
-
// src/internal/config/preferences.ts
|
|
11995
|
-
init_cjs_shims();
|
|
11996
|
-
var import_node_fs2 = require("fs");
|
|
11997
|
-
var import_node_path3 = require("path");
|
|
11998
|
-
var DEFAULTS = {
|
|
11999
|
-
locale: "zh"
|
|
12000
|
-
};
|
|
12001
|
-
function loadPreferences(configDir) {
|
|
12002
|
-
const path = (0, import_node_path3.join)(configDir, "preferences.json");
|
|
12003
|
-
if (!(0, import_node_fs2.existsSync)(path)) {
|
|
12004
|
-
return { ...DEFAULTS };
|
|
12005
|
-
}
|
|
12006
|
-
try {
|
|
12007
|
-
const raw = (0, import_node_fs2.readFileSync)(path, "utf-8");
|
|
12008
|
-
const parsed = JSON.parse(raw);
|
|
12009
|
-
return { ...DEFAULTS, ...parsed };
|
|
12010
|
-
} catch {
|
|
12011
|
-
return { ...DEFAULTS };
|
|
12012
|
-
}
|
|
12013
|
-
}
|
|
12014
|
-
function savePreferences(configDir, updates) {
|
|
12015
|
-
if (isDryRun()) {
|
|
12016
|
-
return;
|
|
12017
|
-
}
|
|
12018
|
-
const current = loadPreferences(configDir);
|
|
12019
|
-
const merged = { ...current, ...updates };
|
|
12020
|
-
const path = (0, import_node_path3.join)(configDir, "preferences.json");
|
|
12021
|
-
ensureConfigDirectory2(configDir);
|
|
12022
|
-
(0, import_node_fs2.writeFileSync)(path, JSON.stringify(merged, null, 2), {
|
|
12023
|
-
encoding: "utf-8",
|
|
12024
|
-
mode: 384
|
|
12025
|
-
});
|
|
12026
|
-
}
|
|
12027
|
-
function ensureConfigDirectory2(configDir) {
|
|
12028
|
-
if (!(0, import_node_fs2.existsSync)(configDir)) {
|
|
12029
|
-
(0, import_node_fs2.mkdirSync)(configDir, { recursive: true });
|
|
12030
|
-
}
|
|
12031
|
-
}
|
|
12032
|
-
function initDefaultPreferences(configDir) {
|
|
12033
|
-
const path = (0, import_node_path3.join)(configDir, "preferences.json");
|
|
12034
|
-
if (!(0, import_node_fs2.existsSync)(path)) {
|
|
12035
|
-
ensureConfigDirectory2(configDir);
|
|
12036
|
-
(0, import_node_fs2.writeFileSync)(path, JSON.stringify(DEFAULTS, null, 2), {
|
|
12037
|
-
encoding: "utf-8",
|
|
12038
|
-
mode: 384
|
|
12039
|
-
});
|
|
12040
|
-
}
|
|
12041
|
-
}
|
|
12042
|
-
|
|
12043
|
-
// src/internal/config/index.ts
|
|
12044
|
-
function loadAppConfig(env) {
|
|
12045
|
-
const envName = env ?? detectEnvironment();
|
|
12046
|
-
const configDir = getConfigDirectory(envName);
|
|
12047
|
-
initDefaultPreferences(configDir);
|
|
12048
|
-
const envConfig = getEnvironmentConfig(envName);
|
|
12049
|
-
const prefs = loadPreferences(configDir);
|
|
12050
|
-
const creds = loadCredentials(configDir);
|
|
12051
|
-
const uid = creds?.uid || null;
|
|
12052
|
-
const tk = creds?.tk || null;
|
|
12053
|
-
const token = creds?.token || null;
|
|
12054
|
-
const cid = creds?.cid || null;
|
|
12055
|
-
return {
|
|
12056
|
-
uid,
|
|
12057
|
-
tk,
|
|
12058
|
-
token,
|
|
12059
|
-
cid,
|
|
12060
|
-
locale: prefs.locale ?? "en",
|
|
12061
|
-
debug: prefs.debug ?? false,
|
|
12062
|
-
baseURL: envConfig.baseURL,
|
|
12063
|
-
wsURL: envConfig.wsURL
|
|
12064
|
-
};
|
|
12065
|
-
}
|
|
12066
|
-
|
|
12067
12117
|
// src/commands/auth/login.ts
|
|
12068
12118
|
async function authLoginRun(factory, opts) {
|
|
12069
12119
|
try {
|
|
@@ -13529,7 +13579,7 @@ var IMGateway = class {
|
|
|
13529
13579
|
return {
|
|
13530
13580
|
status: "success",
|
|
13531
13581
|
code: "CONVERSATION_LIST" /* CONVERSATION_LIST */,
|
|
13532
|
-
message: conversations3.length > 0 ?
|
|
13582
|
+
message: conversations3.length > 0 ? `Conversations (${conversations3.length}):` : "No conversations found.",
|
|
13533
13583
|
data: { conversations: conversations3 }
|
|
13534
13584
|
};
|
|
13535
13585
|
} catch (error) {
|
|
@@ -13589,6 +13639,7 @@ function createFactory(config) {
|
|
|
13589
13639
|
}
|
|
13590
13640
|
|
|
13591
13641
|
// src/cmd.ts
|
|
13642
|
+
var logDebugEnabled = false;
|
|
13592
13643
|
var LocalizedHelp = class extends import_commander8.Help {
|
|
13593
13644
|
/** Format an argument name with <required> or [optional] brackets. */
|
|
13594
13645
|
argDisplayName(arg) {
|
|
@@ -13629,6 +13680,8 @@ async function main() {
|
|
|
13629
13680
|
const envName = detectEnvironment();
|
|
13630
13681
|
const config = loadAppConfig(envName);
|
|
13631
13682
|
setLocale(config.locale);
|
|
13683
|
+
logDebugEnabled = config.debug;
|
|
13684
|
+
setLogDebug(config.debug);
|
|
13632
13685
|
const factory = createFactory(config);
|
|
13633
13686
|
const program = new import_commander8.Command();
|
|
13634
13687
|
const testModeBanner = `
|
|
@@ -13641,7 +13694,7 @@ async function main() {
|
|
|
13641
13694
|
${t("cli.banner")}` : t("cli.banner");
|
|
13642
13695
|
program.addHelpText("beforeAll", `${banner}
|
|
13643
13696
|
`);
|
|
13644
|
-
program.name("qz").version(`v${"0.1
|
|
13697
|
+
program.name("qz").version(`v${"0.2.1"}`, "-v, --version", t("options.version")).helpOption("-h, --help", t("options.help")).option("-q, --jq <expr>", t("options.jq")).option("--dry-run", t("options.dryRun"));
|
|
13645
13698
|
program.usage("<command> [subcommand] [options]");
|
|
13646
13699
|
program.hook("preAction", () => {
|
|
13647
13700
|
const opts = program.opts();
|
|
@@ -13667,6 +13720,27 @@ ${t("messages.helpFooter")}
|
|
|
13667
13720
|
await program.parseAsync(process.argv);
|
|
13668
13721
|
}
|
|
13669
13722
|
main().catch((err) => {
|
|
13670
|
-
|
|
13723
|
+
const envName = detectEnvironment();
|
|
13724
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
13725
|
+
try {
|
|
13726
|
+
appendCliRunLog(getConfigDirectory(envName), {
|
|
13727
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
13728
|
+
argv: process.argv.slice(2),
|
|
13729
|
+
command: process.argv.slice(2).join(" "),
|
|
13730
|
+
status: "error",
|
|
13731
|
+
code: "INTERNAL_ERROR" /* INTERNAL_ERROR */,
|
|
13732
|
+
message,
|
|
13733
|
+
data: null,
|
|
13734
|
+
dryRun: process.argv.includes("--dry-run")
|
|
13735
|
+
});
|
|
13736
|
+
} catch (logError) {
|
|
13737
|
+
if (logDebugEnabled) {
|
|
13738
|
+
process.stderr.write(
|
|
13739
|
+
`[DEBUG] Failed to write CLI log: ${logError instanceof Error ? logError.message : String(logError)}
|
|
13740
|
+
`
|
|
13741
|
+
);
|
|
13742
|
+
}
|
|
13743
|
+
}
|
|
13744
|
+
console.error(`Error: ${message}`);
|
|
13671
13745
|
process.exit(1);
|
|
13672
13746
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qzhuli/qzhuli-cli",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "CLI tool for Q助理 (QZhuli)",
|
|
5
5
|
"main": "dist/cmd.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
+
"skills",
|
|
11
12
|
"README.md",
|
|
12
13
|
"CONTRIBUTING.md"
|
|
13
14
|
],
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
"qzhuli"
|
|
36
37
|
],
|
|
37
38
|
"author": "shootdev <npmjs@aisheshou.com>",
|
|
39
|
+
"license": "MIT",
|
|
38
40
|
"packageManager": "pnpm@10.33.0",
|
|
39
41
|
"engines": {
|
|
40
42
|
"node": ">=18.0.0"
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qzhuli-cli
|
|
3
|
+
description: Use when operating the QZhuli CLI with qz, including login, auth status, config, friends, relations, users, conversations, messages, JSON filtering, dry-run, command help, and interpreting test-environment banners or config files.
|
|
4
|
+
version: 1
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# QZhuli CLI
|
|
8
|
+
|
|
9
|
+
Use this skill as a concise operating manual for the `qz` command.
|
|
10
|
+
|
|
11
|
+
## First Checks
|
|
12
|
+
|
|
13
|
+
1. Check whether the user is logged in:
|
|
14
|
+
```bash
|
|
15
|
+
qz auth status
|
|
16
|
+
```
|
|
17
|
+
2. If auth is missing or expired, run QR login and ask the user to scan:
|
|
18
|
+
```bash
|
|
19
|
+
qz auth login
|
|
20
|
+
```
|
|
21
|
+
3. For exact syntax, use command help:
|
|
22
|
+
```bash
|
|
23
|
+
qz --help
|
|
24
|
+
qz <command> --help
|
|
25
|
+
qz <command> <subcommand> --help
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Environment and Config Files
|
|
29
|
+
|
|
30
|
+
If the CLI prints a `DEVELOPMENT BUILD` / `Running in TEST environment` banner, it is using the test environment and
|
|
31
|
+
stores config under `./.qzhuli-cli/` relative to the process working directory.
|
|
32
|
+
|
|
33
|
+
| Visible behavior | Environment | Config directory |
|
|
34
|
+
|-------------------|-------------|------------------|
|
|
35
|
+
| Shows test banner | test | `./.qzhuli-cli/` |
|
|
36
|
+
| No test banner | production | `~/.qzhuli-cli/` |
|
|
37
|
+
|
|
38
|
+
Treat `credentials.json` as secret. Preferences live in `preferences.json`.
|
|
39
|
+
|
|
40
|
+
## Output and Global Options
|
|
41
|
+
|
|
42
|
+
Commands return JSON with `status`, `code`, `message`, and `data`. Check `status`, not only the exit code; ambiguous
|
|
43
|
+
friend lookups can return `status: "needs_resolution"`.
|
|
44
|
+
|
|
45
|
+
Use `--jq` for simple dot-path filtering:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
qz --jq ".data.uid" auth status
|
|
49
|
+
qz --jq ".data.links" friend list
|
|
50
|
+
qz --jq ".data" conversation list --limit 5
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`--jq` is not full jq. Prefer simple paths such as `.data`, `.data.uid`, `.data.links`.
|
|
54
|
+
|
|
55
|
+
Use `--dry-run` when you need to avoid side effects. It is wired through output handling, HTTP API calls, IM WebSocket
|
|
56
|
+
actions, auth login/logout, and preference writes.
|
|
57
|
+
|
|
58
|
+
## Command Map
|
|
59
|
+
|
|
60
|
+
| Goal | Command |
|
|
61
|
+
|----------------------------|-----------------------------------------------------------------------------------------------|
|
|
62
|
+
| Check login | `qz auth status` |
|
|
63
|
+
| QR login | `qz auth login [--method qr-code]` |
|
|
64
|
+
| Clear credentials | `qz auth logout` |
|
|
65
|
+
| Show preferences | `qz config` |
|
|
66
|
+
| Update preferences | `qz config [--locale en\|zh] [--debug\|--no-debug]` |
|
|
67
|
+
| Search user (Q助号) | `qz user search <query>` |
|
|
68
|
+
| Search user (UID) | `qz user search <query> --uid` |
|
|
69
|
+
| Add friend (Q助号) | `qz user add <q-number>` |
|
|
70
|
+
| List friends | `qz friend list` |
|
|
71
|
+
| Resolve profile (nickname) | `qz friend profile <query>` |
|
|
72
|
+
| Resolve profile (UID) | `qz friend profile <query> --uid` |
|
|
73
|
+
| Resolve profile (remark) | `qz friend profile <query> --remark` |
|
|
74
|
+
| Read relation | `qz relation get <uid>` |
|
|
75
|
+
| Update relation | `qz relation set <uid> [-r, --remark <name>] [-t, --type <type>]` |
|
|
76
|
+
| List conversations | `qz conversation list [--limit <n>]` |
|
|
77
|
+
| Create conversation | `qz conversation create <uid> --agent-id <id>` |
|
|
78
|
+
| Send message | `qz message send <conversation-id> <target-cid> <content>` |
|
|
79
|
+
| Read message history | `qz message history <conversation-id> [--from <id>] [--direction newer\|older] [--limit <n>]` |
|
|
80
|
+
|
|
81
|
+
Relation type values are `0=stranger`, `1=friend`, `2=family`, `3=colleague`.
|
|
82
|
+
|
|
83
|
+
## Common Workflows
|
|
84
|
+
|
|
85
|
+
### Find a Friend and Inspect Relation
|
|
86
|
+
|
|
87
|
+
1. List candidates:
|
|
88
|
+
```bash
|
|
89
|
+
qz friend list
|
|
90
|
+
```
|
|
91
|
+
2. Resolve ambiguous names:
|
|
92
|
+
```bash
|
|
93
|
+
qz friend profile "<nickname>"
|
|
94
|
+
```
|
|
95
|
+
3. Use the resolved `uid`:
|
|
96
|
+
```bash
|
|
97
|
+
qz relation get <uid>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Update a Friend Relation
|
|
101
|
+
|
|
102
|
+
1. Resolve the exact `uid` first with `friend list` or `friend profile`.
|
|
103
|
+
2. Confirm with the user before changing data.
|
|
104
|
+
3. Execute one or both updates:
|
|
105
|
+
```bash
|
|
106
|
+
qz relation set <uid> --remark "Product Manager" --type 1
|
|
107
|
+
```
|
|
108
|
+
4. Verify:
|
|
109
|
+
```bash
|
|
110
|
+
qz relation get <uid>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Do not run `relation set` without `--remark` or `--type`; the CLI returns `INVALID_ARGUMENT`.
|
|
114
|
+
|
|
115
|
+
### Search and Add a Friend
|
|
116
|
+
|
|
117
|
+
1. Search by Q助号:
|
|
118
|
+
```bash
|
|
119
|
+
qz user search 10000
|
|
120
|
+
```
|
|
121
|
+
2. Add directly by Q助号:
|
|
122
|
+
```bash
|
|
123
|
+
qz user add 10000
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Send a Message
|
|
127
|
+
|
|
128
|
+
1. Confirm auth:
|
|
129
|
+
```bash
|
|
130
|
+
qz auth status
|
|
131
|
+
```
|
|
132
|
+
2. Get conversations:
|
|
133
|
+
```bash
|
|
134
|
+
qz conversation list --limit 10
|
|
135
|
+
```
|
|
136
|
+
3. Pick the conversation `id`.
|
|
137
|
+
4. Pick `target-cid` from that conversation's `cids`; for one-to-one chats this is usually the other participant's cid,
|
|
138
|
+
not the current user's own `cid`.
|
|
139
|
+
5. Confirm recipient and content with the user if there is any ambiguity.
|
|
140
|
+
6. Send:
|
|
141
|
+
```bash
|
|
142
|
+
qz message send <conversation-id> <target-cid> "message text"
|
|
143
|
+
```
|
|
144
|
+
7. Verify:
|
|
145
|
+
```bash
|
|
146
|
+
qz message history <conversation-id> --limit 5
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Page Through Message History
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
qz message history <conversation-id> --limit 20
|
|
153
|
+
qz message history <conversation-id> --from <message-id> --direction older --limit 20
|
|
154
|
+
qz message history <conversation-id> --from <message-id> --direction newer --limit 20
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Troubleshooting
|
|
158
|
+
|
|
159
|
+
| Symptom | Action |
|
|
160
|
+
|------------------------|--------------------------------------------------------------------------|
|
|
161
|
+
| Command not found | Confirm `qz` is installed or available on `PATH`. |
|
|
162
|
+
| Auth failure | Run `qz auth status`; then `qz auth login` if needed. |
|
|
163
|
+
| Unexpected language | Run `qz config --locale en` or `qz config --locale zh`. |
|
|
164
|
+
| Too much JSON | Use `--jq ".data"` or another simple dot path. |
|
|
165
|
+
| Need a no-op preview | Use `--dry-run`. |
|
|
166
|
+
| Message send cid error | Re-check `auth status` and choose `target-cid` from `conversation list`. |
|