@zxh126/pi-qqbot 2.0.1 → 2.3.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/CHANGELOG.md +120 -0
- package/README.md +129 -4
- package/approver.ts +33 -12
- package/attachment.ts +502 -0
- package/config.ts +62 -0
- package/constants.ts +24 -0
- package/docs/README.zh-CN.md +117 -4
- package/index.ts +342 -28
- package/package.json +12 -4
- package/qq/api.ts +26 -0
- package/qq/gateway.ts +41 -11
- package/qq/upload.ts +288 -0
- package/remote.ts +81 -0
- package/slash.ts +17 -1
package/docs/README.zh-CN.md
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
| **对话驱动 agent** | QQ 单聊消息送入当前 pi 会话,AI 的回复发回 QQ(长文本自动分片)。 |
|
|
14
14
|
| **消息队列** | 正在处理任务时,后续 QQ 消息会被**排队**而不是被拒;当前任务结束(settled)后按到达顺序自动逐条执行。`/cancel` 是例外——立即生效并清空队列。 |
|
|
15
15
|
| **远程审批** | pi 执行 `bash` / `powershell` / `write` / `edit`,或任何带 `destructiveHint` 注解的工具前,先在 QQ 里申请审批。 |
|
|
16
|
+
| **远程上下文提醒** | **每个会话第一次真正把 QQ 消息交给 pi 跑起来**时,才告诉它「对话来自远程 QQ 用户、本机可能锁屏」:桌面截屏 / 屏幕 OCR / UI 自动化 / 带界面的浏览器默认禁用,要图就离屏渲染再用 `qq_send_file` 发回。仅载入扩展、或本机 TUI 直接对话时都不注入;上下文压缩后自动重新注入。 |
|
|
16
17
|
| **会话级「以后都同意」** | 回复「以后都同意」,**当前会话**内所有审批请求直接放行,连已经挂起的那条也一起放行。 |
|
|
17
18
|
| **单实例锁** | 只有一个 pi 进程作为宿主连接 QQ,其余待命,宿主退出后自动接管。 |
|
|
18
19
|
| **中断正在运行的任务** | 发 `/cancel`(或「取消」/「停止」),当前任务立刻中断 —— QQ 回复、待审批工具调用、写到一半的回答、排队中的消息一并清理。 |
|
|
@@ -20,7 +21,9 @@
|
|
|
20
21
|
| **进度汇报** | 任务运行期间按 `progress.intervalMs`(默认 **15 秒**)推一条进度摘要(轮次、工具调用、正在跑的工具、token 用量)。随时发 `/progress`(别名 `/p`、「进度」)可立即获取;`/progress off` 在本会话内暂停自动汇报,`/progress on` 恢复。推送失败后自动推送静默,直到你再次问询。 |
|
|
21
22
|
| **敏感信息脱敏** | 离开本机的文本先脱敏——进度摘要、审批提示、队列预览、日志文件:`Authorization` 头(含 QQ bot token)、`sk-…`/`ghp_…`/`npm_…`/`AKIA…`/JWT/PEM、`token=`/`password=`/`--api-key` 的值、URL 里的 `user:pass@`,以及超长高熵串。 |
|
|
22
23
|
| **多 bot 同机** | 一份配置里写多个 QQ bot(`qqbots: [...]`,详见 [accounts.md](./accounts.md)),同一台机器上每个 pi 进程按配置顺序接入第一个未上线的 bot;全部在线则待命、每 5 秒重扫,有人退出就接管。别人只是 `/reload` 临时释放的 bot 不会被抢(留 20 秒预约窗口)。接入/接管时会告知当前 bot 名称与工作目录。 |
|
|
23
|
-
|
|
|
24
|
+
| **图片与文件** | QQ 里发来的附件会先下载到临时文件,再以标记行交给 pi——图片是 `图片路径 <path>`,其余按类型是 `语音路径` / `视频路径` / `文档路径` / `压缩包路径` / `文件路径`;QQ 侧收到一条回执(数量、类型、路径)。pi 的 `read` 工具能直接看图片,`bash` 能处理文件。 |
|
|
25
|
+
| **把本机文件发到 QQ** | 让 agent 把机器上的文件发给你(「把 D:\docs\报告.pdf 发给我」)或发 `/sendfile <路径>`;机器人按 5MB 分片上传(QQ 富媒体),图片(png/jpg) / 视频(mp4) / 语音(silk) 直接展示,其余变成可下载的文件卡片。**外发必须先在 QQ 里审批。** |
|
|
26
|
+
| **内置指令** | `/status`、`/queue`、`/progress`、`/reset`、`/cancel`、`/sendfile`、`/help`。 |
|
|
24
27
|
|
|
25
28
|
## 安装
|
|
26
29
|
|
|
@@ -50,6 +53,23 @@ pi install ./pi-qqbot
|
|
|
50
53
|
"queue": {
|
|
51
54
|
"max": 20,
|
|
52
55
|
"ack": true
|
|
56
|
+
},
|
|
57
|
+
"attachments": {
|
|
58
|
+
"enabled": true,
|
|
59
|
+
"dir": "",
|
|
60
|
+
"maxBytes": 26214400,
|
|
61
|
+
"maxPerMessage": 10,
|
|
62
|
+
"retentionHours": 24,
|
|
63
|
+
"maxFiles": 200
|
|
64
|
+
},
|
|
65
|
+
"files": {
|
|
66
|
+
"enabled": true,
|
|
67
|
+
"maxBytes": 31457280
|
|
68
|
+
},
|
|
69
|
+
"remote": {
|
|
70
|
+
"notice": true,
|
|
71
|
+
"guidelines": true,
|
|
72
|
+
"extra": ""
|
|
53
73
|
}
|
|
54
74
|
}
|
|
55
75
|
```
|
|
@@ -68,6 +88,17 @@ pi install ./pi-qqbot
|
|
|
68
88
|
| `queue.ack` | `true` | 排队消息开始执行时是否回执 QQ(入队回执总是会发) |
|
|
69
89
|
| `progress.enabled` | `true` | 任务运行期间是否定期推送进度摘要(会话启动时读取,改完需 `/new` 或重启;运行时用 `/progress off`) |
|
|
70
90
|
| `progress.intervalMs` | `15000` | 推送间隔(可用环境变量 `PI_QQBOT_PROGRESS_MS` 覆盖,便于测试) |
|
|
91
|
+
| `attachments.enabled` | `true` | 是否把附件下载到临时文件并把路径交给 pi;`false` = 只回一句忽略提示、只处理文字 |
|
|
92
|
+
| `attachments.dir` | `""` | 落盘目录;空 = 系统临时文件夹下的 `pi-qqbot/<bot>`(Windows:`%LOCALAPPDATA%\Temp\pi-qqbot\…`) |
|
|
93
|
+
| `attachments.maxBytes` | `26214400` | 单个附件上限(25 MB),超出的记为下载失败、不落盘 |
|
|
94
|
+
| `attachments.maxPerMessage` | `10` | 单条消息最多处理几个附件 |
|
|
95
|
+
| `attachments.retentionHours` | `24` | 超过此时长的临时文件在会话启动时清理 |
|
|
96
|
+
| `attachments.maxFiles` | `200` | 目录内最多保留多少个文件(超出删最旧) |
|
|
97
|
+
| `files.enabled` | `true` | 是否允许把本机文件发到 QQ(工具与 `/sendfile` 共用);`false` 则拒绕 |
|
|
98
|
+
| `files.maxBytes` | `31457280` | 发送单个文件的上限(30MB;QQ 硬限 200MB) |
|
|
99
|
+
| `remote.notice` | `true` | 每会话第一条消息交给 pi 前注入一次「对话来自远程用户」的说明(QQ 侧不可见,压缩后重新注入) |
|
|
100
|
+
| `remote.guidelines` | `true` | 每次来自 QQ 的 run 额外往系统提示里加三条短规则(远程用户、锁屏→离屏渲染、需要人工就直说) |
|
|
101
|
+
| `remote.extra` | `""` | 追加到内置提醒末尾的自定义补充 |
|
|
71
102
|
|
|
72
103
|
也可用环境变量 `QQ_BOT_APPID` / `QQ_BOT_APPSECRET` 代替文件里的凭据(仅单 bot 场景)。
|
|
73
104
|
|
|
@@ -93,7 +124,7 @@ pi install ./pi-qqbot
|
|
|
93
124
|
| 指令 | 说明 |
|
|
94
125
|
|---|---|
|
|
95
126
|
| `/reset` | 重置:清空回复缓冲、审批记忆与自动同意开关(**不换会话**,换会话发 `/new`) |
|
|
96
|
-
| `/status` | 查看本进程服务的 bot(名称 +
|
|
127
|
+
| `/status` | 查看本进程服务的 bot(名称 + 工作目录)、忙闲状态、上一轮来源(QQ / 本机 TUI)、队列长度、自动同意状态、待审批数量、自动汇报模式 |
|
|
97
128
|
| `/queue` | 查看队列(别名 `/q`);`/queue clear` 清空,`/queue drop <编号>` 删一条 |
|
|
98
129
|
| `/progress` | **立即获取当前进度摘要**(别名 `/p`、「进度」「当前进度」「进展」;忙碌时「到哪了」「怎么样了」这类问法同样生效)。手动暂停期间**问一次只回一次**,要重新打开定时汇报需发 `/progress on` 或「恢复汇报」;若只是配额静默,问一次即恢复 |
|
|
99
130
|
| `/progress off` | **在本会话内暂停自动进度汇报**(别名:`pause`、`stop`、`暂停`、「暂停汇报」、「关闭汇报」)。手动 `/progress` 仍可看一次,但不再解除暂停 |
|
|
@@ -101,6 +132,86 @@ pi install ./pi-qqbot
|
|
|
101
132
|
| `/cancel` | **中断当前正在运行的任务**并清空队列(别名:`/stop`、`/abort`、「取消」、「停止」、「中止」、「终止」、「算了」、「停」、「停下」、「停一下」、「别跑了」)。注意:单说「停」是中断**任务**,要关进度推送请说「别汇报了」「闭嘴」或 `/progress off` |
|
|
102
133
|
| `/help` | 帮助 |
|
|
103
134
|
|
|
135
|
+
### QQ 里发来的图片与文件
|
|
136
|
+
|
|
137
|
+
发一张图(或文档、压缩包、语音/视频),机器人会把它下载到临时文件,然后给 pi 一行路径:
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
图片路径 C:\Users\you\AppData\Local\Temp\pi-qqbot\bot-340143\2026-02-11\msg-abc-1-103045.jpg
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
| 附件类型 | 交给 pi 的行 |
|
|
144
|
+
|---|---|
|
|
145
|
+
| 图片 | `图片路径 <path>` |
|
|
146
|
+
| 语音 / 音频 | `语音路径 <path>` |
|
|
147
|
+
| 视频 | `视频路径 <path>` |
|
|
148
|
+
| 文档(pdf、office、文本、代码…) | `文档路径 <path>` |
|
|
149
|
+
| 压缩包(zip、rar、7z、tar…) | `压缩包路径 <path>` |
|
|
150
|
+
| 其它 | `文件路径 <path>` |
|
|
151
|
+
|
|
152
|
+
你自己的文字保持在第一行:发「看下这个」+ 一张图,送给 pi 的就是
|
|
153
|
+
`看下这个\n图片路径 C:\…\a.jpg`——同一轮,路径已在里面。QQ 侧还会收到回执,例如
|
|
154
|
+
`已收到 2 个附件(图片 ×1、文档 ×1),已存为临时文件并交给 pi:` 后跟各条路径;下载失败的附件会列出原因,
|
|
155
|
+
文字部分照常执行。
|
|
156
|
+
|
|
157
|
+
注意:
|
|
158
|
+
|
|
159
|
+
- QQ 的下载地址带短期有效的 `rkey`,所以收到消息的当下就下载。
|
|
160
|
+
- 带附件的消息会**绕过**斜杠命令、审批解析与编号选择,一律当作普通内容交给 pi(附带 `/status` 不会被执行)。
|
|
161
|
+
- 临时文件由 `attachments.retentionHours` / `attachments.maxFiles` 在会话启动时清理;交给 pi 的路径在当前会话(通常一天内)都可读。
|
|
162
|
+
- 落盘文件名只保留 `[0-9a-zA-Z._-]`,并以 QQ 消息 id 作为前缀。
|
|
163
|
+
|
|
164
|
+
### 把本机文件发到 QQ
|
|
165
|
+
|
|
166
|
+
两种触发方式:
|
|
167
|
+
|
|
168
|
+
| 触发 | 用法 |
|
|
169
|
+
|---|---|
|
|
170
|
+
| 自然语言 | 「把 D:\docs\报告.pdf 发给我」——agent 会调 `qq_send_file` 工具 |
|
|
171
|
+
| 斜杠命令 | `/sendfile D:\docs\报告.pdf`(路径带空格就加引号;不开 run,直接执行) |
|
|
172
|
+
|
|
173
|
+
**审批是硬性的,而且每次都问**:`qq_send_file` 无论 `approve.tools` 怎么配都强制走审批,并且**不吃**会话级
|
|
174
|
+
「以后都同意」、也不吃「同意后记住」,因为外发文件等于数据出境,每个文件单独确认。提示里会写明:
|
|
175
|
+
`[审批 #1] 发送文件到 QQ: D:\…` + 「需单独确认」。
|
|
176
|
+
|
|
177
|
+
发送形态(QQ 富媒体分片上传):
|
|
178
|
+
|
|
179
|
+
| 文件 | 对方看到 |
|
|
180
|
+
|---|---|
|
|
181
|
+
| `.png` / `.jpg` / `.jpeg` | 图片直接展示 |
|
|
182
|
+
| `.mp4` | 视频直接播放 |
|
|
183
|
+
| `.silk` | 语音条 |
|
|
184
|
+
| 其他(pdf / zip / mp3 / epub / exe…) | 可下载的文件卡片 |
|
|
185
|
+
|
|
186
|
+
注:
|
|
187
|
+
|
|
188
|
+
- 必须走分片上传(`upload_prepare` → `PUT` → `upload_part_finish` → 合并):URL 上传要求公网可访问,二进制直传只有 5MB 上限。
|
|
189
|
+
- 用被动回复(`srv_send_msg: false` + `msg_type: 7` 带 `msg_id`/`msg_seq`),不烧主动消息额度。
|
|
190
|
+
- QQ 侧还有 **200MB 硬上限**和**每天发送文件总容量上限**(错误码 `40093002`),都翻成中文回执。
|
|
191
|
+
- 成功后会回一行:`已发送「报告.pdf」(2.31 MB,文件卡片)`。
|
|
192
|
+
|
|
193
|
+
### 远程上下文提醒
|
|
194
|
+
|
|
195
|
+
pi 跑在这台机器上,用户在 QQ 那头——而这台机器可能锁屏。所以**每个会话第一次真正把 QQ 消息交给 pi 跑起来**时,
|
|
196
|
+
插件会往**系统提示**里加一段说明(`qq-remote-context` section,排在用户消息之前,QQ 侧看不到),告诉它:
|
|
197
|
+
|
|
198
|
+
- 用户是远程的:看不见屏幕、也点不到弹窗,回复应简明扼要;
|
|
199
|
+
- 桌面截屏、屏幕 OCR、UI 自动化、键鼠模拟、带界面的浏览器默认都不要用(文案里点名了 `mcp__screenshot`、`mcp__winui`),
|
|
200
|
+
锁屏下它们只会拍到锁屏画面或直接失败;
|
|
201
|
+
- 需要图时自己离屏渲染(headless 浏览器渲 HTML、SVG、matplotlib/Pillow…),生成 PNG 再用 `qq_send_file` 发到 QQ,
|
|
202
|
+
不要为了「确认」先截桌面;
|
|
203
|
+
- 只有确实需要判断是否锁屏时,才允许截一次桌面看有没有内容。
|
|
204
|
+
|
|
205
|
+
时机很关键:只有本扩展派发的 QQ 消息真的开跑(`before_agent_start`)时才会注入——**仅仅载入扩展、或者本机在 TUI 里
|
|
206
|
+
直接跟 pi 对话,都不会给 pi 发任何东西**。每个会话注入一次(上下文压缩后重新注入;`remote.extra` 可追加你自己的话)。
|
|
207
|
+
开了 `remote.guidelines` 时,同样的要求会压成三条规则,随每次来自 QQ 的 run 一起进系统提示,避免长会话被摘要后丢失。
|
|
208
|
+
`remote.notice: false` / `remote.guidelines: false` 可分别关掉这两部分。
|
|
209
|
+
|
|
210
|
+
如果同一个会话里你从本机接管——上一轮来自 QQ,下一轮直接在 TUI 里打字——本机那一轮会换成一次性
|
|
211
|
+
`qq-local-handoff` 更正:「远程 QQ 用户」的前提作废(可以正常截屏,不需要 `qq_send_file`)。识别靠 `input` 事件
|
|
212
|
+
(`source: "interactive"`;本扩展自己的 `sendUserMessage` 是 `"extension"`,不会误判),每次交接只更正一次,
|
|
213
|
+
QQ run 还在跑时插话不处理(那时不会开新的 run)。`/status` 会显示 `来源: QQ(远程)` 或 `来源: 本机(TUI)`。
|
|
214
|
+
|
|
104
215
|
### QQ 里的斜杠命令
|
|
105
216
|
|
|
106
217
|
任何以 `/` 开头的消息都会先走路由,再决定是否当成对话:
|
|
@@ -207,7 +318,9 @@ pi 的会话一次只跑一轮 agent run,所以串行调度由 bot 自己做
|
|
|
207
318
|
的自动推送(不重试、不刷屏);你发 `/progress`(或「进度」)即恢复。
|
|
208
319
|
- **手动暂停/恢复**:`/progress off`(或「暂停汇报」)在本会话内停掉自动推送——跨 run 保留,
|
|
209
320
|
之后问 `/progress` 也不会把它打开;`/progress on`(或「恢复汇报」)恢复。开新会话(`/new`、重启)后
|
|
210
|
-
恢复默认开启。`/status` 会显示当前处于哪种模式(开启 / 手动暂停 / 配额静默 / 配置关闭)。
|
|
321
|
+
恢复默认开启。`/status` 会显示当前处于哪种模式(开启 / 手动暂停 / 配额静默 / 等审批暂缓 / 配置关闭)。
|
|
322
|
+
- **审批不被顶走**:有工具审批在等你回复时,自动进度暂缓推送——否则每 15 秒一条进度会把审批提示顶出屏幕;
|
|
323
|
+
你回复(或审批超时)后,下一拍自动恢复。主动发 `/progress` 照旧可用。
|
|
211
324
|
- **保护最终答案**:答案因配额发不出去时会被缓存,等你发下一条消息时以
|
|
212
325
|
`(上一条回复发送失败,补发如下)` 前缀补发。
|
|
213
326
|
- `agent_settled` / `/cancel` / 会话关闭时定时器都会清掉。
|
|
@@ -290,7 +403,7 @@ QQ 网关对同一 bot 只保留一个活跃连接。插件用 `proper-lockfile`
|
|
|
290
403
|
|
|
291
404
|
## 变更日志
|
|
292
405
|
|
|
293
|
-
见 [CHANGELOG.md](../CHANGELOG.md):每个版本改了什么、为什么改。进度汇报的暂停/恢复(`/progress off` / `on`)在 **1.5.0** 加入;多 bot 自动抢占在 **2.0.0**。
|
|
406
|
+
见 [CHANGELOG.md](../CHANGELOG.md):每个版本改了什么、为什么改。进度汇报的暂停/恢复(`/progress off` / `on`)在 **1.5.0** 加入;多 bot 自动抢占在 **2.0.0**;接收 QQ 图片/文件(落盘后以 `图片路径 <path>` 这类标记行交给 pi)在 **2.1.0**;把本机文件发到 QQ(`qq_send_file` / `/sendfile`,富媒体分片上传)在 **2.2.0**。
|
|
294
407
|
|
|
295
408
|
## License
|
|
296
409
|
|