🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

QQ 聊天机器人 wufa-cat/dsh-qq-bot

DeepSeek Harness
wufa-cat9 天前有提交已提供中文文档扫描:含敏感能力

把 QQ 群聊和私聊接入模型,自动收发消息

30.8/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/25 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add wufa-cat/dsh-qq-bot
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · vision
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 9 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 97 处,展示前 55 条)
  • 读取本地文件
    lib/index.js:182
    return readFileSync(join(repoDir, 'persona', `${personaName}.md`), 'utf8')
  • 发起网络请求
    lib/client.js:728
    return fetch(`/qqbot-files${path}`, init).then(async response => {
  • 发起网络请求
    lib/client.js:1172
    const response = await fetch('/qqbot-service/status', { credentials: 'same-origin' })
  • 发起网络请求
    lib/client.js:1192
    const response = await fetch('/qqbot-service/action', {
  • 发起网络请求
    lib/client.js:1216
    const response = await fetch('/qqbot-service/doctor', { credentials: 'same-origin' })
  • 发起网络请求
    lib/client.js:1227
    const response = await fetch('/qqbot-service/init', { method: 'POST', credentials: 'same-origin' })
  • 发起网络请求
    lib/client.js:1559
    const response = await fetch('/qqbot-status', { credentials: 'same-origin' })
  • 写入本地文件
    lib/chatlog.js:22
    mkdirSync(dataDir, { recursive: true })
  • 读取本地文件
    lib/chatlog.js:31
    if (existsSync(this._path(chatId))) {
  • 读取本地文件
    lib/chatlog.js:32
    const parsed = JSON.parse(readFileSync(this._path(chatId), 'utf8'))
  • 删除本地文件
    lib/chatlog.js:57
    try { rmSync(this._path(chatId), { force: true }) } catch { }
  • 写入本地文件
    lib/chatlog.js:69
    writeFileSync(tmp, JSON.stringify(state.log), 'utf8')
  • 读取本地文件
    lib/chatlog.js:82
    if (existsSync(path)) {
  • 读取本地文件
    lib/chatlog.js:83
    const entries = JSON.parse(readFileSync(path, 'utf8'))
  • 读取本地文件
    lib/cq.js:91
    for (const d of readdirSync(root, { withFileTypes: true })) {
  • 读取本地文件
    lib/cq.js:94
    const files = readdirSync(join(root, d.name))
  • 读取本地文件
    lib/cq.js:143
    const info = statSync(file)
  • 读取本地文件
    lib/cq.js:145
    return readFileSync(file).toString('base64')
  • 请求外部主机b23.tv
    lib/cq.js:188
    const resp = await fetch(`https://b23.tv/${code}`, {
  • 发起网络请求
    lib/cq.js:188
    const resp = await fetch(`https://b23.tv/${code}`, {
  • 读取本地文件
    lib/service.js:34
    if (!existsSync(file)) return ''
  • 读取本地文件
    lib/service.js:35
    const parsed = JSON.parse(readFileSync(file, 'utf8'))
  • 读取本地文件
    lib/service.js:92
    composeFileExists: existsSync(join(dir, 'docker-compose.yml')),
  • 读取本地文件
    lib/service.js:120
    { id: 'compose-file', label: 'docker-compose.yml', ok: existsSync(join(dir, 'docker-compose.yml')), detail: dir },
  • 读取本地文件
    lib/service.js:121
    { id: 'data', label: 'NapCat 数据目录', ok: existsSync(join(dir, 'data')), detail: join(dir, 'data') },
  • 读取本地文件
    lib/service.js:122
    { id: 'persona', label: '人格目录', ok: existsSync(join(repoDir, 'persona')), detail: join(repoDir, 'persona') },
  • 读取本地文件
    lib/files.js:56
    if (!existsSync(personaDir)) return []
  • 读取本地文件
    lib/files.js:57
    return readdirSync(personaDir)
  • 读取本地文件
    lib/files.js:60
    const info = statSync(join(personaDir, file))
  • 读取本地文件
    lib/files.js:76
    if (!existsSync(root)) return []
  • 读取本地文件
    lib/files.js:78
    for (const dirent of readdirSync(root, { withFileTypes: true })) {
  • 读取本地文件
    lib/files.js:83
    files = readdirSync(dir)
  • 写入本地文件
    lib/files.js:204
    mkdirSync(personaDir, { recursive: true })
  • 写入本地文件
    lib/files.js:207
    writeFileSync(file, text, 'utf8')
  • 写入本地文件
    lib/files.js:215
    mkdirSync(personaDir, { recursive: true })
  • 写入本地文件
    lib/files.js:233
    writeFileSync(file, template, 'utf8')
  • 删除本地文件
    lib/files.js:242
    rmSync(file)
  • 写入本地文件
    lib/files.js:255
    renameSync(source, target)
  • 删除本地文件
    lib/files.js:273
    rmSync(path)
  • 写入本地文件
    lib/files.js:280
    mkdirSync(dir, { recursive: true })
  • 删除本地文件
    lib/files.js:359
    rmSync(path)
  • 执行外部命令来自配置/变量
    lib/platform.js:50
    const child = spawn(command[0], command[1], { detached: true, stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    lib/platform.js:92
    child = spawn(command, args, {
  • 读取本地文件
    lib/platform.js:159
    return Boolean(dir) && existsSync(dir)
  • 读取本地文件
    lib/scaffold.js:91
    if (existsSync(path)) return
  • 写入本地文件
    lib/scaffold.js:92
    mkdirSync(path, { recursive: true })
  • 读取本地文件
    lib/scaffold.js:103
    const hasPersona = existsSync(personaDir) && readdirSync(personaDir).some(file => file.toLowerCase().endsWith('.md'))
  • 读取本地文件
    lib/scaffold.js:103
    const hasPersona = existsSync(personaDir) && readdirSync(personaDir).some(file => file.toLowerCase().endsWith('.md'))
  • 读取本地文件
    lib/scaffold.js:106
    if (!existsSync(file)) {
  • 写入本地文件
    lib/scaffold.js:107
    writeFileSync(file, PERSONA_TEMPLATE, 'utf8')
  • 读取本地文件
    lib/scaffold.js:111
    kept.push(`persona/ (${readdirSync(personaDir).filter(file => file.toLowerCase().endsWith('.md')).length} 份人设)`)
  • 读取本地文件
    lib/scaffold.js:120
    if (existsSync(composeFile)) {
  • 写入本地文件
    lib/scaffold.js:123
    writeFileSync(composeFile, composeTemplate({ webuiPort, wsPort, platform: platformName }), 'utf8')
  • 写入本地文件
    lib/scaffold.js:128
    writeFileSync(onebotReadme, ONEBOT_README, 'utf8')
  • 发起网络请求
    lib/imagepart.js:18
    const resp = await fetch(url, { signal: AbortSignal.timeout(15000) })
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
涉及外部主机:b23.tv

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/dsh-agent@deepseek-ai/dsh-brand@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-system-prompt
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
展开完整介绍(135 字)↓

QQ 群聊/私聊机器人插件(DeepSeek Harness,macOS/Windows 开箱即用):OneBot v11/NapCat、人设、表情包、工具白名单与联网搜索、对话巡检、关键词规则、定时消息、记忆管理。基于 ezoiLZH/QQ-bot,经原作者许可发布。

README

由 DeepSeek 最新模型翻译生成
dsh-qq-bot -8b5cf6) 非官方移植:本项目是 QQ-bot 的 DeepSeek Harness 插件版。 原项目作者 ezoiLZH —— 人设协议、表情包机制、消息聚合、SKIP/LEAVE 冷却、群内指令等设计全部来自原项目,特此致谢。 本项目经原作者许可发布;按原作者要求,任何转载或二次分发请保留本段署名与上方原项目链接。 如果原作者希望调整署名或撤下本项目,开个 issue 即可,我会立刻处理。 仓库:https://github.com/wufa-cat/dsh-qq-bot · 下载:https://github.com/wufa-cat/dsh-qq-bot/releases 把 QQ 变成 DeepSeek Harness 的聊天入口:OneBot v11(NapCat)收消息,Harness 的模型回消息。 macOS 与 Windows 都能开箱即用——装好插件,在界面里点几下就能跑起来,不需要命令行、不需要 clone 任何仓库。
展开完整文档(README 剩余 1 节)
dsh-qq-bot

-8b5cf6)

非官方移植:本项目是 QQ-bot 的 DeepSeek Harness 插件版。
原项目作者 ezoiLZH —— 人设协议、表情包机制、消息聚合、SKIP/LEAVE 冷却、群内指令等设计全部来自原项目,特此致谢。
本项目经原作者许可发布;按原作者要求,任何转载或二次分发请保留本段署名与上方原项目链接。
如果原作者希望调整署名或撤下本项目,开个 issue 即可,我会立刻处理。

仓库:https://github.com/wufa-cat/dsh-qq-bot · 下载:https://github.com/wufa-cat/dsh-qq-bot/releases

把 QQ 变成 DeepSeek Harness 的聊天入口:OneBot v11(NapCat)收消息,Harness 的模型回消息。
macOS 与 Windows 都能开箱即用——装好插件,在界面里点几下就能跑起来,不需要命令行、不需要 clone 任何仓库。

- 每个 (机器人, 群/私聊) 一个持久智能体会话,人设走系统提示词
- 消息聚合、冷却限频、[SKIP] / [LEAVE] 行为
- 人格(persona/.md)在插件界面里直接编辑
- 表情包按「机器人/分类」管理,界面里上传、删除、直接测试发送
- NapCat(Docker)服务的启动/停止/重启、扫码登录、环境自检、目录打开全在界面里
- 工具白名单:聊天会话默认一个工具都不给;要联网才开 web_search(P0,防止群友间接拿到命令能力)
- 对话巡检:状态灯 + 最近事件 + 跳过原因 + 聊天记录尾巴,排障不用翻日志
- 关键词规则:命中直接回,不进模型
- 定时消息:每天/指定星期往群里发固定内容
- 长期记忆:直接在界面里编辑 data/memory-<chat>.json
- 图片多模态、B 站/分享链接解析、群内指令(/ping、/表情、/reload …)

一、准备:装 Docker

机器人通过 NapCat 连接 QQ,NapCat 跑在 Docker 里。

Windows

1. 安装 Docker Desktop for Windows(自带 docker compose)。
2. 启动 Docker Desktop,等托盘图标变成绿色(引擎就绪)。
3. 不需要在 WSL 里手动装任何东西。

macOS

任选一种:

- Docker Desktop:装好并启动即可;
- colima(更轻):

brew install colima docker docker-compose
colima start --arch aarch64 --vm-type vz --cpu 2 --memory 4

插件会在点「启动服务」时自动 colima start(已装但没运行时)。

Linux 也能跑(用系统 Docker),只是没做专门适配。

二、安装插件

需要已安装 DeepSeek Harness(桌面版或 Web 版)。

直接从 GitHub Release 装(推荐)
dsh plugin --profile desktop add https://github.com/wufa-cat/dsh-qq-bot/releases/download/v1.3.2/dsh-qq-bot-1.3.2.tgz
或者用本地下发的 tarball / 目录
dsh plugin --profile desktop add ./dsh-qq-bot-1.3.2.tgz
或者直接用目录
dsh plugin --profile desktop add /path/to/dsh-plugin
发布到 npm 之后也可以
dsh plugin --profile desktop add dsh-qq-bot

--profile desktop 是桌面版专用配置档;Web 版改成 --profile web。
目录软链安装(add /path/to/dsh-plugin)不会安装插件的依赖,v1.2.2 起已自动回退到 Node 内置 WebSocket,不需要额外处理。

安装完完全退出并重启 Harness(Cmd+Q / 托盘退出),让 Host 侧代码生效。

三、界面里配置(三步)

打开 设置 → QQ 机器人(也可以在插件页找到 QQ 机器人那一行)。

1. 初始化目录

点服务卡片里的 「初始化目录」。它会创建(已存在的绝不覆盖):

~/dsh-qq-bot/ ← 默认工作目录(Windows: %USERPROFILE%\dsh-qq-bot) ├── persona/人设参考模板.md ├── stickers/ ├── data/ └── onebot/napcat-docker/ ├── docker-compose.yml ← 已配好端口与 WebUI 令牌 ├── README.md └── data/{qq,config,plugins}

想换位置:把「工作目录」填成别的绝对路径,再点一次「初始化目录」。

2. 启动服务并扫码登录

- 点 「环境自检」 先确认 Docker / compose / 目录都是 ✔;
- 点 「启动服务」,插件会 docker compose up -d,并自动打开 NapCat WebUI;
- WebUI 里用机器人 QQ 扫码登录(首次约 2 分钟出码,过期就点「重启」重新生成)。

3. 添加机器人

在「机器人」卡片点 添加机器人,填:

| 字段 | 说明 | 例子 |
| QQ 号 | 机器人自己的 QQ | 3177752843 |
| 名字 | 日志与表情包目录用 | 千早爱音 |
| 人设 | persona/ 里的文件名(不带 .md) | Anonther |
| 管理员 | 能用 /reload、/clear 的 QQ 号,逗号分隔 | 3635811460 |
| WS 地址 | 默认指向本机 NapCat | ws://127.0.0.1:3001 |
| WS Token | NapCat 没设就留空 | |

保存后插件会重载并连接。日志里看到 qq-bot: 🤖 [名字] ... 就说明通了。

四、人格

「人格」卡片:列出 persona/.md,点名字在页面里编辑,保存后群里发 /reload(管理员)让机器人换用新人设。
也可以新建(带模板)、删除、重命名。人设内容会作为系统提示词注入每个会话。

五、表情包

目录结构(机器人名字必须与配置里的「名字」一致):

stickers/
└── 千早爱音/ ├── 开心/开心.jpg ├── 喜欢/喜欢.png └── 震惊/震惊-这啥啊.jpg

- 分类名 = 目录名;目录里的图片文件名随意,支持 png/jpg/jpeg/gif/bmp/webp;
- 模型在回复里写 [动画表情:分类名],插件随机挑一张发出去(整条回复只有这个标记时就是单发一张表情);
- 插件把「可用分类」自动写进提示词,不需要在人设里手写清单;
- 界面里可 上传图片到分类、新建分类、展开删除;
- 发送用 base64:// 而不是本地路径——NapCat 在容器里看不到宿主机路径,用路径会静默失败;
- 回复长度限制(chat.maxReplyLength,默认 800)作用在展开表情之前,不会把 base64 截断;
- 手动测试:群里 @机器人 /表情 列分类,@机器人 /表情 开心 直接发一张。

旧布局兼容:stickers/<分类>/图片 也能识别(当 stickers/<机器人名字>/ 不存在时)。根目录直接放图片不会被发送——那些只会显示在卡片的「根目录图片」里。

六、工具白名单与联网搜索(P0)

群里任何人说话都可能触发模型,所以聊天档默认不给任何工具——不能跑命令、不能写文件、不能开子代理。
要什么给什么,白名单写在每个机器人的 tools 里:

| 开关 | 工具 | 说明 |
| webSearch | web_search | 联网搜索,默认 关 |
| webFetch | web_fetch | 抓取网页正文,默认 关(打开搜索后才有意义) |

1.4.0 起:插件自己注册 web_search(宿主全局层)

DSH 桌面版把工具搬进了「agent 预设」,而插件用 agents.create() 建的聊天 agent 不经过预设流程——实测那个 agent 里只有 working_directory,web_search 根本不存在,所以以前「配了搜索也没用」、模型只能自己编 <invoke> 语法。

现在插件在宿主全局层注册一个 web_search(lib/webtool.js),检索仍走后端 ctx.web(凭据/provider 还是 profile 里那套),聊天 agent 自动继承;关掉 tools.webSearch 时用 per-agent restrict 遮掉。另用 tools.guard() 拒绝 bash/write/edit/subagent 这类危险工具执行。

状态接口 web.tool 会告诉你注册结果: json
"web": { "available": true, "tool": { "ok": true, "reason": "已注册" } }

实现是 agentCtx.tools.restrict({ allow })(必须用 agentCtx.tools,用 ctx.get('tools') 会抛 "requires a scoped context")。

工具名从 tools.view(scope).restrictableNames 读(读不到再退回 schemas() / 逐个 get)。读不到工具表时不会用 allow: [] 一刀切——那会把 web_search 一起屏蔽,模型就只能自己编 <invoke> 语法发到群里;这时改成 deny 掉危险工具(bash/write/edit/subagent…),保证联网还能用。

改完后在群里发 /搜索 看状态,/qqbot-status 里每个机器人有: json
"tools": { "webSearch": true, "webFetch": false }, // 配置/指令层面
"toolsAvailable": { "webSearch": true, "webFetch": false } // agent 里真的拿到的

toolsAvailable.webSearch 为 true 才算联网真的可用;为 false 说明 Harness 没把工具给聊天 agent(缺 @deepseek-ai/dsh-tool-web 或 web 服务)。

界面:插件页 → 机器人卡片 → 「工具权限」。也有运行时开关:

- /搜索 on|off(管理员):下一轮重建会话时生效,/搜索 不带参数看当前状态;
- 「运行状态」卡片里的 开 / 关 / 跟随配置 按钮。

搜索凭据不是这个插件管的

搜索后端是 Harness 内置的 DeepSeek 官方搜索(deepseek-official):
- 用 DeepSeek 账号登录 Harness → 自动可用;
- 或环境变量 DEEPSEEK_API_KEY;
- 或「设置 → 插件 → 官方 → 网页搜索」里填 Key。

⚠️ 聊天模型如果走别的服务商(例如 SiliconFlow),搜索仍需要单独的 DeepSeek 凭据,否则报 401。插件界面的状态卡会直接给出这条提示。
💰 Messages 模式搜索 = 一次完整模型调用(60s 超时、最多 5 次),开之前先想清楚值不值。

七、谁可以调用功能(权限)

每个功能单独设置,不再是一个总开关。三个功能:

| 功能 | 管的动作 |
| sticker | /收图(写表情包目录) |
| search | /搜索(切换联网) |
| manage | /ai、/clear、/reload |
yaml
access:
mode: admin # 默认范围:all 全员 | admin 仅管理员 | list 仅白名单
users: [] # 默认白名单 QQ
groups: [] # 默认白名单群号(群里任何人都算)
denyUsers: [] # 默认黑名单,永远优先
denyGroups: []
features: # 每个功能可以覆盖默认值;mode: inherit = 跟随默认
sticker:{ mode: admin }
search: { mode: inherit }
manage: { mode: admin, denyUsers: ["10002"] }

- 判定顺序:黑名单(默认+该功能)→ 管理员 → 该功能 mode(inherit 时用默认 mode);
- 名单和黑名单的条目:QQ 号,或 群:群号(群里任何人都算);
- 管理员始终可用,除非被黑名单点名;

界面里就是一张表:每个功能一行,选范围、填名单(一行一个,也吃逗号)、黑名单折叠在下面。

八、对话巡检与状态灯

插件页顶部「运行状态」:

- 绿/红状态灯:是否连上 OneBot、重连次数、最近错误、已运行时长;
- 计数:收到消息 / 发出回复 / 跳过 / 错误;
- 搜索与 AI 的当前状态(只读;运行时开关用群指令 /搜索、/ai)。

「对话巡检」卡片:

- 最近 60 条事件:谁、在哪个聊天、说了什么、bot 回没回、为什么跳过(冷却 / 没被 @ / AI 关 / 聚合中);
- 下拉选一个 data/<chat>.json 直接看最近 20 条聊天记录。

事件只存在内存环形缓冲(400 条),重启清空;聊天记录本体仍在 data/。

九、关键词规则

命中关键词直接回复,不进模型:快、省钱、不受上下文影响。
yaml
rules:
- enabled: true
pattern: 在吗 mode: contains # contains | exact | regex reply: 在的 {user}
bots: [千早爱音] # 留空 = 所有机器人

- reply 支持 {user}(昵称)、{qq}、{bot};
- 规则优先于模型,但指令优先于规则(/ping 不会被规则抢走)。

十、定时消息 yaml schedules:
- enabled: true
label: 早安 at: "08:00"
days: [1, 2, 3, 4, 5] # 1=周一 … 7=周日;留空 = 每天
bot: 千早爱音 chat: group:123456789 # 或 private:10001 text: 早上好呀~ {weekday}

- 每 20 秒检查一次,同一天同一分钟只发一次;
- {date} {time} {weekday} 会替换;
- 机器人不在线就跳过并记日志(不会补发)。

十一、长期记忆

「长期记忆」卡片直接编辑 data/memory-<chat>.json:一行一条,保存时自动补日期。
新会话建立(种子)时会把这些摘要注入提示词;也可以整份删除。

十二、群内指令

| 指令 | 说明 |
| /help | 指令列表 |
| /ping | 延迟测试 |
| /time | 服务器时间 |
| /表情 [分类] | 列出表情分类 / 直接发一张 |
| /echo 文本 | 复读 |
| /roll | 掷骰子 |
| /calc 1+23 | 计算 |
| /clear [N] | 清除对话记忆 |
| /ai on\|off\|status | 开关 AI 回复(受 access.features.manage 限制) |
| /收图 [分类] | 把图片收进表情包(受 access.features.sticker 限制) |
| /搜索 [on\|off\|跟随] | 联网搜索开关(受 access.features.search 限制) |
| /reload | 重读人设与表情包(管理员) |

十三、目录与清理

「目录与清理」卡片:

- 一键打开 仓库目录 / 人格 / 表情包 / 聊天数据 / OneBot 目录;
- 清理未使用镜像:docker system prune -af(在用的容器不受影响);
- 删除虚拟机:仅 macOS + colima 可用,回收约 3.5 GB,下次启动会重建并重新拉镜像; Windows 上引擎在 WSL2 里,插件不会动它(要彻底重置用 Docker Desktop → Troubleshoot → Reset)。

十四、配置项(cordis.patch.yml)

界面保存的就是这些;一般不用手写。所有字段都有默认值,最小配置只需要 bots: yaml
- id: qq-bot
name: dsh-qq-bot
config:
repoDir: "" # 留空 = ~/dsh-qq-bot(首次启动自动创建) autoStart: true bots:
- qq: "3177752843"
name: 千早爱音 persona: Anonther
admins: ["3635811460"]
yaml
ws: { url: "ws://127.0.0.1:3001", accessToken: "" }

provider: guijiliudong # 可选:缺省用 DSH 默认模型

model: deepseek-ai/DeepSeek-V4.1-Flash

timeout: 180
tools: { webSearch: false, webFetch: false } # 聊天档工具白名单
access: # 每个功能单独设;features 里的 mode=inherit 跟随默认 mode: admin
users: []
groups: []
denyUsers: []
denyGroups: []
features:
sticker: { mode: inherit }
search: { mode: inherit }
manage: { mode: inherit }
rules: [] # 关键词规则
schedules: [] # 定时消息
service:
onebotDir: "" # 留空 = <repoDir>/onebot/napcat-docker webuiPort: 6099 wsPort: 3001 chat: maxReplyLength: 800 # 作用在展开表情之前 replyCooldown: 5 leaveCooldown: 300 logMaxEntries: 300
blacklistGroups: []
aggregation:
windowTimeout: 8
maxMessages: 8
rateLimit:
tier1Count: 3 # 1 分钟 ≥4 条 → 冷却 ×1.5 tier2Count: 10 # 5 分钟 ≥11 条 → 冷却 ×2 capCount: 15 # 10 分钟 ≥16 条 → 停止回复

provider/model 缺省时使用 DSH 全局默认模型;指定时使用该 provider(须已在 DSH 设置里配好)。

十五、界面背后的接口

界面按钮打到 Harness 自带 web 服务器的两个前缀(不额外开端口):

- /qqbot-service/:status、doctor(环境自检)、init(初始化目录)、action(start/stop/restart)
- /qqbot-files/:list、persona/{load,save,create,delete,rename}、sticker/{upload,category,delete}、memory/{list,read,save,delete}、chats、chat/tail、open、clean
- /qqbot-status:状态灯数据(连接/计数/工具策略/搜索可用性)
- /qqbot-inspect:巡检事件
- /qqbot-runtime/{search,ai}:运行时开关(不改配置文件,重载后回到配置值)
- /qqbot-runtime/models:POST {baseURL, apiKey|apiKeyEnv} → 上游模型 id 列表(界面「拉取模型」)

十六、运行日志

qq-bot: 仓库目录 /Users/you/dsh-qq-bot,数据目录 /Users/you/dsh-qq-bot/data qq-bot: 初始化工作区,创建 12 项 qq-bot: 正在连接 ws://127.0.0.1:3001 ... qq-bot: ✅ 已连接 qq-bot: 启动监测 [千早爱音] [chat=group-42] qq-bot: 🤖 [千早爱音] 上下文 5行, 2图 qq-bot: 📤 [千早爱音] 分段回复 (2段)

十七、开发 bash
node --check lib/.js # 语法检查
npm run check # 同上(含 client.js)
npm pack # 打 tarball 给别人装

| 文件 | 作用 |
| lib/index.js | 插件入口、Config schema、装配 worker |
| lib/onebot.js | OneBot v11 WS 客户端 |
| lib/hub.js | 消息分发、指令、聚合 |
| lib/bot.js | 单个机器人运行时(触发判断、限频、发送) |
| lib/brain.js | 与 Harness agent 的桥接、会话压缩 |
| lib/chatlog.js | data/.json 聊天日志(与原版兼容) |
| lib/cq.js | CQ 码解析、表情包、@、分段 |
| lib/files.js | 人格/表情包/目录管理路由 |
| lib/service.js | Docker/NapCat 启停与自检 |
| lib/scaffold.js | 工作区初始化(目录 + compose 模板) |
| lib/platform.js | 平台差异(打开目录、compose 探测、虚拟机信息) |
| lib/client.js | 界面(设置分区 + 插件页配置入口) |

十八、已知行为差异(相对原 Python 版)

1. 命令必须空格分隔:@bot /ping 生效,@bot/ping 不生效。
2. data/.json 里图片以 liveImages(base64)内联保存,不再落 data/images/。
3. compact 后的记忆总结不再自动生成;已有 memory-<chat>.json 会继续注入种子文本。
4. 一个 (bot, 聊天) 的会话在插件进程存活期间复用;DSH 重启后首轮用聊天日志窗口整体重建。

十九、排障:插件「消失」与 404

| 现象 | 原因 | 处理 |
| 设置侧栏没有「QQ 机器人」、插件页也无此项 | Host 侧 apply()/import 失败(最常见:软链安装缺依赖) | 看启动日志的 failed to import;v1.2.2 起软链安装已自动回退内置 WebSocket |
| 界面卡片在,接口 404(/qqbot-status 等) | 页面刷新只换前端,Host 还是旧进程 | 完全退出并重启 Harness,不是刷新页面 |
| 状态灯红、lastError 有内容 | NapCat 没起来 / 端口不对 / token 不对 | 用「服务」卡片启动,或 docker logs napcat |
| 搜索报 401 | 聊天模型不是 DeepSeek 账号模型,搜索仍需 DeepSeek 凭据 | 「设置 → 插件 → 官方 → 网页搜索」填 Key |
| 群里出现 <invoke> / <parameter> 之类的文本 | 搜索开着但智能体没拿到 web_search,模型自己编了调用语法 | 1.3.2 起会自动过滤并丢弃纯语法回复;看 /qqbot-status 的 toolsAvailable.webSearch 排查 |

致谢

| 项目 | 说明 |
| ezoiLZH/QQ-bot | 原项目(Python + Claude Code CLI)。本插件的人设系统、表情包协议、消息聚合、冷却与指令都移植自它 |
| NapCatQQ | 本插件默认使用的 OneBot v11 实现(Docker 镜像 mlikiowa/napcat-docker) |
| LLOneBot | 另一种 OneBot v11 实现,同样可用 |
| DeepSeek Harness | 宿主:智能体会话、模型路由、系统提示词、插件槽位 |

出处引用:本项目基于 QQ-bot(作者 ezoiLZH)改写,经原作者许可发布;转载、二次分发请保留本段署名与链接。

原项目没有附带开源许可证,所以本移植版不对原项目的代码与设计主张任何权利;新增的插件封装、界面与跨平台适配代码以 MIT 发布(见 LICENSE 与 NOTICE)。

MIT License.
预览分享卡片长什么样 ↓wufa-cat/dsh-qq-bot
分享 · DeepSeek Harness Hub
wufa-cat/dsh-qq-bot

把 QQ 群聊和私聊接入模型,自动收发消息

这是你的仓库?认领条目

回到顶部