把 QQ 机器人接入 DeepSeek Harness:私聊或群聊里 @bot 即可对话、传文件、调用工具,扫码绑定 QQ 凭据,按消息派生独立会话。
- 语言
- TypeScript
- License
- MIT
- 分支
- main
安装
$ dsh plugin --profile web add github:tencent-connect/dsh-qqbot在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程
对话式安装
帮我安装 DeepSeek Harness 插件 tencent-connect/dsh-qqbot:先查看仓库 https://github.com/tencent-connect/dsh-qqbot.git 确认安全性,然后执行安装命令并验证插件加载成功。
把这段指令粘贴给 DSH Web GUI 里的助手,由它代你完成安装与验证。
一句话定位
dsh-qqbot 把 QQ 机器人接到 DeepSeek Harness:把 QQ 消息平台变成 dsh agent 的前端通道,私聊或群聊里 @机器人就能对话、发文件、调用 agent 工具;首次启动扫码绑定 QQ 凭据,每个聊天窗口各自持有独立会话。
核心能力
- 私聊与群聊对话:私聊始终响应;群聊默认只在 @bot 时触发,可关掉门控让它响应所有消息
- 扫码绑定 QQ 凭据:首次启动终端打印二维码,手机 QQ 扫一下即可拿到 AppID/AppSecret 并自动写入 profile
- 附件处理:图片自动带尺寸描述,语音转写为文本,文件附件下载到本地后通过路径提示模型自行读取
- Markdown 流式回复:私聊默认逐段推送(streaming),群聊因 QQ 协议限制整段发送;超长回复会按代码块/表格感知切分
- 独立会话:每个 QQ 用户/群对应一个 dsh agent,会话按 SHA-256 派生的 sessionId 持久化,重启后能恢复
- 内置斜杠命令 + 访问控制:
/new/compact/model/stop以及/bot-ping/bot-version/bot-status/bot-help,并支持按 openid / groupOpenid 白名单放行或禁用私聊与群聊
技术实现
- 语言: TypeScript(ESM,
tsconfig编译到dist/,main指向dist/index.js) - 关键依赖:
@tencent-connect/qqbot-nodejs(QQ OpenAPI + WebSocket 客户端 + 中间件链)、@tencent-connect/qqbot-connector(扫码绑定)、js-yaml(cordis.patch.yml 读写) - 架构模式: 纯 Cordis 插件,
inject = ['agents'];入口apply()跑完凭据引导后调用bootstrapGateway()组装 SDK 中间件链(错误处理→过滤→访问控制→群历史缓冲→@门控→清洗→限流→斜杠命令→并发串行→输入状态→引用→附件→envelope),并通过ctx.on('session/event', ...)把 dsh 出站事件路由回 QQ - 入口文件:
src/index.ts(Cordis 插件入口,含凭据引导);网关装配见src/gateway/bootstrap.ts
适用场景
适合想用 QQ 跟 DeepSeek Harness 交互的用户:日常在 QQ 里问问题、让 agent 帮忙读文件、写代码、跑命令,省去打开 web 控制台的步骤。QQ 群组里也能作为团队助理出现,每个人的对话上下文彼此隔离,30 分钟没说话自动释放资源。
前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DeepSeek Harness | 0.1.0-rc.6+ | peerDependencies 锁 @deepseek-ai/dsh-agent / dsh-llm / dsh-session / cordis / schemastery 全部为 0.1.0-rc.6 / 4.0.1 / 3.18.1 以上 |
| QQ 机器人凭据 | — | 必须有 AppID + AppSecret,可走扫码自动获取,也可通过 QQBOT_APPID / QQBOT_SECRET 环境变量手工注入 |
| Node.js | 未声明 | package.json 没有 engines 字段;devDependencies 含 @types/node ^26.2.0,实际运行需要支持 Node 18+ 内置的 fetch、AbortSignal.timeout、node:dns/promises 等 API |
| 平台 | macOS / Windows / Linux | 扫码引导在 Windows 下会自动切到 set 语法(src/setup.ts:186),其他平台走 export;其它代码无平台相关分支 |
| 原生模块 | 无 | 仅依赖 node:crypto / node:fs / node:path / node:dns 等内置模块,不引入 node-pty / sqlite 等原生绑定 |
安装方式
dsh plugin --profile web add github:tencent-connect/dsh-qqbot
配置项
插件通过 Schemastery Schema(src/config.ts:56)声明字段,下表里"说明"列写人话。安装后默认值已能跑通普通场景,普通用户无需调整。
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
appId | 字符串 | QQ 机器人 AppID;留空时启动会进入扫码引导 | 空(需扫码或设环境变量) |
appSecret | 字符串 | QQ 机器人 AppSecret;同上 | 空 |
provider | 字符串 | 默认 LLM 提供商;留空时继承宿主配置 | 继承 |
model | 字符串 | 默认模型;留空时继承宿主配置 | 继承 |
preset | 字符串 | 关联的 agent preset id(工具集、prompt 等) | 无 |
cwd | 字符串 | agent 执行命令的根目录 | 进程当前目录 |
requireMention | 布尔 | 群聊是否要求 @bot 才回复 | true |
groupPrompt | 字符串 | 群聊额外注入到 system prompt 的内容 | 无 |
directPrompt | 字符串 | 私聊额外注入到 system prompt 的内容 | 无 |
textChunkLimit | 数字 | 单条 QQ 消息最大字符数(QQ 上限约 5000) | 4500 |
streaming | 布尔 | 私聊是否启用流式回复(群聊始终不启用) | true |
sessionIdleTimeout | 数字 | 会话闲置多少毫秒后自动回收 | 1800000(30 分钟) |
maxQueue | 数字 | 同一会话最多排队多少条消息 | 20 |
processingTimeoutMs | 数字 | 单轮 LLM 调用超过多少毫秒自动中断 | 120000(2 分钟) |
historyLimit | 数字 | 群聊回复时回带最近多少条消息作为上下文 | 10 |
access.c2cMode | 字符串 | 私聊访问模式:open 全部放行 / allowlist 白名单 / disabled 全部拒绝 | open |
access.c2cAllow | 字符串数组 | 私聊白名单(填 user openid) | [] |
access.groupMode | 字符串 | 群聊访问模式(取值同上) | open |
access.groupAllow | 字符串数组 | 群聊白名单(填 group openid) | [] |
showToolResults | 布尔 | 是否把工具调用的成功结果展示出来(错误始终展示) | false |
debug | 布尔 | 开启调试日志(包含中间件命中详情) | false |
常见问题
Q: 第一次启动需要做什么?
A: 启动时如果没检测到 AppID/AppSecret,插件会在终端打印二维码,扫码完成绑定;凭据会自动写入当前 profile 的 cordis.patch.yml,下次启动无需再扫。二维码错位时可用 0.4.0+ 版本输出的浏览器链接替代。
Q: 群聊里必须 @bot 才会回复吗?
A: 默认开启 requireMention,群聊只在 @bot 时触发回复;设为 false 后任何消息都会触发。私聊不受此开关影响,始终响应。
Q: 一个 QQ 群里的对话上下文会串到另一个群吗?
A: 不会。每个 QQ 私聊用户和每个 QQ 群都有独立的 sessionKey,sessionId 由 qqbot:${appId}:${scope}:${peerId} 经 SHA-256 确定性派生,重启后可恢复;但不同群/不同人之间的对话是隔离的。
Q: 支持图片、语音、文件吗?
A: 图片会带尺寸描述写入上下文;语音优先使用 ASR 转写后的文字,模型拿不到音频时附原始链接兜底;文件附件会自动下载到 ${cwd}/.qqbot/${messageId}/ 下并提示路径,模型再通过工具读取。文件下载做了 HTTPS + SSRF 防护与 20MB 大小限制。
Q: 流式回复怎么开?
A: 私聊默认开启流式(streaming: true),回复会逐段推送;群聊始终不启用流式,因为 QQ 群消息接口限制只能发整段 Markdown。如果关闭全局流式,私聊也会改为一次性发送完整回复。
Q: 想切模型怎么操作?
A: 在聊天里直接发 /model 会列出当前可用模型(点击切换),或 /model provider/model 指定具体路由。偏好会按 sessionKey 持久化到 ~/.dsh-qqbot/model-prefs.json,同一个人/群下次启动仍然生效。
Q: 怎么彻底重置当前对话?
A: 发 /new(别名 /reset、/clear)会丢弃当前会话并开新会话;要保留上下文但压缩历史可发 /compact(需要 host 装了 compaction 服务)。长会话闲置超过 30 分钟会被自动回收,下次消息到来时再恢复。
Q: 报 "凭据未配置" 怎么办?
A: 走扫码会自动写入 profile;如果是开发模式(用 cordis.dev.yml 加载源码),无法定位 profile 目录,插件会在终端打印 export/set 环境变量的指引。手工配置时把 appId 与 appSecret 写到 profile 的 cordis.patch.yml 对应插件条目下即可。
上手难度
入门 — 扫码即可绑定 QQ 凭据,私聊直接开聊;进阶用户可按需调整群门控、白名单、Markdown 切分阈值等参数。
已知问题与限制
- 模型偏好按 sessionKey 持久化在
~/.dsh-qqbot/model-prefs.json,删除该文件可重置全部偏好;当前未提供 UI 化的批量清理入口 - 群聊 streaming 始终关闭:QQ 群消息接口不支持增量更新,因此群聊只能整段发送 Markdown,单条上限受
textChunkLimit(默认 4500)控制 - 文件附件下载带 20MB 大小限制与 HTTPS + SSRF 防护,命中任一规则时会跳过下载,仅保留路径描述;过大文件需要用户手工放到 agent 工作目录
- 会话闲置 30 分钟后自动 dispose,下次消息触发"resume → create"流程;如果 host 缺少
sessions服务,resume 会失败并退化为创建全新会话(历史丢失) - 切换模型走 fork + 重建策略,底层若没有
sessions.fork服务,会回退为 dispose 旧会话、用新模型创建新会话(与/new等价,会丢失上下文) /compact命令依赖 host 装载了agent-presets或compaction服务;未装载时返回"压缩能力不可用"- 流式回复下
assistant/chunk与assistant/message都会进入 buffer;中途turn/end异常结束时若STREAM_CLOSED等底层错误码会被静默忽略(不出现在用户消息里)
基于 deepseek-harness (dsh) 的 QQ Bot IM 插件,将 QQ 消息平台作为 dsh agent 的前端协议驱动。
中文 | English
架构
QQ 用户 → QQ WebSocket → dsh-im-qqbot → ctx.agents → dsh agent loop → LLM
↑ │
└── session/event ──────────┘
(assistant reply → QQ sendMarkdown)
安装
方式一:手动执行
# 安装到 profile
npx @deepseek-ai/dsh plugin --profile qqbot add @tencent-connect/dsh-qqbot
# 启动
npx @deepseek-ai/dsh --profile qqbot
首次启动时,插件检测到凭据未配置会自动进入扫码引导:终端输出二维码 → 手机 QQ 扫码绑定 → 凭据自动保存到 profile,后续启动无需再次扫码。
提示:建议升级至
0.4.0以上版本扫码,支持点击链接在浏览器打开,避免部分终端二维码渲染错位的问题。
方式二:本地路径安装
# 构建
cd /path/to/dsh-qqbot
pnpm install && pnpm build
# 安装到 profile(本地路径)
npx @deepseek-ai/dsh plugin --profile qqbot add /path/to/dsh-qqbot
# 启动
export QQBOT_APPID="你的AppID" QQBOT_SECRET="你的AppSecret"
npx @deepseek-ai/dsh --profile qqbot
方式三:--patch 开发模式
export QQBOT_APPID="你的AppID" QQBOT_SECRET="你的AppSecret"
npx @deepseek-ai/dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml
配置项
| 配置 | 类型 | 默认值 | 说明 |
|---|---|---|---|
appId | string | 必填 | QQ Bot AppID(或通过 QQBOT_APPID 环境变量) |
appSecret | string | 必填 | QQ Bot AppSecret(或通过 QQBOT_SECRET 环境变量) |
provider | string | deepseek-official | LLM 提供商名称 |
model | string | deepseek-chat | 模型名称 |
preset | string | - | Agent preset id |
cwd | string | process.cwd() | Agent 工作目录 |
requireMention | boolean | true | 群聊是否需要 @bot 才触发 |
groupPrompt | string | - | 群聊额外 system prompt |
directPrompt | string | - | 私聊额外 system prompt |
textChunkLimit | number | 4500 | 单条消息最大字符数 |
sessionIdleTimeout | number | 1800000 | 会话闲置超时(ms),默认 30 分钟 |
debug | boolean | false | 调试模式 |
内置命令
| 命令 | 说明 |
|---|---|
/new(别名 /reset /clear) | 开始新会话(清空上下文) |
/compact | 压缩会话历史(摘要替换旧记录,保留上下文) |
/model | 查看或切换模型 |
/stop | 中止当前生成 |
/bot-ping | 连通性测试 |
/bot-version | 查看版本信息 |
/bot-status | 查看当前会话状态 |
/bot-help | 查看所有指令 |
核心模块
src/
├── index.ts # Cordis 插件入口(async apply)
├── config.ts # 配置 Schema
├── types.ts # 全局类型定义
├── setup.ts # 凭据绑定(扫码)
├── transport/ # 传输层
│ ├── inbound.ts # QQ 入站消息 → agent.followup()
│ ├── outbound.ts # session/event → QQ sendMarkdown
│ ├── outbound-buffer.ts # 流式缓冲
│ └── chunker.ts # Markdown 文本切分
├── session/ # 会话管理层
│ ├── session-manager.ts # QQ peer → Agent 映射
│ └── idle-evictor.ts # 闲置回收
├── model/ # 模型路由层
│ ├── model-resolver.ts # 路由解析
│ ├── prefs-store.ts # per-peer 偏好持久化
│ └── settings-reader.ts # settings.yaml 只读
├── shared/ # 共享工具
│ ├── utils.ts # 通用函数
│ ├── scope.ts # scope/peer 提取
│ └── send-helper.ts # 分块发送
├── commands/ # 斜杠命令
└── typings/ # 外部模块声明
会话路由
sessionKey: qqbot:${appId}:${scope}:${peerId},由 SHA-256 确定性派生 SessionId,重启后可恢复。
解析策略:进程内复用 → 持久化恢复 → 全新创建。
设计原则
- 纯 Cordis 插件 — 遵循 dsh "Plugins, not loop changes" 原则
- 声明式依赖 —
inject = ['agents'],不直接耦合其他插件 - 会话隔离 — 每个 QQ 私聊用户/群聊各一个独立 Agent
- Preset 支持 — 可通过
agent-presets服务挂载预设(工具集、prompt 等) - 闲置回收 — 超时自动 dispose Agent,防止内存泄漏
- Markdown 输出 — 回复以 Markdown 格式发送,支持代码块/表格感知切分
本地开发
# 安装依赖
pnpm install
# 构建
pnpm build
# 开发模式(watch)
pnpm dev
# 用 --patch 方式调试
export QQBOT_APPID="xxx" QQBOT_SECRET="xxx"
npx @deepseek-ai/dsh web --patch /path/to/dsh-qqbot/cordis.dev.yml
License
收录徽章
[](https://deepseek-plugin.org/plugins/tencent-connect/dsh-qqbot)把这段 markdown 粘贴到你的 GitHub README,链接回本插件详情页。徽章只声明已被本站收录,不代表安全认证。