@qzhuli/qzhuli-cli 0.4.3 → 0.5.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/README.md +17 -20
- package/dist/cmd.js +275 -161
- package/package.json +1 -1
- package/scripts/install-skill.mjs +36 -2
- package/skills/qzhuli-cli/SKILL.md +49 -72
package/README.md
CHANGED
|
@@ -28,38 +28,35 @@ npx qz --version
|
|
|
28
28
|
The CLI ships with a `SKILL.md` that teaches AI agents how to use it. During `npm install -g`, the skill is
|
|
29
29
|
automatically installed to your agent's skill directory.
|
|
30
30
|
|
|
31
|
-
###
|
|
31
|
+
### Install skill to your agent
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
```bash
|
|
34
|
+
npx -p @qzhuli/qzhuli-cli qz-install-skill --target <your-agent-skill-dir>
|
|
35
|
+
```
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
Replace `<your-agent-skill-dir>` with your agent's skill path (e.g. `~/.claude/skills` for Claude Code, `~/.agents/skills` as universal fallback).
|
|
37
38
|
|
|
38
|
-
|
|
39
|
+
### Check skill version
|
|
39
40
|
|
|
40
41
|
```bash
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
npx -p @qzhuli/qzhuli-cli qz-install-skill --version
|
|
43
|
+
```
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
npx -p @qzhuli/qzhuli-cli qz-install-skill --project
|
|
45
|
+
### Update installed skills
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
npx -p @qzhuli/qzhuli-cli qz-install-skill --agent claude-code
|
|
47
|
+
If a newer version is available, update all installed skills:
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
```bash
|
|
51
50
|
npx -p @qzhuli/qzhuli-cli qz-install-skill --update
|
|
52
51
|
```
|
|
53
52
|
|
|
54
|
-
###
|
|
53
|
+
### Verify installation
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
npm update -g @qzhuli/qzhuli-cli
|
|
58
|
-
npx -p @qzhuli/qzhuli-cli qz-install-skill --update
|
|
59
|
-
```
|
|
55
|
+
After install or update, confirm everything works:
|
|
60
56
|
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
1. `qz --version` — CLI version matches the installed package
|
|
58
|
+
2. `npx -p @qzhuli/qzhuli-cli qz-install-skill --version` — skill version is current
|
|
59
|
+
3. Check that `SKILL.md` exists in your agent's skill directory and contains valid `name` and `version` fields
|
|
63
60
|
|
|
64
61
|
## Commands
|
|
65
62
|
|
|
@@ -92,7 +89,7 @@ qz conversation list [--limit <n>] [--offset <n>] # List conversations, def
|
|
|
92
89
|
qz conversation profile <conversation-id> [--type <n>] # Get conversation details with user profiles
|
|
93
90
|
|
|
94
91
|
# Messages
|
|
95
|
-
qz message send <conversation-id> <
|
|
92
|
+
qz message send <conversation-id> <content> [--role <n>] # 0=Assistant(default), 1=User
|
|
96
93
|
qz message history <conversation-id> [--from <id>] [--direction newer|older] [--limit <n>]
|
|
97
94
|
```
|
|
98
95
|
|
package/dist/cmd.js
CHANGED
|
@@ -11234,7 +11234,7 @@ var commands = {
|
|
|
11234
11234
|
},
|
|
11235
11235
|
message: {
|
|
11236
11236
|
desc: "Message operations",
|
|
11237
|
-
sendDesc: "Send a message to a conversation
|
|
11237
|
+
sendDesc: "Send a message to a conversation",
|
|
11238
11238
|
historyDesc: "View message history from a conversation",
|
|
11239
11239
|
fromOption: "Start from message ID",
|
|
11240
11240
|
directionOption: "Direction to pull",
|
|
@@ -11381,7 +11381,7 @@ var commands2 = {
|
|
|
11381
11381
|
},
|
|
11382
11382
|
message: {
|
|
11383
11383
|
desc: "\u6D88\u606F\u64CD\u4F5C",
|
|
11384
|
-
sendDesc: "\
|
|
11384
|
+
sendDesc: "\u5411\u4F1A\u8BDD\u53D1\u9001\u6D88\u606F",
|
|
11385
11385
|
historyDesc: "\u67E5\u770B\u4F1A\u8BDD\u6D88\u606F\u5386\u53F2",
|
|
11386
11386
|
fromOption: "\u8D77\u59CB\u6D88\u606F ID",
|
|
11387
11387
|
directionOption: "\u62C9\u53D6\u65B9\u5411",
|
|
@@ -11529,12 +11529,14 @@ init_cjs_shims();
|
|
|
11529
11529
|
var TEST_CONFIG = {
|
|
11530
11530
|
name: "test",
|
|
11531
11531
|
baseURL: "https://test.client.qzhuli.com",
|
|
11532
|
-
|
|
11532
|
+
imBaseURL: "https://test.im.qzhuli.com",
|
|
11533
|
+
imWsURL: "wss://test.im.qzhuli.com/ws"
|
|
11533
11534
|
};
|
|
11534
11535
|
var PRODUCTION_CONFIG = {
|
|
11535
11536
|
name: "production",
|
|
11536
11537
|
baseURL: "https://client.qzhuli.com",
|
|
11537
|
-
|
|
11538
|
+
imBaseURL: "https://im.qzhuli.com",
|
|
11539
|
+
imWsURL: "wss://im.qzhuli.com/ws"
|
|
11538
11540
|
};
|
|
11539
11541
|
var ENV_MAP = {
|
|
11540
11542
|
test: TEST_CONFIG,
|
|
@@ -11616,7 +11618,8 @@ function loadAppConfig(env) {
|
|
|
11616
11618
|
locale: prefs.locale ?? "en",
|
|
11617
11619
|
debug: prefs.debug ?? false,
|
|
11618
11620
|
baseURL: envConfig.baseURL,
|
|
11619
|
-
|
|
11621
|
+
imBaseURL: envConfig.imBaseURL,
|
|
11622
|
+
imWsURL: envConfig.imWsURL
|
|
11620
11623
|
};
|
|
11621
11624
|
}
|
|
11622
11625
|
|
|
@@ -12829,12 +12832,8 @@ async function messageHistoryRun(factory, opts) {
|
|
|
12829
12832
|
// src/commands/message/send.ts
|
|
12830
12833
|
init_cjs_shims();
|
|
12831
12834
|
async function messageSendRun(factory, opts) {
|
|
12832
|
-
const
|
|
12833
|
-
|
|
12834
|
-
opts.targetCid,
|
|
12835
|
-
opts.content
|
|
12836
|
-
);
|
|
12837
|
-
if (result.status === "error" && result.code === "AUTH_FAILED" /* AUTH_FAILED */) {
|
|
12835
|
+
const cid = factory.config.cid;
|
|
12836
|
+
if (!cid) {
|
|
12838
12837
|
return {
|
|
12839
12838
|
status: "error",
|
|
12840
12839
|
code: "AUTH_FAILED" /* AUTH_FAILED */,
|
|
@@ -12842,14 +12841,39 @@ async function messageSendRun(factory, opts) {
|
|
|
12842
12841
|
data: null
|
|
12843
12842
|
};
|
|
12844
12843
|
}
|
|
12845
|
-
|
|
12844
|
+
const req = {
|
|
12845
|
+
sender_cid: cid,
|
|
12846
|
+
conv_id: opts.conversationId,
|
|
12847
|
+
content: opts.content,
|
|
12848
|
+
role: opts.role ?? 0,
|
|
12849
|
+
msg_type: 0 /* Text */
|
|
12850
|
+
};
|
|
12851
|
+
const result = await factory.gateway.pushMessage(req);
|
|
12852
|
+
if (!result.ok) {
|
|
12853
|
+
return {
|
|
12854
|
+
status: "error",
|
|
12855
|
+
code: result.code,
|
|
12856
|
+
message: result.message,
|
|
12857
|
+
data: null
|
|
12858
|
+
};
|
|
12859
|
+
}
|
|
12860
|
+
return {
|
|
12861
|
+
status: "success",
|
|
12862
|
+
code: "MESSAGE_SENT" /* MESSAGE_SENT */,
|
|
12863
|
+
message: result.data.message,
|
|
12864
|
+
data: null
|
|
12865
|
+
};
|
|
12846
12866
|
}
|
|
12847
12867
|
|
|
12848
12868
|
// src/commands/message/index.ts
|
|
12849
12869
|
function NewCmdMessage(factory) {
|
|
12850
12870
|
const cmd = new import_commander6.Command("message").description(t("commands.message.desc"));
|
|
12851
|
-
cmd.command("send <conversation-id> <
|
|
12852
|
-
const result = await messageSendRun(factory, {
|
|
12871
|
+
cmd.command("send <conversation-id> <content>").description(t("commands.message.sendDesc")).option("--role <n>", "Sender role: 0=Assistant, 1=User (default 0)", "0").action(async (conversationId, content, options3) => {
|
|
12872
|
+
const result = await messageSendRun(factory, {
|
|
12873
|
+
conversationId,
|
|
12874
|
+
content,
|
|
12875
|
+
role: parseInt(options3.role, 10)
|
|
12876
|
+
});
|
|
12853
12877
|
handleCommand(result);
|
|
12854
12878
|
});
|
|
12855
12879
|
cmd.command("history <conversation-id>").description(t("commands.message.historyDesc")).option("--from <id>", t("commands.message.fromOption")).option("--direction <newer|older>", t("commands.message.directionOption"), "older").option("--limit <n>", t("commands.message.limitOption"), "20").action(async (conversationId, options3) => {
|
|
@@ -13055,150 +13079,7 @@ function NewCmdUser(factory) {
|
|
|
13055
13079
|
// src/factory.ts
|
|
13056
13080
|
init_cjs_shims();
|
|
13057
13081
|
|
|
13058
|
-
// src/internal/api/api-
|
|
13059
|
-
init_cjs_shims();
|
|
13060
|
-
var ApiGateway = class {
|
|
13061
|
-
constructor(client) {
|
|
13062
|
-
this.client = client;
|
|
13063
|
-
}
|
|
13064
|
-
client;
|
|
13065
|
-
setDryRun(enabled) {
|
|
13066
|
-
this.client.setDryRun(enabled);
|
|
13067
|
-
}
|
|
13068
|
-
/** Check auth and return uid or a fail result. */
|
|
13069
|
-
requireAuth() {
|
|
13070
|
-
const uid = this.client.getAuthUid();
|
|
13071
|
-
if (!uid) {
|
|
13072
|
-
return {
|
|
13073
|
-
ok: false,
|
|
13074
|
-
code: "AUTH_FAILED" /* AUTH_FAILED */,
|
|
13075
|
-
message: "Authentication required."
|
|
13076
|
-
};
|
|
13077
|
-
}
|
|
13078
|
-
return { ok: true, data: uid };
|
|
13079
|
-
}
|
|
13080
|
-
// MARK: Friends / Contacts
|
|
13081
|
-
/** POST /user/get_links_contacts — auth required */
|
|
13082
|
-
getLinksContacts() {
|
|
13083
|
-
const auth3 = this.requireAuth();
|
|
13084
|
-
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13085
|
-
return this.client.performRequest("/user/get_links_contacts", "POST", {
|
|
13086
|
-
uid: auth3.data
|
|
13087
|
-
});
|
|
13088
|
-
}
|
|
13089
|
-
// MARK: Relation
|
|
13090
|
-
/** POST /user/get_link_name_type — auth required, body: uid + friend_uid */
|
|
13091
|
-
getLinkNameType(friendUid) {
|
|
13092
|
-
const auth3 = this.requireAuth();
|
|
13093
|
-
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13094
|
-
return this.client.performRequest("/user/get_link_name_type", "POST", {
|
|
13095
|
-
uid: auth3.data,
|
|
13096
|
-
friend_uid: friendUid
|
|
13097
|
-
});
|
|
13098
|
-
}
|
|
13099
|
-
/** POST /user/update_link_name — auth required */
|
|
13100
|
-
updateLinkName(friendUid, remark) {
|
|
13101
|
-
const auth3 = this.requireAuth();
|
|
13102
|
-
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13103
|
-
return this.client.performSimpleRequest("/user/update_link_name", "POST", {
|
|
13104
|
-
uid: auth3.data,
|
|
13105
|
-
friend_uid: friendUid,
|
|
13106
|
-
link_name: remark
|
|
13107
|
-
});
|
|
13108
|
-
}
|
|
13109
|
-
/** POST /user/update_link_type — auth required, body: friend_uid + link_type (string) */
|
|
13110
|
-
updateLinkType(friendUid, groupType) {
|
|
13111
|
-
const auth3 = this.requireAuth();
|
|
13112
|
-
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13113
|
-
return this.client.performSimpleRequest("/user/update_link_type", "POST", {
|
|
13114
|
-
friend_uid: friendUid,
|
|
13115
|
-
link_type: String(groupType)
|
|
13116
|
-
});
|
|
13117
|
-
}
|
|
13118
|
-
// MARK: User
|
|
13119
|
-
/** POST /user/user_agent_profile — auth required, body: friend_uid + uid (+ agent_id) */
|
|
13120
|
-
findUserById(id) {
|
|
13121
|
-
const auth3 = this.requireAuth();
|
|
13122
|
-
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13123
|
-
return this.client.performRequest("/user/user_agent_profile", "POST", {
|
|
13124
|
-
friend_uid: id,
|
|
13125
|
-
uid: auth3.data
|
|
13126
|
-
});
|
|
13127
|
-
}
|
|
13128
|
-
/** POST /user/user_agent_profile — auth required, body: friend_uid + uid (+ agent_id) */
|
|
13129
|
-
getUserAgentProfile(friendUid, agentId) {
|
|
13130
|
-
const auth3 = this.requireAuth();
|
|
13131
|
-
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13132
|
-
const params = {
|
|
13133
|
-
friend_uid: friendUid,
|
|
13134
|
-
uid: auth3.data
|
|
13135
|
-
};
|
|
13136
|
-
if (agentId) {
|
|
13137
|
-
params.agent_id = agentId;
|
|
13138
|
-
}
|
|
13139
|
-
return this.client.performRequest("/user/user_agent_profile", "POST", params);
|
|
13140
|
-
}
|
|
13141
|
-
// MARK: QR Login
|
|
13142
|
-
/** POST /user/qr_login_create/3 — no auth required */
|
|
13143
|
-
qrLoginCreate() {
|
|
13144
|
-
return this.client.performUnauthenticated(
|
|
13145
|
-
"/user/qr_login_create/3",
|
|
13146
|
-
"POST",
|
|
13147
|
-
{}
|
|
13148
|
-
);
|
|
13149
|
-
}
|
|
13150
|
-
/** POST /user/qr_login_status — no auth required */
|
|
13151
|
-
qrLoginStatus(sceneId) {
|
|
13152
|
-
return this.client.performUnauthenticated("/user/qr_login_status", "POST", {
|
|
13153
|
-
scene_id: sceneId
|
|
13154
|
-
});
|
|
13155
|
-
}
|
|
13156
|
-
// MARK: Connectivity
|
|
13157
|
-
/** Quick connectivity check — calls the simplest endpoint. */
|
|
13158
|
-
async ping() {
|
|
13159
|
-
const result = await this.getLinksContacts();
|
|
13160
|
-
if (result.ok) {
|
|
13161
|
-
return { ok: true, data: true };
|
|
13162
|
-
}
|
|
13163
|
-
return result;
|
|
13164
|
-
}
|
|
13165
|
-
// MARK: Friend Add
|
|
13166
|
-
/** POST /user/find_user_by_id — search any user by Q助号 */
|
|
13167
|
-
searchUserById(id) {
|
|
13168
|
-
return this.client.performRequest("/user/find_user_by_id", "POST", {
|
|
13169
|
-
id
|
|
13170
|
-
});
|
|
13171
|
-
}
|
|
13172
|
-
/** POST /user/create_conversation — auth required, body: uid + friend_uid + friend_agent_id */
|
|
13173
|
-
createConversation(friendUid, friendAgentId) {
|
|
13174
|
-
const auth3 = this.requireAuth();
|
|
13175
|
-
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13176
|
-
return this.client.performRequest("/user/create_conversation", "POST", {
|
|
13177
|
-
uid: auth3.data,
|
|
13178
|
-
friend_uid: friendUid,
|
|
13179
|
-
friend_agent_id: friendAgentId
|
|
13180
|
-
});
|
|
13181
|
-
}
|
|
13182
|
-
/** POST /user/get_profile_by_conversation_id — auth required */
|
|
13183
|
-
getProfileByConversationId(conversationId, conversationType) {
|
|
13184
|
-
const auth3 = this.requireAuth();
|
|
13185
|
-
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13186
|
-
const params = {
|
|
13187
|
-
uid: auth3.data,
|
|
13188
|
-
conversation_id: conversationId
|
|
13189
|
-
};
|
|
13190
|
-
if (conversationType !== void 0) {
|
|
13191
|
-
params.conversation_type = conversationType;
|
|
13192
|
-
}
|
|
13193
|
-
return this.client.performRequest(
|
|
13194
|
-
"/user/get_profile_by_conversation_id",
|
|
13195
|
-
"POST",
|
|
13196
|
-
params
|
|
13197
|
-
);
|
|
13198
|
-
}
|
|
13199
|
-
};
|
|
13200
|
-
|
|
13201
|
-
// src/internal/api-client.ts
|
|
13082
|
+
// src/internal/api/api-client.ts
|
|
13202
13083
|
init_cjs_shims();
|
|
13203
13084
|
var import_node_crypto = require("crypto");
|
|
13204
13085
|
var APIClient = class {
|
|
@@ -13378,6 +13259,238 @@ function printDryRun(url, method, body) {
|
|
|
13378
13259
|
console.log();
|
|
13379
13260
|
}
|
|
13380
13261
|
|
|
13262
|
+
// src/internal/api/api-gateway.ts
|
|
13263
|
+
init_cjs_shims();
|
|
13264
|
+
var ApiGateway = class {
|
|
13265
|
+
constructor(client) {
|
|
13266
|
+
this.client = client;
|
|
13267
|
+
}
|
|
13268
|
+
client;
|
|
13269
|
+
imApiClient = null;
|
|
13270
|
+
/** Inject the IM HTTP client after gateway creation. */
|
|
13271
|
+
setIMApiClient(client) {
|
|
13272
|
+
this.imApiClient = client;
|
|
13273
|
+
}
|
|
13274
|
+
setDryRun(enabled) {
|
|
13275
|
+
this.client.setDryRun(enabled);
|
|
13276
|
+
this.imApiClient?.setDryRun(enabled);
|
|
13277
|
+
}
|
|
13278
|
+
/** Check auth and return uid or a fail result. */
|
|
13279
|
+
requireAuth() {
|
|
13280
|
+
const uid = this.client.getAuthUid();
|
|
13281
|
+
if (!uid) {
|
|
13282
|
+
return {
|
|
13283
|
+
ok: false,
|
|
13284
|
+
code: "AUTH_FAILED" /* AUTH_FAILED */,
|
|
13285
|
+
message: "Authentication required."
|
|
13286
|
+
};
|
|
13287
|
+
}
|
|
13288
|
+
return { ok: true, data: uid };
|
|
13289
|
+
}
|
|
13290
|
+
// MARK: Friends / Contacts
|
|
13291
|
+
/** POST /user/get_links_contacts — auth required */
|
|
13292
|
+
getLinksContacts() {
|
|
13293
|
+
const auth3 = this.requireAuth();
|
|
13294
|
+
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13295
|
+
return this.client.performRequest("/user/get_links_contacts", "POST", {
|
|
13296
|
+
uid: auth3.data
|
|
13297
|
+
});
|
|
13298
|
+
}
|
|
13299
|
+
// MARK: Relation
|
|
13300
|
+
/** POST /user/get_link_name_type — auth required, body: uid + friend_uid */
|
|
13301
|
+
getLinkNameType(friendUid) {
|
|
13302
|
+
const auth3 = this.requireAuth();
|
|
13303
|
+
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13304
|
+
return this.client.performRequest("/user/get_link_name_type", "POST", {
|
|
13305
|
+
uid: auth3.data,
|
|
13306
|
+
friend_uid: friendUid
|
|
13307
|
+
});
|
|
13308
|
+
}
|
|
13309
|
+
/** POST /user/update_link_name — auth required */
|
|
13310
|
+
updateLinkName(friendUid, remark) {
|
|
13311
|
+
const auth3 = this.requireAuth();
|
|
13312
|
+
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13313
|
+
return this.client.performSimpleRequest("/user/update_link_name", "POST", {
|
|
13314
|
+
uid: auth3.data,
|
|
13315
|
+
friend_uid: friendUid,
|
|
13316
|
+
link_name: remark
|
|
13317
|
+
});
|
|
13318
|
+
}
|
|
13319
|
+
/** POST /user/update_link_type — auth required, body: friend_uid + link_type (string) */
|
|
13320
|
+
updateLinkType(friendUid, groupType) {
|
|
13321
|
+
const auth3 = this.requireAuth();
|
|
13322
|
+
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13323
|
+
return this.client.performSimpleRequest("/user/update_link_type", "POST", {
|
|
13324
|
+
friend_uid: friendUid,
|
|
13325
|
+
link_type: String(groupType)
|
|
13326
|
+
});
|
|
13327
|
+
}
|
|
13328
|
+
// MARK: User
|
|
13329
|
+
/** POST /user/user_agent_profile — auth required, body: friend_uid + uid (+ agent_id) */
|
|
13330
|
+
findUserById(id) {
|
|
13331
|
+
const auth3 = this.requireAuth();
|
|
13332
|
+
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13333
|
+
return this.client.performRequest("/user/user_agent_profile", "POST", {
|
|
13334
|
+
friend_uid: id,
|
|
13335
|
+
uid: auth3.data
|
|
13336
|
+
});
|
|
13337
|
+
}
|
|
13338
|
+
/** POST /user/user_agent_profile — auth required, body: friend_uid + uid (+ agent_id) */
|
|
13339
|
+
getUserAgentProfile(friendUid, agentId) {
|
|
13340
|
+
const auth3 = this.requireAuth();
|
|
13341
|
+
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13342
|
+
const params = {
|
|
13343
|
+
friend_uid: friendUid,
|
|
13344
|
+
uid: auth3.data
|
|
13345
|
+
};
|
|
13346
|
+
if (agentId) {
|
|
13347
|
+
params.agent_id = agentId;
|
|
13348
|
+
}
|
|
13349
|
+
return this.client.performRequest("/user/user_agent_profile", "POST", params);
|
|
13350
|
+
}
|
|
13351
|
+
// MARK: QR Login
|
|
13352
|
+
/** POST /user/qr_login_create/3 — no auth required */
|
|
13353
|
+
qrLoginCreate() {
|
|
13354
|
+
return this.client.performUnauthenticated(
|
|
13355
|
+
"/user/qr_login_create/3",
|
|
13356
|
+
"POST",
|
|
13357
|
+
{}
|
|
13358
|
+
);
|
|
13359
|
+
}
|
|
13360
|
+
/** POST /user/qr_login_status — no auth required */
|
|
13361
|
+
qrLoginStatus(sceneId) {
|
|
13362
|
+
return this.client.performUnauthenticated("/user/qr_login_status", "POST", {
|
|
13363
|
+
scene_id: sceneId
|
|
13364
|
+
});
|
|
13365
|
+
}
|
|
13366
|
+
// MARK: Connectivity
|
|
13367
|
+
/** Quick connectivity check — calls the simplest endpoint. */
|
|
13368
|
+
async ping() {
|
|
13369
|
+
const result = await this.getLinksContacts();
|
|
13370
|
+
if (result.ok) {
|
|
13371
|
+
return { ok: true, data: true };
|
|
13372
|
+
}
|
|
13373
|
+
return result;
|
|
13374
|
+
}
|
|
13375
|
+
// MARK: Friend Add
|
|
13376
|
+
/** POST /user/find_user_by_id — search any user by Q助号 */
|
|
13377
|
+
searchUserById(id) {
|
|
13378
|
+
return this.client.performRequest("/user/find_user_by_id", "POST", {
|
|
13379
|
+
id
|
|
13380
|
+
});
|
|
13381
|
+
}
|
|
13382
|
+
/** POST /user/create_conversation — auth required, body: uid + friend_uid + friend_agent_id */
|
|
13383
|
+
createConversation(friendUid, friendAgentId) {
|
|
13384
|
+
const auth3 = this.requireAuth();
|
|
13385
|
+
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13386
|
+
return this.client.performRequest("/user/create_conversation", "POST", {
|
|
13387
|
+
uid: auth3.data,
|
|
13388
|
+
friend_uid: friendUid,
|
|
13389
|
+
friend_agent_id: friendAgentId
|
|
13390
|
+
});
|
|
13391
|
+
}
|
|
13392
|
+
/** POST /user/get_profile_by_conversation_id — auth required */
|
|
13393
|
+
getProfileByConversationId(conversationId, conversationType) {
|
|
13394
|
+
const auth3 = this.requireAuth();
|
|
13395
|
+
if (!auth3.ok) return Promise.resolve(auth3);
|
|
13396
|
+
const params = {
|
|
13397
|
+
uid: auth3.data,
|
|
13398
|
+
conversation_id: conversationId
|
|
13399
|
+
};
|
|
13400
|
+
if (conversationType !== void 0) {
|
|
13401
|
+
params.conversation_type = conversationType;
|
|
13402
|
+
}
|
|
13403
|
+
return this.client.performRequest(
|
|
13404
|
+
"/user/get_profile_by_conversation_id",
|
|
13405
|
+
"POST",
|
|
13406
|
+
params
|
|
13407
|
+
);
|
|
13408
|
+
}
|
|
13409
|
+
// MARK: IM
|
|
13410
|
+
/** POST /api/v1/conversations/push_message — JSON body, no HMAC signature */
|
|
13411
|
+
async pushMessage(req) {
|
|
13412
|
+
if (!this.imApiClient) {
|
|
13413
|
+
return {
|
|
13414
|
+
ok: false,
|
|
13415
|
+
code: "INTERNAL_ERROR" /* INTERNAL_ERROR */,
|
|
13416
|
+
message: "IM API client not configured."
|
|
13417
|
+
};
|
|
13418
|
+
}
|
|
13419
|
+
return this.imApiClient.pushMessage(req);
|
|
13420
|
+
}
|
|
13421
|
+
};
|
|
13422
|
+
|
|
13423
|
+
// src/internal/api/im-api-client.ts
|
|
13424
|
+
init_cjs_shims();
|
|
13425
|
+
var IMApiClient = class {
|
|
13426
|
+
baseURL;
|
|
13427
|
+
debugEnabled = false;
|
|
13428
|
+
dryRun = false;
|
|
13429
|
+
constructor(baseURL, debugEnabled = false) {
|
|
13430
|
+
this.baseURL = baseURL;
|
|
13431
|
+
this.debugEnabled = debugEnabled;
|
|
13432
|
+
}
|
|
13433
|
+
setDryRun(enabled) {
|
|
13434
|
+
this.dryRun = enabled;
|
|
13435
|
+
}
|
|
13436
|
+
setDebug(enabled) {
|
|
13437
|
+
this.debugEnabled = enabled;
|
|
13438
|
+
}
|
|
13439
|
+
async pushMessage(req) {
|
|
13440
|
+
const url = `${this.baseURL}/api/v1/conversations/push_message`;
|
|
13441
|
+
if (this.dryRun) {
|
|
13442
|
+
this.log("[dry-run]", url, req);
|
|
13443
|
+
return ok({
|
|
13444
|
+
status: "success",
|
|
13445
|
+
sender_cid: req.sender_cid ?? "",
|
|
13446
|
+
conv_id: req.conv_id,
|
|
13447
|
+
message: "Message sent successfully"
|
|
13448
|
+
});
|
|
13449
|
+
}
|
|
13450
|
+
this.log("POST", url, req);
|
|
13451
|
+
try {
|
|
13452
|
+
const response = await fetch(url, {
|
|
13453
|
+
method: "POST",
|
|
13454
|
+
headers: {
|
|
13455
|
+
"Content-Type": "application/json"
|
|
13456
|
+
},
|
|
13457
|
+
body: JSON.stringify(req)
|
|
13458
|
+
});
|
|
13459
|
+
const text = await response.clone().text();
|
|
13460
|
+
this.log(`${response.status} ${response.statusText}`, text);
|
|
13461
|
+
if (!response.ok) {
|
|
13462
|
+
return fail(
|
|
13463
|
+
response.status === 401 || response.status === 403 ? "AUTH_FAILED" /* AUTH_FAILED */ : "NETWORK_ERROR" /* NETWORK_ERROR */,
|
|
13464
|
+
`HTTP ${response.status}: ${response.statusText}`
|
|
13465
|
+
);
|
|
13466
|
+
}
|
|
13467
|
+
let json;
|
|
13468
|
+
try {
|
|
13469
|
+
json = JSON.parse(text);
|
|
13470
|
+
} catch {
|
|
13471
|
+
return fail("DECODE_ERROR" /* DECODE_ERROR */, "Failed to parse push_message response");
|
|
13472
|
+
}
|
|
13473
|
+
if (json.code !== 200) {
|
|
13474
|
+
return fail("API_ERROR" /* API_ERROR */, json.msg || `API error (code: ${json.code})`);
|
|
13475
|
+
}
|
|
13476
|
+
if (json.data === null) {
|
|
13477
|
+
return fail("NOT_FOUND" /* NOT_FOUND */, "push_message returned empty data");
|
|
13478
|
+
}
|
|
13479
|
+
return ok(json.data);
|
|
13480
|
+
} catch (error) {
|
|
13481
|
+
return fail(
|
|
13482
|
+
"NETWORK_ERROR" /* NETWORK_ERROR */,
|
|
13483
|
+
error instanceof Error ? error.message : "Failed to push message"
|
|
13484
|
+
);
|
|
13485
|
+
}
|
|
13486
|
+
}
|
|
13487
|
+
log(...args) {
|
|
13488
|
+
if (this.debugEnabled) {
|
|
13489
|
+
console.log("[PUSH]", ...args);
|
|
13490
|
+
}
|
|
13491
|
+
}
|
|
13492
|
+
};
|
|
13493
|
+
|
|
13381
13494
|
// src/internal/im/im-gateway.ts
|
|
13382
13495
|
init_cjs_shims();
|
|
13383
13496
|
|
|
@@ -13738,7 +13851,7 @@ var IMClient = class {
|
|
|
13738
13851
|
}
|
|
13739
13852
|
// MARK: - Private
|
|
13740
13853
|
buildWsUrl() {
|
|
13741
|
-
const httpUrl = this.config.
|
|
13854
|
+
const httpUrl = this.config.imWsURL;
|
|
13742
13855
|
let wsUrl = httpUrl.replace(/^http/, "ws");
|
|
13743
13856
|
wsUrl = wsUrl.replace(/\/+$/, "");
|
|
13744
13857
|
if (!wsUrl.endsWith("/ws")) {
|
|
@@ -14736,8 +14849,9 @@ function createFactory(config) {
|
|
|
14736
14849
|
client.setAuth({ uid: config.uid, tk: config.tk, token: config.token });
|
|
14737
14850
|
}
|
|
14738
14851
|
const gateway = new ApiGateway(client);
|
|
14852
|
+
gateway.setIMApiClient(new IMApiClient(config.imBaseURL, config.debug));
|
|
14739
14853
|
const imGateway = new IMGateway({
|
|
14740
|
-
|
|
14854
|
+
imWsURL: config.imWsURL,
|
|
14741
14855
|
cid: config.cid,
|
|
14742
14856
|
debugEnabled: config.debug
|
|
14743
14857
|
});
|
|
@@ -14807,7 +14921,7 @@ async function main() {
|
|
|
14807
14921
|
${t("cli.banner")}` : t("cli.banner");
|
|
14808
14922
|
program.addHelpText("beforeAll", `${banner}
|
|
14809
14923
|
`);
|
|
14810
|
-
program.name("qz").version(`v${"0.
|
|
14924
|
+
program.name("qz").version(`v${"0.5.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"));
|
|
14811
14925
|
program.usage("<command> [subcommand] [options]");
|
|
14812
14926
|
program.hook("preAction", () => {
|
|
14813
14927
|
const opts = program.opts();
|
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* node scripts/install-skill.mjs # install to all detected agents (global)
|
|
7
7
|
* node scripts/install-skill.mjs --project # install to current project's skills dir
|
|
8
8
|
* node scripts/install-skill.mjs --agent claude-code # install to specific agent only
|
|
9
|
+
* node scripts/install-skill.mjs --target /path/to/skills # install to custom directory
|
|
9
10
|
* node scripts/install-skill.mjs --help # show help
|
|
10
11
|
*
|
|
11
12
|
* Works with:
|
|
@@ -51,8 +52,27 @@ function getPkgVersion() {
|
|
|
51
52
|
|
|
52
53
|
// ── CLI parsing ────────────────────────────────────────────────────
|
|
53
54
|
|
|
55
|
+
function printVersion(sourceDir) {
|
|
56
|
+
const pkgVersion = getPkgVersion();
|
|
57
|
+
const skillVersion = sourceDir ? readSkillVersion(sourceDir) : 'n/a';
|
|
58
|
+
console.log(`@qzhuli/qzhuli-cli v${pkgVersion}`);
|
|
59
|
+
console.log(`qzhuli skill v${skillVersion}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function readSkillVersion(sourceDir) {
|
|
63
|
+
const skillMd = join(sourceDir, 'SKILL.md');
|
|
64
|
+
if (!existsSync(skillMd)) return 'n/a';
|
|
65
|
+
try {
|
|
66
|
+
const content = readFileSync(skillMd, 'utf8');
|
|
67
|
+
const match = content.match(/^version:\s*(.+)$/m);
|
|
68
|
+
return match ? match[1].trim() : 'n/a';
|
|
69
|
+
} catch {
|
|
70
|
+
return 'n/a';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
54
74
|
function parseArgs(argv) {
|
|
55
|
-
const args = { project: false, agent: null, help: false, update: false };
|
|
75
|
+
const args = { project: false, agent: null, help: false, update: false, target: null, version: false };
|
|
56
76
|
for (let i = 0; i < argv.length; i++) {
|
|
57
77
|
switch (argv[i]) {
|
|
58
78
|
case '--project':
|
|
@@ -64,6 +84,12 @@ function parseArgs(argv) {
|
|
|
64
84
|
case '--update':
|
|
65
85
|
args.update = true;
|
|
66
86
|
break;
|
|
87
|
+
case '--target':
|
|
88
|
+
args.target = argv[++i];
|
|
89
|
+
break;
|
|
90
|
+
case '--version':
|
|
91
|
+
args.version = true;
|
|
92
|
+
break;
|
|
67
93
|
case '--help':
|
|
68
94
|
case '-h':
|
|
69
95
|
args.help = true;
|
|
@@ -80,13 +106,16 @@ Usage: node install-skill.mjs [options]
|
|
|
80
106
|
Options:
|
|
81
107
|
--project Install to current project's .claude/skills (or equivalent)
|
|
82
108
|
--agent <name> Install to a specific agent only (e.g. claude-code, cursor)
|
|
109
|
+
--target <path> Install to a custom directory path (skips agent detection)
|
|
83
110
|
--update Check for updates and reinstall if version changed
|
|
111
|
+
--version Show package and skill version
|
|
84
112
|
--help, -h Show this help message
|
|
85
113
|
|
|
86
114
|
Examples:
|
|
87
115
|
node scripts/install-skill.mjs # global, all agents
|
|
88
116
|
node scripts/install-skill.mjs --project # project-level, all agents
|
|
89
117
|
node scripts/install-skill.mjs --agent claude-code # global, claude-code only
|
|
118
|
+
node scripts/install-skill.mjs --target /path/to/skills # custom directory
|
|
90
119
|
node scripts/install-skill.mjs --update # update all installed agents
|
|
91
120
|
npx @qzhuli/qzhuli-cli scripts/install-skill.mjs # from published npm
|
|
92
121
|
`);
|
|
@@ -97,6 +126,7 @@ Examples:
|
|
|
97
126
|
function main() {
|
|
98
127
|
const opts = parseArgs(process.argv.slice(2));
|
|
99
128
|
if (opts.help) { printHelp(); process.exit(0); }
|
|
129
|
+
if (opts.version) { printVersion(findSourceDir()); process.exit(0); }
|
|
100
130
|
|
|
101
131
|
const sourceDir = findSourceDir();
|
|
102
132
|
if (!sourceDir) {
|
|
@@ -109,7 +139,11 @@ function main() {
|
|
|
109
139
|
|
|
110
140
|
// Resolve target agents
|
|
111
141
|
let targets = [];
|
|
112
|
-
if (opts.
|
|
142
|
+
if (opts.target) {
|
|
143
|
+
// --target: install to an arbitrary directory path
|
|
144
|
+
const targetPath = resolve(opts.target);
|
|
145
|
+
targets.push({ cfg: { name: `custom:${targetPath}`, global: targetPath }, isProject: false, isCustom: true });
|
|
146
|
+
} else if (opts.update) {
|
|
113
147
|
// --update: check agents that already have the skill installed
|
|
114
148
|
const candidates = opts.agent
|
|
115
149
|
? [AGENT_PATHS.find(a => a.name === opts.agent)]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: qzhuli-cli
|
|
3
3
|
description: Use when operating the QZhuli CLI (`qz`), including login, auth status, config, friends, relations, users, conversations, messages, cache management, JSON filtering, dry-run, command help, and interpreting test-environment banners or config files.
|
|
4
|
-
version:
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# QZhuli CLI
|
|
@@ -38,45 +38,36 @@ When ANY of the following applies, STOP and ask the user first:
|
|
|
38
38
|
- **Ambiguous search results**: `status: "needs_resolution"` — show options and ask.
|
|
39
39
|
- **Friend operations**: Before `user add`, show the target profile and confirm.
|
|
40
40
|
- **Relation changes**: Before `relation set`, show the current value and the new value, then confirm.
|
|
41
|
-
- **Message sending**: Before `message send`, show the target conversation, recipient, and message content.
|
|
42
41
|
- **Cache clearing**: Before `cache clear`, confirm scope (all tables vs single table).
|
|
43
|
-
- **
|
|
42
|
+
- **Message without conversation**: Before `message send`, check if a conversation with the target user exists. If not,
|
|
43
|
+
ask the user whether to create one first.
|
|
44
|
+
- **Any write operation** (`user add`, `relation set`, `conversation create`, `cache clear`): confirm
|
|
44
45
|
with user.
|
|
45
46
|
|
|
46
|
-
### Use --dry-run for Preview
|
|
47
|
-
|
|
48
|
-
Before any write operation the user hasn't explicitly confirmed, run with `--dry-run` first:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
qz --dry-run message send <id> <cid> "hello"
|
|
52
|
-
qz --dry-run relation set <uid> --remark "New Name"
|
|
53
|
-
```
|
|
54
|
-
|
|
55
47
|
### Least-Surprise Principle
|
|
56
48
|
|
|
57
|
-
- Never auto-send messages without explicit content approval.
|
|
58
49
|
- Never change a friend's remark without showing both old and new.
|
|
59
50
|
- Never delete cache data without confirming scope.
|
|
60
51
|
- If the user says "send a message" but doesn't specify content, draft it and ask before sending.
|
|
61
52
|
|
|
62
|
-
|
|
53
|
+
### Message Role Detection
|
|
63
54
|
|
|
64
|
-
|
|
55
|
+
When sending messages, determine the role based on the user's wording:
|
|
65
56
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
| Conversation ID | `conversationId` | Base64-like long string | `9boGaR7iii2Jdjhmb5LSo37...` | `message send`, `message history`, `conversation profile` |
|
|
72
|
-
| Agent ID | `agent.id` | Number | `5` | `conversation create --agent-id` |
|
|
57
|
+
- If the user says something like **"以我的名义"** (in my name), **"帮我发给"** (help me send to), **"替我发送"** (send
|
|
58
|
+
on my behalf), or similar phrasing indicating they want to send as themselves → use `--role 1` (User).
|
|
59
|
+
- Otherwise, send normally without `--role` (defaults to `0` = Assistant).
|
|
60
|
+
|
|
61
|
+
## ID Reference
|
|
73
62
|
|
|
74
|
-
**
|
|
63
|
+
The CLI uses 4 distinct ID types. **Using the wrong type will fail silently or hit the wrong target.**
|
|
75
64
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
-
|
|
79
|
-
|
|
65
|
+
| ID Type | Field Name | Format | Example | Used By |
|
|
66
|
+
|-----------------|------------------|-------------------------|------------------------------|---------------------------------------------------------------------------------------------------------------------|
|
|
67
|
+
| Q助号 | `id` | Number, short | `10003` | `user add <q-number>`, `user search`, `conversation search` (default) |
|
|
68
|
+
| UID | `uid` | 32-char hex string | `d5b6308e3abad6bc96573c58` | `relation get/set`, `friend profile --uid`, `user search --uid`, `conversation search --uid`, `conversation create` |
|
|
69
|
+
| Conversation ID | `conversationId` | Base64-like long string | `9boGaR7iii2Jdjhmb5LSo37...` | `message send`, `message history`, `conversation profile` |
|
|
70
|
+
| Agent ID | `agent.id` | Number | `5` | `conversation create --agent-id` |
|
|
80
71
|
|
|
81
72
|
**Common mistake**: Using UID for `message send` instead of conversationId. Always resolve via `conversation search` or
|
|
82
73
|
`conversation list` first.
|
|
@@ -112,9 +103,6 @@ qz --jq ".data" conversation list --limit 5
|
|
|
112
103
|
|
|
113
104
|
`--jq` is not full jq. Prefer simple paths: `.data`, `.data.uid`, `.data.links`.
|
|
114
105
|
|
|
115
|
-
Use `--dry-run` to preview without side effects. Wired through: output, HTTP API calls, IM WebSocket actions, auth
|
|
116
|
-
login/logout, and preference writes.
|
|
117
|
-
|
|
118
106
|
## Command Map
|
|
119
107
|
|
|
120
108
|
| Goal | Command |
|
|
@@ -138,7 +126,7 @@ login/logout, and preference writes.
|
|
|
138
126
|
| Create conversation | `qz conversation create <uid> --agent-id <id>` |
|
|
139
127
|
| Search conversations (Q助号) | `qz conversation search <q-number>` |
|
|
140
128
|
| Search conversations (UID) | `qz conversation search <uid> --uid` |
|
|
141
|
-
| Send message | `qz message send <conversation-id> <
|
|
129
|
+
| Send message | `qz message send <conversation-id> <content> [--role <n>]` |
|
|
142
130
|
| Read message history | `qz message history <conversation-id> [--from <id>] [--direction newer\|older] [--limit <n>]` |
|
|
143
131
|
| Sync cache | `qz cache sync` |
|
|
144
132
|
| Cache status | `qz cache status` |
|
|
@@ -156,8 +144,8 @@ Relation type values: `0=stranger`, `1=friend`, `2=family`, `3=colleague`.
|
|
|
156
144
|
|
|
157
145
|
### Update a Friend Relation
|
|
158
146
|
|
|
159
|
-
1. Resolve the exact `uid`
|
|
160
|
-
2. Show current value
|
|
147
|
+
1. Resolve the exact `uid` via `friend list` or `friend profile`.
|
|
148
|
+
2. Show current value, confirm the change.
|
|
161
149
|
3. Execute: `qz relation set <uid> --remark "New Name" --type 1`
|
|
162
150
|
4. Verify: `qz relation get <uid>`
|
|
163
151
|
|
|
@@ -172,22 +160,26 @@ Relation type values: `0=stranger`, `1=friend`, `2=family`, `3=colleague`.
|
|
|
172
160
|
### Find All Conversations with a User
|
|
173
161
|
|
|
174
162
|
```bash
|
|
175
|
-
qz conversation search
|
|
176
|
-
qz conversation search
|
|
163
|
+
qz conversation search <q-number>
|
|
164
|
+
qz conversation search <uid> --uid
|
|
177
165
|
```
|
|
178
166
|
|
|
179
|
-
Response includes `id
|
|
180
|
-
|
|
167
|
+
Response includes `id`, `uid`, and `conversations` with full profile data. Each entry contains `conversationId`,
|
|
168
|
+
`isGroup`, `users`, and `visitors`.
|
|
181
169
|
|
|
182
170
|
### Send a Message
|
|
183
171
|
|
|
184
172
|
1. Confirm auth: `qz auth status`
|
|
185
|
-
2.
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
173
|
+
2. **Check existing conversation**: Use `conversation search <q-number>` or `conversation search <uid> --uid` to find
|
|
174
|
+
conversations with the target user.
|
|
175
|
+
3. **Decision**:
|
|
176
|
+
- If conversations exist → pick the relevant `conversationId`.
|
|
177
|
+
- If no conversation exists → **ask the user first** whether to create one, then
|
|
178
|
+
`qz conversation create <uid> --agent-id <id>`.
|
|
179
|
+
4. Determine role: if the user says "以我的名义" / "帮我发给" / "替我发送" etc., add `--role 1`; otherwise omit (
|
|
180
|
+
defaults to Assistant).
|
|
181
|
+
5. Send: `qz message send <conversation-id> "message text"`
|
|
182
|
+
6. Verify: `qz message history <conversation-id> --limit 5`
|
|
191
183
|
|
|
192
184
|
### Page Through Message History
|
|
193
185
|
|
|
@@ -199,35 +191,20 @@ qz message history <conversation-id> --from <message-id> --direction newer --lim
|
|
|
199
191
|
|
|
200
192
|
### Pre-Sync Cache for Offline Speed
|
|
201
193
|
|
|
202
|
-
|
|
203
|
-
qz cache sync # fetch all data into local SQLite
|
|
204
|
-
qz cache status # verify record counts and sync time
|
|
205
|
-
qz conversation search 10000 # now instant from cache
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
## Cache Architecture (Reference)
|
|
209
|
-
|
|
210
|
-
Read operations use a **Repository Pattern** with SQLite-backed caching (`~/.qzhuli-cli/cache.db`):
|
|
211
|
-
|
|
212
|
-
- **TTL**: conversations 30 min, contacts/relations 5 min, user profiles 1 hour
|
|
213
|
-
- **Incremental sync**: only fetches profiles for *new* conversations
|
|
214
|
-
- **Cache miss** → auto incremental sync (not full refetch)
|
|
215
|
-
- **Write operations** bypass cache, invalidate relevant entries
|
|
216
|
-
|
|
217
|
-
Tables: `conversations_index`, `conversation_profiles`, `contacts_cache`, `user_profiles`, `relations_cache`,
|
|
218
|
-
`messages_cache`.
|
|
194
|
+
Run `qz cache sync` before heavy read operations. Verify with `qz cache status`.
|
|
219
195
|
|
|
220
196
|
## Troubleshooting
|
|
221
197
|
|
|
222
|
-
| Symptom | Action
|
|
223
|
-
|
|
224
|
-
| Command not found | Confirm `qz` is on PATH. Install: `npm install -g @qzhuli/qzhuli-cli`
|
|
225
|
-
| Auth failure | `qz auth status`; then `qz auth login` if needed
|
|
226
|
-
| Unexpected language | `qz config --locale en` or `--locale zh`
|
|
227
|
-
| Too much JSON | Use `--jq ".data"` or another simple dot path
|
|
228
|
-
| Need no-op preview | Use `--dry-run`
|
|
229
|
-
| Message send
|
|
230
|
-
|
|
|
231
|
-
|
|
|
232
|
-
|
|
|
233
|
-
|
|
|
198
|
+
| Symptom | Action |
|
|
199
|
+
|---------------------------------|-----------------------------------------------------------------------------|
|
|
200
|
+
| Command not found | Confirm `qz` is on PATH. Install: `npm install -g @qzhuli/qzhuli-cli` |
|
|
201
|
+
| Auth failure | `qz auth status`; then `qz auth login` if needed |
|
|
202
|
+
| Unexpected language | `qz config --locale en` or `--locale zh` |
|
|
203
|
+
| Too much JSON | Use `--jq ".data"` or another simple dot path |
|
|
204
|
+
| Need no-op preview | Use `--dry-run` |
|
|
205
|
+
| Message send fails | Re-check `auth status`, verify conversationId via `conversation list` |
|
|
206
|
+
| Target has no conversation | Ask user to create one, then `conversation create <uid> --agent-id <id>` |
|
|
207
|
+
| Slow queries | Run `qz cache sync` first (incremental, fast), then retry |
|
|
208
|
+
| Cache corrupted | `qz cache clear` to reset, then retry (falls back to API) |
|
|
209
|
+
| Ambiguous search | `status: "needs_resolution"` — refine query with `--uid` or `--remark` flag |
|
|
210
|
+
| `relation set` INVALID_ARGUMENT | Must include at least one of `--remark` or `--type` |
|