10. QQ 机器人(官方开放平台)
机器人:「吃白饭的大肥鱼」,AppID 1906280003。
10.1 申请
q.qq.com用已实名的 QQ 扫码登录,主体认证选个人,填身份证 + 手机 QQ 扫脸- 应用管理 → 创建机器人(昵称、简介、头像 240×240 以上正方形)
- 提交审核,1–3 个工作日,通过后拿到 AppID + AppSecret(Secret 只显示一次)
- 开发管理 → 沙箱配置,把自己的 QQ 号加进体验用户,否则私聊会提示"该机器人去火星了"
个人主体不能公开上架,只能自己(和白名单里的人)用。想让陌生人加,需要企业认证 + AI 模型备案。
10.2 接入方式:必须 WebSocket
| WebSocket ✅ | Webhook | |
|---|---|---|
| 公网 IP | 不需要 | 需要 |
| 域名/证书 | 不需要 | 需要 |
| 适合 | 家用电脑 | 服务器 |
千万不要先配 webhook——一旦配了回调地址,官方会禁用 WebSocket 模式,通常切不回来。
10.3 配置(cordis.patch.yml)
- id: im-qqbot config: appId: "1906280003" appSecret: <你的 AppSecret> directPrompt: | (人设 + 工具规则,见下) access: c2cMode: allowlist c2cAllow: - <你的 openid>
openid 必须从真实事件里拿(日志里 Processing: scope=c2c peerId=... 那个), 用开发者后台看到的 id 会报 11255。
10.4 directPrompt 里要写死的规则
- 每轮必须调
dafeiyu_play_action挑一个动作(清单见第 11 节) - 语音三到五次挑一次,且内容必须和文字不一样;调用时
channel必须传qq - 工具调用不要向用户解释
聊天里可用指令:
/new(清空上下文)、/compact(压缩历史)、/model、/bot-status、/bot-help。
11. 自建插件 dsh-dafeiyu-action
源码在 _plugins\dsh-dafeiyu-action\(index.js / package.json / cordis.patch.yml)。 给 Agent 两个工具:
| 工具 | 作用 |
|---|---|
dafeiyu_play_action(clip) | 调桌宠控制口 7799,让桌面上的她做动作 |
dafeiyu_speak(text, channel) | 起 直播\发声.mjs;channel=qq 发语音条,local 本机念 |
11.1 安装(不能走 dsh plugin add)
dsh plugin --profile desktop add 会报 profile "desktop" is managed exclusively by the Electron application。手动两步:
# 1. 复制进 profileCopy-Item E:\llmood\dsh\_plugins\dsh-dafeiyu-action ` E:\llmood\dsh\profiles\desktop\node_modules\dsh-dafeiyu-action -Recurse -Force
# 2. profiles\desktop\cordis.patch.yml 末尾追加- insert: - id: dafeiyu-action name: dsh-dafeiyu-action
然后完全退出 DSH 再打开,日志里应出现 dafeiyu-action: 已注册 dafeiyu_play_action(桌宠 7799) / dafeiyu_speak。
11.2 三个必知的坑
- 改完先
node --check。少一个逗号整个插件加载失败,症状是"只有动作没有语音"——很难一眼看出。 - 工具上下文里没有
sessionId(exec 只有 token / callId / agent / deferContext / concludeTurn / signal / arguments), 所以不能按会话判断渠道,渠道靠channel参数由调用方传。 - DSH 桌面端的老会话拿不到新工具,插件更新后要开新会话(QQ 每条消息都是独立回合,不受影响)。
11.3 桌面端自动触发:往 system prompt 注入
QQ 有 directPrompt,桌面端没有。所以插件 inject = ['tools', 'systemPrompt'], 在 apply() 里注册一段系统提示:
ctx.systemPrompt.section({ name: 'dafeiyu:action-guidance', order: 150, // 工具指引的约定区间是 100–199 text: '每次回复主人时调用一次 dafeiyu_play_action …',});
这会让桌面端每一轮对话都拿到「回完话让她动一下」的规则,不需要用户提醒。
- 服务拿不到时只
warn,不影响 QQ 那条路 - 日志里会打
动作提示已注入 systemPrompt(order 150),没这句就是没注入成功 order: 150别乱改:-100是 harness 身份、0是人格,工具指引在 100–199
11.4 动作清单要改四处
加/删动作时这四处必须同时改,否则会出现「菜单里有但模型选不到」或反之:
| 位置 | 内容 |
|---|---|
_setup\pet-actions\apply-pet-actions.ps1 | $clips 表(素材源头) |
_setup\helper-patch\patch-helper.py | ACTION_LABELS + ACTION_GROUPS(右键菜单) |
_plugins\dsh-dafeiyu-action\index.js | ACTIONS 枚举 + ACTION_HINT(模型看到的) |
profiles\desktop\cordis.patch.yml | im-qqbot 的 directPrompt(QQ 会话看到的) |
ACTION_GROUPS是白名单:不在组里的动作_playable_clips()能返回,但右键菜单不显示。
11.5 连调防抖
模型偶尔一轮里连调好几个动作。插件会把后一次调用 clearTimeout 掉前一次, 只播最后一个——否则几个定时器在同一秒触发,前面几个白跑还把日志刷满。
延时 4500ms 是故意的:回合结束时桌宠会放「完成任务」的庆祝动画,不等它放完,我们的动作会被盖掉。 可用环境变量 DAFEIYU_ACTION_DELAY_MS 覆盖。
12. 语音
12.1 发声.mjs
一次合成、按参数决定去哪:
| 参数 | 行为 |
|---|---|
| (默认) | 本机播放 + 发 QQ 语音条 |
--local-only | 只在电脑上念 |
--qq-only | 只发 QQ 语音条(不在电脑外放) |
node E:\llmood\dsh\直播\发声.mjs "要说的话" --qq-only
音色走 edge-tts 的 zh-CN-XiaoyiNeural(和直播同一条线)。
12.2 QQ 语音条
- 上传:
POST /v2/users/{openid}/files,file_type=3,file_data用 base64 - 发送:
msg_type: 7+media.file_info - mp3 直接可用,不需要转 silk(实测客户端显示为语音条)
- 单条几十 KB,远低于 20MB 软限
12.3 不要弹黑窗口
所有子进程都要带 windowsHide: true(插件 spawn、python、ffmpeg、powershell), 否则每说一句就闪一个 cmd 窗口。
13. 记忆回流与主动消息
13.1 QQ 聊天 → 共用记忆
直播\QQ回流.mjs:解压 sessions\*qqbot*\session-*\session.v4.jsonl.zstd → 过滤系统注入的上下文 → 写 直播\QQ往来.md,并把值得长期记的事实补进 mnemon\runtime\MEMORY.md。
内置三种保护:事实写成功才推进状态(失败留 pendingDigest 下次补跑)、写前跟记忆比对去重、 摘要只留最近 3 天全文(更早折叠成一行)。
定时(每 3 小时):
schtasks /create /tn "大肥鱼QQ回流" /tr "node \"E:\llmood\dsh\直播\QQ回流.mjs\"" /sc hourly /mo 3 /f
13.2 让她主动找你
node E:\llmood\dsh\直播\QQ主动.mjs # 用人设现编一句发过来node E:\llmood\dsh\直播\QQ主动.mjs --dry # 只看不发
用 msg_type: 0(主动消息)直发 POST /v2/users/{openid}/messages。频控:每用户 20 条/分钟、1000 条/天。 用户在 QQ 里关掉"允许主动发送"就会失败。
主动消息绕过 Agent 会话,所以她不记得自己主动说过什么——回流脚本也捞不到这一条。
14. QQ 常见故障
| 症状 | 原因 | 处理 |
|---|---|---|
| 聊天提示「该机器人去火星了」 | 沙箱/体验用户没配 | 开放平台加自己的 QQ 号 |
她报 unknown tool "dafeiyu_speak" | 会话工具表是旧的 | 开新会话(不用重启程序) |
| 每条都弹黑窗口 | 子进程没 windowsHide | 见 12.3 |
| QQ 里让她发语音,结果电脑外放 | channel 没传 qq | 检查 directPrompt |
| 桌宠不动 | 7799 没起来(DSH 升级冲掉了补丁) | 重跑 _setup\helper-patch\应用右键菜单补丁.cmd |
| 消息发了但手机没收到 | 用户关了"允许主动发送",或超过频控 | 见 13.2 |
| 改了动作但桌宠还是播旧的 | 缓存 %LOCALAPPDATA%\dsh-dafeiyu\<版本>\assets 没删 | 删掉再重启(见 5.2) |
/health 返回的数量不对 | 只更新了包内 manifest,没重建 helper exe | 跑 _setup\helper-patch\应用右键菜单补丁.cmd |
| 右键菜单少了某些动作 | patch-helper.py 的 ACTION_GROUPS 里没加 | 补分组后重建 exe(见 11.4) |
| 桌面端聊天她不动,QQ 里正常 | systemPrompt 注入失败 | 日志搜「动作提示已注入」;没有就查插件 inject |
跑 ps1 报 Unexpected token '}' | 脚本存成 UTF-8 无 BOM,中文注释被按 ANSI 解析 | 用 UTF-8 with BOM 另存 |
| 服务启动报 BOM 解析错 | PowerShell 写 JSON 带了 BOM | 读文件时剥掉开头 \uFEFF |