@zhin.js/adapter-icqq 2.0.25 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/adapter.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * ICQQ 适配器 — 通过 @icqqjs/cli 守护进程 IPC 管理 Bot 实例
3
3
  */
4
- import { Adapter, Plugin } from "zhin.js";
4
+ import { formatCompact, Adapter, Plugin } from 'zhin.js';
5
5
  import { IcqqBot } from "./bot.js";
6
6
  import type { IcqqBotConfig, IpcMemberInfo } from "./types.js";
7
7
  import { Actions } from "./protocol.js";
@@ -17,12 +17,11 @@ export class IcqqAdapter extends Adapter<IcqqBot> {
17
17
 
18
18
  async start(): Promise<void> {
19
19
  await super.start();
20
- this.logger.info("ICQQ 适配器已启动");
21
20
  }
22
21
 
23
22
  async stop(): Promise<void> {
24
23
  await super.stop();
25
- this.logger.info("ICQQ 适配器已停止");
24
+ this.logger.debug(formatCompact({ stop: true }));
26
25
  }
27
26
 
28
27
  // ── IGroupManagement 标准群管方法(通过 IPC) ─────────────────────
@@ -0,0 +1,115 @@
1
+ import type {
2
+ AgentPromptBuildContext,
3
+ AgentPromptContributor,
4
+ AgentPromptSection,
5
+ } from 'zhin.js';
6
+ import type { AgentTool } from 'zhin.js';
7
+ import { filterTools } from 'zhin.js';
8
+
9
+ function isIcqqDelegatedTask(query: string, goal: string): boolean {
10
+ const text = `${query} ${goal}`;
11
+ const lower = text.toLowerCase();
12
+ if (/\bicqq\b|mcp_icqq|send_private_msg|friend\s+send/i.test(text)) return true;
13
+ if (/\bfriend\s+like\b/.test(lower) && /qq|好友|\d{5,}/i.test(text)) return true;
14
+ if (/点赞/.test(text) && /qq|好友|\d{5,}/i.test(text)) return true;
15
+ if (/发消息|发送消息|私聊/.test(text) && /qq|\d{5,}/i.test(text)) return true;
16
+ return false;
17
+ }
18
+
19
+ function selectIcqqDeferredTools(
20
+ query: string,
21
+ goal: string,
22
+ deferredCatalog: AgentTool[],
23
+ maxTools: number,
24
+ ): AgentTool[] {
25
+ const pool = deferredCatalog.filter(
26
+ t => !t.name.startsWith('mcp_filesystem') && !t.name.startsWith('mcp_memory_'),
27
+ );
28
+ const icqqMcpTools = pool.filter(t => t.name.startsWith('mcp_icqq_'));
29
+ const icqqTools = pool.filter(t => t.name.startsWith('icqq_'));
30
+ const pinned: AgentTool[] = [];
31
+ const bash = pool.find(t => t.name === 'bash');
32
+ if (bash) pinned.push(bash);
33
+ const preferOrder = [
34
+ 'mcp_icqq_icqq_invoke',
35
+ 'mcp_icqq_icqq_list_actions',
36
+ 'icqq_send_user_like',
37
+ 'icqq_friend_list',
38
+ 'icqq_poke',
39
+ ];
40
+ for (const name of preferOrder) {
41
+ const t =
42
+ icqqMcpTools.find(x => x.name === name) ??
43
+ icqqTools.find(x => x.name === name);
44
+ if (t) pinned.push(t);
45
+ }
46
+ for (const t of [...icqqMcpTools, ...icqqTools]) {
47
+ if (pinned.length >= maxTools) break;
48
+ if (!pinned.some(p => p.name === t.name)) pinned.push(t);
49
+ }
50
+
51
+ const extra = filterTools(query, pool, { maxTools, minScore: 0.08 })
52
+ .filter(t => !pinned.some(p => p.name === t.name));
53
+
54
+ const merged: AgentTool[] = [...pinned];
55
+ for (const t of extra) {
56
+ if (merged.length >= maxTools) break;
57
+ merged.push(t);
58
+ }
59
+ return merged.slice(0, maxTools);
60
+ }
61
+
62
+ const ORCHESTRATOR_ICQQ = [
63
+ 'On icqq/QQ: use run_deferred_task with tool_query "mcp_icqq_icqq_invoke" or "icqq_send_user_like".',
64
+ 'Examples: send_private_msg, friend_like; do not use mcp_filesystem_* for QQ tasks.',
65
+ 'Skip tool_search when the user clearly asks to send a message, like a friend, or poke on QQ.',
66
+ ].join('\n');
67
+
68
+ const WORKER_ICQQ = [
69
+ 'Send private message: `mcp_icqq_icqq_invoke` action `send_private_msg` params `{ user_id, message }`, or bash `icqq friend send <uid> "<text>"`.',
70
+ 'Friend like: action `friend_like` or `icqq_send_user_like`, or bash `icqq friend like <uid> -t <times>`.',
71
+ 'Use `icqq_list_actions` only if action name is unclear.',
72
+ 'Do NOT use mcp_filesystem_* or explore node_modules / package.json to "discover" icqq.',
73
+ 'Do not stop at --help; execute the action the goal describes.',
74
+ ].map(line => `- ${line}`).join('\n');
75
+
76
+ export function createIcqqAgentPromptContributor(): AgentPromptContributor {
77
+ return {
78
+ platform: 'icqq',
79
+
80
+ async buildSections(ctx: AgentPromptBuildContext): Promise<AgentPromptSection[] | null> {
81
+ if (ctx.slot === 'orchestrator') {
82
+ if (!ctx.toolSearch) return null;
83
+ return [{
84
+ id: 'platform.icqq.orchestrator',
85
+ title: '## icqq / QQ',
86
+ body: ORCHESTRATOR_ICQQ,
87
+ priority: 50,
88
+ }];
89
+ }
90
+ if (ctx.slot === 'deferred_worker') {
91
+ const query = ctx.deferred?.toolQuery ?? ctx.deferred?.goal ?? '';
92
+ const goal = ctx.deferred?.goal ?? '';
93
+ if (!isIcqqDelegatedTask(query, goal)) return null;
94
+ return [{
95
+ id: 'platform.icqq.deferred_worker',
96
+ title: '## icqq / QQ(本任务)',
97
+ body: WORKER_ICQQ,
98
+ priority: 50,
99
+ }];
100
+ }
101
+ return null;
102
+ },
103
+
104
+ matchesDeferredTask(ctx: AgentPromptBuildContext): boolean {
105
+ const query = ctx.deferred?.toolQuery ?? ctx.deferred?.goal ?? ctx.userMessagePreview ?? '';
106
+ const goal = ctx.deferred?.goal ?? ctx.userMessagePreview ?? '';
107
+ return isIcqqDelegatedTask(query, goal);
108
+ },
109
+
110
+ selectDeferredTools(query, goal, catalog, maxTools) {
111
+ if (!isIcqqDelegatedTask(query, goal)) return null;
112
+ return selectIcqqDeferredTools(query, goal, catalog, maxTools);
113
+ },
114
+ };
115
+ }
package/src/bot.ts CHANGED
@@ -4,14 +4,7 @@
4
4
  * 不再直接依赖 @icqqjs/icqq 协议库。
5
5
  * 登录由 `icqq login` 完成,本 Bot 只负责连接守护进程并收发消息。
6
6
  */
7
- import {
8
- Bot,
9
- Message,
10
- SendOptions,
11
- MessageSegment,
12
- SendContent,
13
- segment,
14
- } from "zhin.js";
7
+ import { formatCompact, Bot, Message, MessageSegment, segment, SendContent, SendOptions } from 'zhin.js';
15
8
  import type {
16
9
  IcqqBotConfig,
17
10
  IcqqSenderInfo,
@@ -64,20 +57,20 @@ export class IcqqBot implements Bot<IcqqBotConfig, IpcMessageEventData> {
64
57
  this.intentionalDisconnect = false;
65
58
  const rpc = this.$config.rpc;
66
59
 
67
- if (rpc) {
68
- this.logger.info(
69
- `[${this.$id}] 正在通过 RPC 连接 icqq 守护进程 (${rpc.host}:${rpc.port})...`,
70
- );
71
- } else {
72
- this.logger.info(`[${this.$id}] 正在连接 icqq 守护进程...`);
73
- }
60
+ this.logger.debug(formatCompact( {
61
+ connecting: this.$id,
62
+ mode: rpc ? "rpc" : "ipc",
63
+ host: rpc?.host,
64
+ port: rpc?.port,
65
+ }));
74
66
 
75
67
  await this.rebindIpcSession();
76
68
 
77
- this.logger.info(`[${this.$id}] 已连接守护进程${rpc ? " (RPC)" : ""}`);
78
- this.logger.info(
79
- `[${this.$id}] 登录成功,好友 ${this.friends.size},群 ${this.groups.size}`,
80
- );
69
+ this.logger.info(formatCompact( {
70
+ bot: this.$id,
71
+ friends: this.friends.size,
72
+ groups: this.groups.size,
73
+ }));
81
74
  }
82
75
 
83
76
  /** 建立或恢复与守护进程的 IPC/RPC 会话(订阅、缓存列表) */
@@ -147,23 +140,33 @@ export class IcqqBot implements Bot<IcqqBotConfig, IpcMessageEventData> {
147
140
  const delayMs = base + jitter;
148
141
 
149
142
  this.$connected = false;
150
- this.logger.warn(
151
- `[${this.$id}] 与 icqq 守护进程连接已断开,${delayMs}ms 后尝试重连(第 ${attempt + 1} 次)…`,
152
- );
143
+ this.logger.warn(formatCompact( {
144
+ op: "disconnect",
145
+ bot: this.$id,
146
+ ok: false,
147
+ delay_ms: delayMs,
148
+ attempt: attempt + 1,
149
+ }));
153
150
 
154
151
  await new Promise<void>((r) => setTimeout(r, delayMs));
155
152
  if (this.intentionalDisconnect) break;
156
153
 
157
154
  try {
158
155
  await this.rebindIpcSession();
159
- this.logger.info(
160
- `[${this.$id}] 已重新连接守护进程,好友 ${this.friends.size},群 ${this.groups.size}`,
161
- );
156
+ this.logger.info(formatCompact( {
157
+ op: "reconnect",
158
+ bot: this.$id,
159
+ friends: this.friends.size,
160
+ groups: this.groups.size,
161
+ }));
162
162
  break;
163
163
  } catch (e: any) {
164
- this.logger.warn(
165
- `[${this.$id}] 重连失败: ${e?.message ?? String(e)}`,
166
- );
164
+ this.logger.warn(formatCompact( {
165
+ op: "reconnect",
166
+ bot: this.$id,
167
+ ok: false,
168
+ error: e?.message ?? String(e),
169
+ }));
167
170
  }
168
171
  }
169
172
  } finally {
@@ -204,7 +207,7 @@ export class IcqqBot implements Bot<IcqqBotConfig, IpcMessageEventData> {
204
207
  this.subscriptions = [];
205
208
  this.ipc?.close();
206
209
  this.$connected = false;
207
- this.logger.info(`[${this.$id}] 已断开连接`);
210
+ this.logger.info(formatCompact( { op: "disconnect", bot: this.$id }));
208
211
  }
209
212
 
210
213
  // ── 消息处理 ───────────────────────────────────────────────────────
@@ -245,9 +248,12 @@ export class IcqqBot implements Bot<IcqqBotConfig, IpcMessageEventData> {
245
248
  $timestamp: raw.time * 1000,
246
249
  $recall: async () => {
247
250
  // 合成 id 无法撤回
248
- this.logger.warn(
249
- `[${this.$id}] 收到的消息无法撤回(守护进程推送不含 message_id)`,
250
- );
251
+ this.logger.warn(formatCompact( {
252
+ op: "recall",
253
+ bot: this.$id,
254
+ ok: false,
255
+ error: "no message_id in push",
256
+ }));
251
257
  },
252
258
  $reply: async (
253
259
  content: SendContent,
@@ -278,7 +284,12 @@ export class IcqqBot implements Bot<IcqqBotConfig, IpcMessageEventData> {
278
284
  message_id: id,
279
285
  });
280
286
  if (!resp.ok) {
281
- this.logger.warn(`[${this.$id}] 撤回消息失败: ${resp.error}`);
287
+ this.logger.warn(formatCompact( {
288
+ op: "recall",
289
+ bot: this.$id,
290
+ ok: false,
291
+ error: resp.error,
292
+ }));
282
293
  }
283
294
  }
284
295
 
package/src/index.ts CHANGED
@@ -2,7 +2,14 @@
2
2
  * ICQQ 适配器入口:类型扩展、导出、注册
3
3
  */
4
4
  import path from "path";
5
- import { usePlugin, type Plugin, type ToolFeature } from "zhin.js";
5
+ import {
6
+ usePlugin,
7
+ type Plugin,
8
+ type ToolFeature,
9
+ registerAgentPromptContributor,
10
+ unregisterAgentPromptContributor,
11
+ } from "zhin.js";
12
+ import { createIcqqAgentPromptContributor } from "./agent-prompt.js";
6
13
  import type { Router } from "@zhin.js/http";
7
14
  import { PageManager } from "@zhin.js/console";
8
15
  import { IcqqAdapter } from "./adapter.js";
@@ -34,11 +41,13 @@ provide({
34
41
  name: "icqq",
35
42
  description: "ICQQ Adapter",
36
43
  mounted: async (p: Plugin) => {
44
+ registerAgentPromptContributor(createIcqqAgentPromptContributor());
37
45
  const adapter = new IcqqAdapter(p);
38
46
  await adapter.start();
39
47
  return adapter;
40
48
  },
41
49
  dispose: async (adapter: IcqqAdapter) => {
50
+ unregisterAgentPromptContributor("icqq");
42
51
  await adapter.stop();
43
52
  },
44
53
  } as any);
@@ -1,41 +0,0 @@
1
- ---
2
- name: icqq
3
- platforms:
4
- - icqq
5
- description: '通过 icqq 命令行操作 QQ 账号。适用于:发私聊或群消息、撤回、查聊天记录;好友(列表、资料、备注、戳一戳、点赞、删好友、分组);群(禁言、踢人、公告、签到、精华、成员、邀请、全体禁言);好友/群验证与入群请求;群文件;昵称头像签名、在线状态;黑名单、OCR、Webhook、通知;登录与守护进程。用户提到 QQ、企鹅、好友、群聊、@、撤回、禁言、踢人、加群、好友请求、群文件、签到等时使用本技能。'
6
- argument-hint: '用一句话说明要对 QQ 执行的操作,例如「给好友 12345 发一条你好」或「把群 11111 里的用户 67890 禁言 10 分钟」'
7
- disable-model-invocation: true
8
- ---
9
-
10
- # icqq — 用命令行操作 QQ
11
-
12
- 通过 **`icqq`** 命令行工具操作 QQ。需先 **`icqq login`** 启动守护进程后再执行其它命令。
13
-
14
- ## 使用流程
15
-
16
- 1. **判断模块** — 对照下方「模块表」,匹配用户意图属于哪一类
17
- 2. **只读对应参考** — 仅打开与意图相关的 `references/*.md`,不要凭记忆猜命令
18
- 3. **执行命令** — 在终端运行 `icqq …`,把结果回报给用户;未登录或守护未起时命令失败即如实说明
19
-
20
- ## 模块表
21
-
22
- 按用户想做的事,打开对应参考文件:
23
-
24
- | 用户意图 | 模块 | 参考文档 |
25
- |----------|------|----------|
26
- | 发消息、撤回、聊天记录、消息详情、合并转发 | 消息 | [messaging.md](./references/messaging.md) |
27
- | 好友列表、查看、发消息、戳一戳、点赞、删除、备注、文件、好友分组 | 好友 | [friends.md](./references/friends.md) |
28
- | 群:发消息、禁言、踢人、公告、邀请、签到、精华、成员、表态 | 群管理 | [groups.md](./references/groups.md) |
29
- | 昵称、头像、签名、群名片、群头衔、加群方式、匿名等设置 | 设置 | [settings.md](./references/settings.md) |
30
- | 好友请求、群请求、入群验证 | 请求 | [requests.md](./references/requests.md) |
31
- | 群文件:目录、上传下载、转发 | 群文件 | [gfs.md](./references/gfs.md) |
32
- | 登录、服务/守护、配置、OCR、黑名单、Webhook、通知、UID 转换、陌生人、漫游表情、缓存、重载、频道、RPC、补全 | 通用 | [general.md](./references/general.md) |
33
-
34
- ## 全局约定
35
-
36
- - `<uid>` = QQ 号(数字),`<gid>` = 群号(数字)
37
- - 多账号:全局参数 `-u <uin>` 或环境变量 `ICQQ_CURRENT_UIN`;默认用配置里的 `currentUin`
38
- - **自动执行发消息** 优先用 **`icqq friend send` / `icqq group send`**(非交互);`icqq friend chat` / `icqq group chat` 为交互式,不适合代理串行跑
39
- - CQ 码片段:`[face:id]` `[image:路径或URL]` `[at:uid]` `[at:all]` `[dice]` `[rps]`
40
- - 含空格的内容用英文双引号包起来:`icqq friend send 12345 "你好 世界"`
41
- - 批量操作用 `&&` 串联多条命令
@@ -1,54 +0,0 @@
1
- # Friends
2
-
3
- ## List & View
4
-
5
- ```
6
- icqq friend list # List all friends
7
- icqq friend view <uid> # View friend profile
8
- icqq friend avatar-url <uid> # Get avatar URL
9
- ```
10
-
11
- ## Actions
12
-
13
- ```
14
- icqq friend send <uid> <message> # Send private message
15
- icqq friend poke <uid> # Poke a friend
16
- icqq friend like <uid> [-t times] # Like (1-20 times, default 1)
17
- icqq friend delete <uid> [-b] # Delete friend (-b: also block)
18
- icqq friend remark <uid> <remark> # Set friend remark/alias
19
- icqq friend add <uid> # Add friend (optionally via group)
20
- ```
21
-
22
- ## Files
23
-
24
- ```
25
- icqq friend send-file <uid> <file> # Send file to friend
26
- icqq friend file-info <uid> <fid> # Get file info
27
- icqq friend file-url <uid> <fid> # Get file download URL
28
- icqq friend recall-file <uid> <fid> # Recall a sent file
29
- ```
30
-
31
- ## Friend Classes (Groups)
32
-
33
- ```
34
- icqq friend class list # List friend groups
35
- icqq friend class add <name> # Create friend group
36
- icqq friend class delete <id> # Delete friend group
37
- icqq friend class rename <id> <name> # Rename friend group
38
- icqq friend class set <uid> <id> # Move friend to group
39
- ```
40
-
41
- ## Examples
42
-
43
- ```bash
44
- icqq friend list
45
- icqq friend view 12345
46
- icqq friend send 12345 "你好"
47
- icqq friend poke 12345
48
- icqq friend like 12345 -t 10
49
- icqq friend remark 12345 "小王"
50
- icqq friend delete 12345 -b
51
- icqq friend send-file 12345 ./doc.pdf
52
- icqq friend class list
53
- icqq friend class add "大学同学"
54
- ```
@@ -1,230 +0,0 @@
1
- # General
2
-
3
- ## Account
4
-
5
- > Use **`icqq service status`** for service/daemon state, or **`icqq profile`** / **`icqq friend list`** to verify the daemon answers over IPC.
6
-
7
- ```
8
- icqq login # Login QQ and start daemon (interactive wizard)
9
- icqq login -r # Quick reconnect using saved token
10
- icqq login -q <uid> -r # Quick reconnect specific account
11
- icqq logout # Logout and stop daemon (token invalidated)
12
- icqq logout -k # Disconnect only, keep token (login -r still works)
13
- icqq logout <uin> # Logout specific account
14
- icqq switch # Switch current account (interactive)
15
- icqq switch <uin> # Switch to specific account
16
- icqq profile # View current account profile
17
- icqq requests # View pending friend/group requests
18
- ```
19
-
20
- ## System Service (auto-restart on crash, start on boot)
21
-
22
- ```
23
- icqq service install # Register daemon as system service (launchd/systemd)
24
- icqq service install -a # Install service for all configured accounts
25
- icqq service uninstall # Remove system service
26
- icqq service uninstall -a # Uninstall all
27
- icqq service start # Start installed service
28
- icqq service start -a # Start all
29
- icqq service stop # Stop service (keeps service file, no restart until start)
30
- icqq service stop -a # Stop all
31
- icqq service status # Show service install/running state
32
- icqq service status -a # Show status for all accounts
33
- ```
34
-
35
- Note: `icqq logout` does NOT prevent service auto-restart. To permanently stop, uninstall the service first.
36
-
37
- ## Config
38
-
39
- ```
40
- icqq config get # View all config
41
- icqq config get <key> # View specific config key (currentUin, webhookUrl, notifyEnabled)
42
- icqq config set <key> <value> # Set config value
43
- ```
44
-
45
- ## Multi-Instance
46
-
47
- Use `-u <uin>` global flag or `ICQQ_CURRENT_UIN` env to target a specific account.
48
- Default falls back to `config.currentUin`.
49
-
50
- ```
51
- icqq -u 12345 profile # View profile for account 12345
52
- ICQQ_CURRENT_UIN=12345 icqq friend list
53
- ```
54
-
55
- ## Blacklist
56
-
57
- ```
58
- icqq blacklist # View blacklist
59
- ```
60
-
61
- ## OCR
62
-
63
- ```
64
- icqq ocr <image> # OCR image text recognition (local file path)
65
- ```
66
-
67
- ## Webhook
68
-
69
- ```
70
- icqq webhook # View current webhook config
71
- icqq webhook set <url> # Set webhook URL (daemon pushes events via POST)
72
- icqq webhook off # Disable webhook
73
- ```
74
-
75
- ## Notification
76
-
77
- ```
78
- icqq notify # View notification status
79
- icqq notify on # Enable system notifications
80
- icqq notify off # Disable system notifications
81
- ```
82
-
83
- ## Conversion
84
-
85
- ```
86
- icqq convert uid <qq> # QQ number to UID
87
- icqq convert uin <uid> # UID to QQ number
88
- ```
89
-
90
- ## Keys & URLs
91
-
92
- ```
93
- icqq get client-key # Get ClientKey
94
- icqq get pskey # Get PSKey
95
- icqq get video-url <vid> # Get video download URL
96
- ```
97
-
98
- ## Stranger
99
-
100
- ```
101
- icqq stranger view <uid> # View stranger profile
102
- icqq stranger status <uid> # Check online status
103
- icqq stranger add-setting <uid> # Check add-friend settings
104
- ```
105
-
106
- ## Roaming Emoji (Stamps)
107
-
108
- ```
109
- icqq stamp list # List roaming emojis
110
- icqq stamp delete # Delete roaming emoji
111
- ```
112
-
113
- ## Cache & Reload
114
-
115
- ```
116
- icqq cache clean # Clear cache
117
- icqq reload friends # Refresh friend list
118
- icqq reload groups # Refresh group list
119
- icqq reload blacklist # Reload blacklist
120
- icqq reload guilds # Reload guild list
121
- icqq reload strangers # Reload stranger list
122
- ```
123
-
124
- ## Guild (Server & Channel)
125
-
126
- ```
127
- icqq guild list # List guilds
128
- icqq guild info <guild_id> # View guild info
129
- icqq guild members <guild_id> # List guild members
130
- icqq guild channel list <guild_id> # List subchannels
131
- icqq guild channel send <guild_id> <channel_id> <message> # Send channel message
132
- icqq guild channel chat <guild_id> <channel_id> # Interactive channel chat
133
- icqq guild channel recall <guild_id> <channel_id> <seq> # Recall channel message
134
- icqq guild channel share <guild_id> <channel_id> <url> <title> # Share post link
135
- icqq guild channel forum-url <guild_id> <channel_id> <forum_id> # Get forum URL
136
- ```
137
-
138
- ## Shell Completion
139
-
140
- ```
141
- icqq completion [shell] # Generate shell completion script (bash/zsh/fish)
142
- ```
143
-
144
- ## RPC (TCP Remote Connection)
145
-
146
- The daemon supports optional TCP remote access for cross-machine QQ account control.
147
-
148
- ### Configuration
149
-
150
- In `~/.icqq/config.json`:
151
-
152
- ```json
153
- {
154
- "rpc": {
155
- "enabled": true,
156
- "host": "127.0.0.1",
157
- "port": 0
158
- }
159
- }
160
- ```
161
-
162
- Or via CLI:
163
-
164
- ```
165
- icqq config set rpc.enabled true # Enable RPC TCP listener
166
- icqq config set rpc.host 0.0.0.0 # Listen on all interfaces (for remote access)
167
- icqq config set rpc.port 9100 # Set listen port (0 = auto-assign)
168
- ```
169
-
170
- | Field | Description | Default |
171
- |-------|-------------|---------|
172
- | `enabled` | Enable RPC TCP listener | `false` |
173
- | `host` | Listen address, `"0.0.0.0"` for remote | `"127.0.0.1"` |
174
- | `port` | Listen port, `0` = auto-assign | `0` |
175
-
176
- ### Security
177
-
178
- - **HMAC-SHA256 challenge-response auth** — token never transmitted over network
179
- - **IP rate limiting** — 5 failures in 5 minutes → auto-block
180
- - **Default localhost only** — must explicitly set `host: "0.0.0.0"` for remote access
181
- - **4KB unauthenticated buffer limit** — prevents memory exhaustion
182
-
183
- ### Programmatic Access
184
-
185
- ```typescript
186
- import { IpcClient } from "@icqqjs/cli/lib/ipc-client";
187
-
188
- // Option 1: Specify host/port/token directly
189
- const client = await IpcClient.connectRpc({
190
- host: "192.168.1.100",
191
- port: 9100,
192
- token: "your-token-here",
193
- });
194
-
195
- // Option 2: Auto-read from daemon.rpc file (local only)
196
- const client = await IpcClient.connectRpcByUin(12345);
197
-
198
- const resp = await client.request("list_friends");
199
- client.close();
200
- ```
201
-
202
- ### Auth Flow
203
-
204
- 1. Client connects to TCP port
205
- 2. Server sends `{ "challenge": "<random-hex>" }`
206
- 3. Client computes `HMAC-SHA256(token, challenge)` → digest
207
- 4. Client sends `{ "action": "auth", "params": { "digest": "<hex>" } }`
208
- 5. Server verifies → authenticated
209
-
210
- ## Examples
211
-
212
- ```bash
213
- icqq service status
214
- icqq profile
215
- icqq requests
216
- icqq login -r
217
- icqq config get
218
- icqq config set currentUin 12345
219
- icqq switch 12345
220
- icqq -u 12345 profile
221
- icqq ocr ./screenshot.png
222
- icqq webhook set https://example.com/hook
223
- icqq notify on
224
- icqq convert uid 12345
225
- icqq stranger view 12345
226
- icqq stamp list
227
- icqq cache clean
228
- icqq reload friends
229
- icqq guild list
230
- ```
@@ -1,49 +0,0 @@
1
- # Group File System (GFS)
2
-
3
- ## List Files
4
-
5
- ```
6
- icqq group fs list <gid> # List root directory
7
- icqq group fs list <gid> -p <pid> # List subdirectory by parent ID
8
- ```
9
-
10
- ## Info & Stats
11
-
12
- ```
13
- icqq group fs info <gid> # View GFS usage stats (space, file count)
14
- icqq group fs stat <gid> <fid> # View file/directory details
15
- ```
16
-
17
- ## Manage
18
-
19
- ```
20
- icqq group fs mkdir <gid> <name> # Create directory
21
- icqq group fs delete <gid> <fid> # Delete file/directory by ID
22
- icqq group fs rename <gid> <fid> <name> # Rename file/directory
23
- icqq group fs move <gid> <fid> <pid> # Move file to directory
24
- ```
25
-
26
- ## Upload & Download
27
-
28
- ```
29
- icqq group fs upload <gid> <file> # Upload file to group
30
- icqq group fs download <gid> <fid> # Get download URL
31
- icqq group fs forward <gid> <fid> <target_gid> # Forward file to another group
32
- icqq group fs forward-offline <gid> <fid> # Convert to offline file
33
- ```
34
-
35
- The `<fid>` (file ID) is shown in `icqq group fs list` output.
36
-
37
- ## Examples
38
-
39
- ```bash
40
- icqq group fs list 67890
41
- icqq group fs info 67890
42
- icqq group fs stat 67890 abc123
43
- icqq group fs mkdir 67890 "会议资料"
44
- icqq group fs upload 67890 ./report.pdf
45
- icqq group fs download 67890 abc123
46
- icqq group fs rename 67890 abc123 "新文件名"
47
- icqq group fs move 67890 abc123 def456
48
- icqq group fs delete 67890 abc123
49
- ```