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

QQ 远程遥控 xcisxc29/dsh-qq-plugin

DeepSeek Harnessv1.0.5
xcisxc2913 天前有提交已提供中文文档扫描:含敏感能力

在 QQ 里用手机指挥这台电脑上的 DeepSeek Harness agent。

46.3/100
综合分
35
GitHub 星标
1,807
npm 周下载
—/5
用户评分

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-qq-plugin
npm 源 · dsh-qq-plugin 的发布者账号已校验与本仓库一致

状态速览

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

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-qq-plugin @ 1.0.5
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/28 02:49:09

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

读写/删除本地文件发起外部网络请求
查看扫描证据(共 27 处,展示前 27 条)
  • 发起网络请求
    client.js:148
    void fetch(`${PREFIX}/client-error`, {
  • 发起网络请求
    client.js:507
    const response = await fetch(path, {
  • 写入本地文件
    lib/log.js:46
    mkdirSync(dirname(logFile), { recursive: true })
  • 写入本地文件
    lib/log.js:70
    appendFileSync(logFile, line)
  • 读取本地文件
    lib/log.js:79
    if (statSync(logFile).size <= MAX_LOG_BYTES) return
  • 写入本地文件
    lib/log.js:84
    renameSync(logFile, `${logFile}.1`)
  • 写入本地文件
    lib/paths.js:73
    mkdirSync(workspace, { recursive: true })
  • 写入本地文件
    lib/paths.js:88
    mkdirSync(join(home, WORKSPACE_DIR_NAME), { recursive: true })
  • 写入本地文件
    lib/paths.js:171
    mkdirSync(dir, { recursive: true })
  • 写入本地文件
    lib/paths.js:173
    writeFileSync(probe, 'ok', 'utf8')
  • 删除本地文件
    lib/paths.js:174
    rmSync(probe, { force: true })
  • 写入本地文件
    lib/runtime.js:1894
    writeFileSync(path, plan.text, 'utf8')
  • 读取本地文件
    lib/runtime.js:2767
    if (!existsSync(entry.path)) {
  • 读取本地文件
    lib/runtime.js:2809
    info = statSync(path)
  • 读取本地文件
    lib/routes.js:225
    const text = readFileSync(logPath(), 'utf8')
  • 写入本地文件
    lib/media.js:73
    mkdirSync(dir, { recursive: true })
  • 发起网络请求
    lib/media.js:174
    const response = await fetch(url, { signal: AbortSignal.timeout(30_000) })
  • 写入本地文件
    lib/media.js:190
    writeFileSync(path, data)
  • 读取本地文件
    lib/session-index.js:122
    const raw = await readFile(join(storeDir, name), 'utf-8')
  • 读取本地文件
    lib/session-index.js:174
    const entries = await readdir(root, { withFileTypes: true })
  • 读取本地文件
    lib/session-index.js:281
    await stat(join(indexDir, name))
  • 读取本地文件
    lib/session-index.js:291
    const entries = await readdir(join(home, 'sessions', folder), { withFileTypes: true })
  • 读取本地文件
    lib/state.js:276
    text = await readFile(this.#file, 'utf8')
  • 写入本地文件
    lib/state.js:291
    renameSync(this.#file, `${this.#file}.corrupt`)
  • 写入本地文件
    lib/state.js:339
    mkdirSync(dirname(this.#file), { recursive: true })
  • 写入本地文件
    lib/state.js:346
    writeFileSync(temp, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 })
  • 删除本地文件
    lib/state.js:374
    unlinkSync(temp)
扫描于 2026/11/2(1 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

6 张 · 点击查看大图

README

由 DeepSeek 最新模型翻译生成
dsh-qq-plugin 在 QQ 里用手机指挥这台电脑上的 DeepSeek Harness agent。 走腾讯官方 QQ 机器人通道(api.bot.qq.com,扫码绑定),不需要公网 IP、不需要反向代理、中间也没有第三方协议客户端。绑定一次,之后一直有效。 能在当前的 DSH 桌面端上跑 —— 针对 DSH 0.2.0-rc.2 开发和实测。 这是 dsh-wechat-plugin 的 QQ 版本,功能与它对齐;有几处有意不同,因为 QQ 协议本来就不需要微信那套机器(见与微信版的差异)。 一句话要一个文件,它就出现在手机上:在 QQ 里说「把我电脑上桌面那张 DSH 自画像发过来」, agent 在电脑上找到那个文件、发回来,并在下面回一句「已发送 ✅ 桌面上的「DSH 自画像.png」(29 KB,PNG)」。 输入框右边那个 + 是附件入口——图片、视频、语音、文件都从那里发进去(见媒体双向)。 功能 - 文字双向:QQ 消息变成 DSH 提示词,回复发回 QQ。 - 图片、文件、语音进来,图片、视频、文件出去:收到的附件落盘到会话工作区并交给 agent; agent 用 send_to_qq 把本机文件发回来。超长回复自动转成 .md 文件发回手机。
展开完整文档(README 剩余 1 节)
dsh-qq-plugin

在 QQ 里用手机指挥这台电脑上的 DeepSeek Harness agent。

走腾讯官方 QQ 机器人通道(api.bot.qq.com,扫码绑定),不需要公网 IP、不需要反向代理、中间也没有第三方协议客户端。绑定一次,之后一直有效。

能在当前的 DSH 桌面端上跑 —— 针对 DSH 0.2.0-rc.2 开发和实测。

这是 dsh-wechat-plugin 的 QQ 版本,功能与它对齐;有几处有意不同,因为 QQ 协议本来就不需要微信那套机器(见与微信版的差异)。

一句话要一个文件,它就出现在手机上:在 QQ 里说「把我电脑上桌面那张 DSH 自画像发过来」, agent 在电脑上找到那个文件、发回来,并在下面回一句「已发送 ✅ 桌面上的「DSH 自画像.png」(29 KB,PNG)」。
输入框右边那个 + 是附件入口——图片、视频、语音、文件都从那里发进去(见媒体双向)。

功能

- 文字双向:QQ 消息变成 DSH 提示词,回复发回 QQ。
- 图片、文件、语音进来,图片、视频、文件出去:收到的附件落盘到会话工作区并交给 agent; agent 用 send_to_qq 把本机文件发回来。超长回复自动转成 .md 文件发回手机。
- 一个 QQ 对话,多个 DSH 会话:/new、/list、/switch、/current、/cancel,或者直接说「换个对话」。列表分会话夹与会话两层。
- 模型与推理等级也能在手机上换:/model 列出模型和各自的推理等级, /model 2、/model 等级 high 直接切换,对下一步生效。
- 在手机上回答权限与提问:权限审批回「允许」/「拒绝」(或数字选项), agent 的二选一/多选提问带编号发到 QQ,回个数字就行——离开电脑时回合不会再卡住。
- 主动推送:notify_qq 让这台机器上的任意会话都能给你发消息,这正是「干完了告诉我」的实现。实测可用:连发十条消息全部送达,其中后六条走的就是主动推送。
(腾讯对主动推送的规则会变,插件不假设额度;任何原因没送达都会进队列,等你下次说话时先补发。)
- 定时任务:用 DSH 宿主自带的 schedule_create / schedule_list / schedule_delete / schedule_update,说「23:12 叫我」就行。插件不重复实现 DSH 已有的能力,只做通道。
- 设置页:设置 → QQ,九个设置项、带原生文件夹选择器、带诊断区。

安装

给 DSH 桌面端用的,装在一台一直开着的机器上。它需要 DSH 的工作区、工具与 UI 服务——也就是标准的桌面端组合。

| DSH 桌面端 | @deepseek-ai/dsh-desktop 0.2.0-rc.2 或更高 |
| 手机 | 能装手机 QQ,用来扫一次二维码 |
| QQ 机器人 | 不需要事先注册。机器人应用是那次扫码当场创建的,不必提前准备 AppID/AppSecret |
| 腾讯的规则 | 未认证的机器人仅管理员可用——也就是只有你自己能用,这正是「私人遥控器」要的 |

打开侧边栏的 plugin 入口,选 添加插件。输入框接受包名、Git 地址、tarball 或本地路径。

要装的这个名字是 dsh-qq-plugin

仓库与包同名,没有需要对上的东西——但 -plugin 这个后缀很容易漏掉。
把 dsh-qq-plugin 复制过去,别手打。 安装命令必须与包名逐字一致。

在终端里就是一行(你用的 profile 是 web 就把 --profile desktop 换成 --profile web):

dsh plugin --profile desktop add dsh-qq-plugin

从 npm 装 —— 不用配置任何东西

dsh-qq-plugin

需要指定版本就写 dsh-qq-plugin@1.0.5。

从本地目录装 —— 没有构建步骤要等

C:\path\to\dsh-qq

指到放着 package.json 的那个目录:文件夹叫 dsh-qq,它声明的包名是 dsh-qq-plugin。

从 tarball 装

npm pack
→ dsh-qq-plugin-1.0.5.tgz

把那个 .tgz 的绝对路径粘进 添加插件。

改用命令行安装

界面底下驱动的就是 pnpm,所以同样的事也能在终端里做:

dsh plugin --profile desktop add dsh-qq-plugin
dsh plugin --profile desktop add C:\path\to\dsh-qq

然后得自己启用这个 bundle——也就是 立即启用 替你做的事——改 ~/.dsh/profiles/desktop/package.json:

{
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-qq-plugin"
]
}
}
}

等安装结束,点 立即启用,重启 DSH。

开始使用

重启 DSH 后打开 设置 → QQ,点 开始扫码。用手机 QQ 扫二维码并在手机上确认。

扫码这一步不用先去腾讯开放平台注册。 机器人应用是那次扫码当场创建的, 不需要事先准备 AppID/AppSecret,也不需要公网 IP 或反向代理。

凭据直接写进 DSH 的凭据存储——插件自己的状态文件里只有 AppID,没有 AppSecret。
绑定后通道会自动连接:在 QQ 里给机器人发消息即可开始对话。

上面这张是装上之后真正在用的样子:agent 在电脑上整理好一份 13 首的《秋日诗歌选》,把 docx 和 pdf 两个文件直接发到手机上;同一条对话里问一句「告诉我,我现在电脑时间」,它答 2026-10-13 22:43:28 星期二,还顺手问要不要设个提醒。

这一刻电脑是锁屏的——手机上的时间是 22:43,锁屏界面上的时间也是 22:43:

锁屏不会让 agent 停下来,所以你走开之后它还在干活,而手机上的对话照常推进。
反过来也一样成立:锁屏也正是你离开时该做的事(见安全)。

使用

直接发消息就会到达 agent:

你好

下面按能力分块,每块都配一张真机截图说明它长什么样、在证明什么。

会话管理(手机上)

一个 QQ 对话,背后是任意多个 DSH 会话。/list 打开本工作区的会话,每屏 10 条:

这张图一次证明四件事:一屏 10 条、每行末尾一个 6 位短 id(7cee80、4b55e1…)、 当前会话标着「← 当前」、以及底部那句提示。列表还会告诉你其它会话夹里还有 89 个对话。

/list all 是上面那一层——会话夹(跨项目/工作区),每个夹子带会话数;回编号或名字就进入,进去之后看到的还是会话列表(图里回的是 1,于是进了「QQ 会话」):

进会话夹只改浏览位置,不改绑定——真要切过去,还要在里面再选一个会话。

裸数字就是 /switch <数字>:列表就在眼前时不用打 /switch,直接回 2 就行,而且它会告诉你切到了哪个(连短 id 一起回,你能对上是不是那一行):

★ 引用冻结编号:长按引用那条列表消息再回数字,就按你引用的那一屏解析。
列表在这期间变了也不会切错会话——编号冻结在那条消息里。列表底部自己就这么提示:「引用这条消息再回编号,可以避免编号过期。」

大白话也行。 下面这张是发「查看所有会话」(不是指令):

agent 判的是意图而不是匹配固定规则:它认出了这是「列会话」,于是列出了会话夹,还告诉你下一步可以回编号、也可以回「查看其余」。切换成功或失败它也都会说。

用这些指令控制你在和哪个 DSH 会话说话:

| 指令 | 作用 |
| /new [标题] | 新建对话。后面跟的文字就是标题:/new 修复登录 会开一个叫「修复登录」的对话 |
| /list | 直接进 QQ 工作区那一层(每屏最多 10 条) |
| /list all | 列出本机的会话夹(工作区),每个一行、带会话数;回复编号或名字进入 |
| /switch 3 | 切到那一屏的第 3 个 |
| /switch e716f0 | 按行尾那个短 id 切——跟编号无关,永远不会过期 |
| 回复「查看其余」 | 往下翻十条(两层都能用,一直翻到底)。编号跨屏连续(1–10,然后 11–20) |
| 直接回 3、名字或行尾 id | 列表就在眼前时不用打 /switch |
| 引用列表消息 → /switch 3 | 按那一屏的编号切,编号冻结在那条消息里 |
| /model | 看有哪些模型,以及每个模型的推理等级,标出当前用的那个 |
| /model 2 | 切到列表里的第 2 个,也可以直接发模型名字 |
| /model 等级 high | 换当前模型的推理等级(等级名字就是列表里印的那些) |
| /model 2 等级 high | 换模型的同时指定等级 |
| /current | 显示当前在哪个对话 |
| /cancel | 中断正在跑的任务 |
| /help | 显示这份列表 |

空格是可选的:/switch3、/switch 3、/switch:3 意思相同——这些指令是在手机键盘上敲的,掉空格是常态。只是以指令名开头的词不算指令,所以 /news 不是 /new。

编号会过期:会话在你读列表时还在跑,等你回「3」时第 3 行可能已经换人了。所以每行末尾都带一个 最多 6 个字符的短 id,直接回它或 /switch 都收;或者引用那一屏的列表消息再回编号,编号就按那条消息印的算。

列表分两层,每屏 10 条:/list 直接进本工作区的会话;/list all 列出会话夹(工作区),回编号或名字进入。两层都用「查看其余」往下翻十条,编号跨屏连续(1–10,然后 11–20),翻到底会明说而不是继续邀请你翻。进会话夹只改浏览位置,不改绑定——真要切过去,还要在里面再选一个会话。

模型与推理等级

/model 列出有哪些模型(带「(当前)」「(默认)」标记)以及每个模型的推理等级。
/model <名字|编号> 切模型;/model 等级 high 只改推理等级;/model 2 等级 high 一起改。
切换对下一步生效。

推理等级的取值来自宿主适配器,本机自带的 DeepSeek 适配器发布的是 off / low / high / max (清单里印成 Off / Low / High / Max)。/model 等级 后面写的就是这些名字,大小写不敏感;中文的「高」「低」不在取值里——等级名字就是列表里印的那些。

也可以直接用大白话说,例如「换个对话」「我有哪些对话」「停下」。agent 判的是意图而不是匹配固定规则,而且切换会告诉你成功还是失败。

媒体双向:图片、视频、语音、文件

收:手机发图片 / 视频 / 语音 / 文件给 agent。语音用服务端转写,你无感。
Word、Excel 这类文档附件也能读。

下面是发一张狗的照片过去、只问一句「这是什么」:

图里值得注意的不是它认出了狗,而是那两处只有真看过图才知道的细节:黄身橙嘴的鸭子玩具、画面左边人的腿,以及它主动指出照片被横过来了(拍照时手机拿反了)。

发一份 PDF 过去、同样只问一句「这是什么」:

文档类附件也能读:它说出了这是一份 5 页的招新任务文档、由 MarkText 导出,并按「第一部分 环境配置 / 第二部分 用 AI+工程规范 / 第三部分 传统视觉 OpenCV」把内容概括了一遍。

发:agent 用 send_to_qq 把电脑上的文件发到手机——图片显示成图、视频显示成可播放的片段、其它变文件附件:

这就是本页顶部那张封面图在讲的事,也是一次完整的取件:说清楚要哪个文件,它在电脑上找到、发回来,并且回一句带文件名与大小的确认,你一眼能看出发的是不是你要的那个。

★ 超长回复会自动转成 .md 文件发回手机(默认上限 4000 字,可调;0 = 不限制):

手机上一屏读不完的东西,转成文件比刷长消息好用得多——不截断,也不拆成十几条刷屏。
阈值就是设置页里的「单条回复字数上限」。

语音:手机按住说话,agent 收到的是文字(服务端转写,不需要你多做什么):

图里那条 3 秒的语音气泡下面,直接就是一份完整的天气回答——中间那一步(把语音变成文字)你在手机上完全看不到,也不需要看到。

交互

这三件事没有配图——它们是同一条对话里的一问一答,截出来的图跟上面那些几乎一样,所以用文字说清楚更好。它们在手机上收到的是这样:

- 权限审批:agent 要动你的文件时,QQ 里会出现一条待批准的请求,带上它打算做什么。
你回 「允许」、「拒绝」,或者回数字选项都算回答;答完任务接着跑。
(想让这种提示真的出现,权限预设得是能弹提示的那两个——见设置。)
- 二选一/多选提问:agent 的提问会带编号选项发过来,回个数字就行。
- 引用当上下文:长按引用它的某条回答再说话,例如「这条里的第二点展开说」,它知道「这条」是哪一条,也知道「第二点」指哪个。

主动性:干完了告诉你

★★ notify_qq:这台机器上任意会话都能主动推消息给你——「干完了告诉我」就是靠它。
下面左边是桌面端在干这个活儿的会话,右边是手机 QQ上收到的结果:

注意两边不是同一个会话:干活的是桌面端那个会话,收消息的是你绑定的 QQ 对话。
这正是 allowCrossSessionNotify 默认开着的原因——不放开这一条,干活的会话就报不了自己的结果。

实测可用:实测连发十条消息全部送达,其中后六条走的正是主动推送。
(腾讯对主动推送的规则会变,插件不假设额度;任何原因没送达都会进队列,等你下次说话时先补发。)

定时任务走的是 DSH 宿主自带的 schedule_create / schedule_list / schedule_delete / schedule_update——插件不重复实现 DSH 已有的能力,只做通道。说人话就行:

到点它真的会推一条过来(这是主动推送,不是你在问它):

「每天早上 9 点提醒我今天要做什么」「每小时给我发一次当前时间」「看看我设了哪些定时任务」都归这条。看有哪些定时任务就是 schedule_list,删和改也一样。

可靠性

- 归档或消失的会话会自动换绑,并给你一句提示(不是把消息吞掉):原对话被归档了 → 新建一个接上,你收到通知。
- 状态写入在 Windows 上有重试与退避(应对「文件被占用」那类 EPERM)。
- 空内容/未知帧类型的入站消息留日志(不再零痕迹)。

agent 能用的三个工具

| 工具 | 作用 |
| send_to_qq | 把本机文件发到提问的那个对话。图片变照片、视频变可播放片段、其它变文件附件 |
| notify_qq | 从任意会话推送到你当前所在的 QQ 对话。这是「干完了告诉我」的实现,实测可用(连发十条全部送达,其中后六条是主动推送) |
| qq_session_control | 查看/切换/新建/中断对话,以及查看或切换模型与推理等级 |

名字里的 qq_ / _qq 是有意的:工具名在宿主作用域下全局唯一,而微信版已经占了 session_control。两个插件抢同一个名字,后注册的那一方会静默失败。

这三个是插件给的。定时任务不在其中,因为它不需要插件实现:它走 DSH 宿主自带的 schedule_create / schedule_list / schedule_delete / schedule_update,插件只负责把结果发到 QQ 这条通道上。

设置

设置 → QQ,按页面上的顺序一共六组:

- 帮助 —— 页面上那个「打开使用手册」按钮,打开的是用户手册(docs/HANDBOOK-USER.md,指令与设置项都以它为准)
- 连接 —— 通道开关、扫码绑定、已绑定账号、解绑
- 权限 —— QQ 会话的权限预设(只有 auto 和「跟随 DSH 设置:和桌面端一样」还可能弹审批提示)
- 行为设置 —— 见下表
- 指令 —— 页面上印的斜杠指令速查(/help、/new、/list、/switch、/current、/cancel、/model)
- 诊断 —— 日志尾、工作区路径、会话数、待处理交互

这是设置页的全貌(下面几张是把它分段放大):

这是页面顶部两张卡片,也是你第一次装完会看到的东西——「帮助」与「连接」:

扫码绑定就在这张图的下半部分:点「重新扫码」,用手机 QQ 扫一扫并在手机上确认。
你不需要事先去腾讯开放平台注册,也不需要准备 AppID/AppSecret——机器人应用是那次扫码当场创建的。
「已绑定账号」那一行是绑定之后的样子(AppID ← 一个不可逆的指纹 · 绑定时间),旁边「已连接」是通道此刻的状态。

中间两组是权限与指令速查:

权限预设是三个中文选项,图里选中的是默认的那个:

| 选项 | 含义 |
| 完全访问:不询问,直接执行 | 默认。agent 不再问你——问了的话消息发到 QQ,而任务会一直等你回答 |
| 自动审核:电脑上判断 | 让电脑上那套策略来判,可能弹提示 |
| 跟随 DSH 设置:和桌面端一样 | 和桌面端完全一致,可能弹提示 |

只有后两个还可能把权限提示发到 QQ。想验证「权限审批能不能回流到手机」这件事,就把这里切成能弹提示的那个预设——那时候你手机上会收到一条待批准的请求, 回「允许」/「拒绝」,或者回数字选项都算回答。

<img src="docs/images/settings-b.png" width="620" alt="设置页的「指令」组:「斜杠指令」表格列出 /help、/new [标题]、/list、/switch <编号>、/model [名字]、/current、/cancel 及各自说明,底部写「分隔符可用「:」或直接省略,例如 /switch1。」;下面「说大白话也可以」一段说明直接说「换个对话」「看下有哪些对话」「停一下」都行">

这一组就是 /help 在设置页里的样子,指令与设置项都以用户手册为准。
下面那句「说大白话也可以」也是真的:DSH 会先说明它要做什么,你同意后再执行——想跳过这一步,把上面的「会话操作先确认」关掉。

页面下半部分的行为设置与会话文件夹路径:

会话文件夹这一项带原生文件夹选择器(就是那个「选择…」按钮)。
输入框里是你填的原文,右边「当前生效」是实际在用的路径——两者分开是有意的,填错时你能看到自己填了什么去改,同时知道现在实际在用哪个。

最后是诊断区,出问题时的第一条线索:

<img src="docs/images/settings-c.png" width="620" alt="设置页的「诊断」组:日志文件 C:\Users\XCISXC\.dsh\qq\boot.log、会话工作目录 C:\Users\XCISXC\.dsh\dsh_qq、对话数 1、待回答交互 0、被动回复限流 4 次/1 小时;下面「日志末尾」是一个可滚动的日志框,里面有 sdk info [qqbot:api] <<< Status: 200 OK 与 TraceId 等行,最后一行是 send_to_qq: path=…DSH 自画像.png -> 文本已发送;已发送图片 DSH 自画像.png">

诊断区给的是日志路径 + 末尾日志,所以大多数问题你自己就能看出是发失败了、限流了,还是附件没落盘。图里最后一行正好是一次成功的 send_to_qq。

把这些卡片加起来,一共九个设置项:

| 设置 | 默认 | 说明 |
| permissionPreset | danger-full-access | QQ 会话的权限预设。权限提示发到手机上会让任务一直等你回答,所以默认不设闸——见安全 |
| requireConfirmation | 开 | agent 执行会话操作前是否先问你一次 |
| allowCrossSessionNotify | 开 | 关掉后 notify_qq 只能推给调用者自己的会话(更严的姿态) |
| mergeWindowMs | 10000 | 纯附件消息先停这么久,等你补一句指令;0 = 不等待 |
| autoReplyAttachments | 开 | 窗口内没等到指令时,是否把附件交给 agent。关掉不是忽略附件,而是等用户说话 |
| maxReplyChars | 4000 | 超过就作为 .md 文件发送;0 = 不限制 |
| settleMs | 1200 | 连续流片段之间静默多久就发出去 |
| presenceNote | 一段中文说明 | 随每条消息交给 agent:你在手机上、看不到这台电脑的屏幕,要看东西就直接发 |
| workspacePath | 空 = $DSH_HOME\dsh_qq | 会话文件夹。必须是绝对路径;填错只会「没生效」,绝不会让插件起不来 |

设置会持久化,重启后仍是你选的那份。老状态文件(没有 settings 块)照常可读。

每一项设置只定义在一处——lib/settings.js 的 SETTINGS_SCHEMA,每项一个校验器加一个 default。加载归一、落盘、设置页快照与往返测试全部由它派生,所以加一项设置就是在那张表里加一行,其余各处不可能各走各的。纯 JS 没有编译器能拦住"加了设置却忘了加校验器",所以 scripts/verify.mjs 里有一条断言:schema 的键集、"运行时此刻实际持有"的键集、以及真正写到盘上的键集必须是同一个集合——那条断言就是我们没有的那个编译器。
(微信插件踩过这条故障:三份手抄名单各改各的,加设置时漏掉一份就会静默丢字段,而且每次写盘都重新加载并重新规范化,于是下一次写盘把丢失持久化了。)

workspacePath 旁边显示的是实际生效的路径,而输入框里是你填的原文。两者分开是有意的:填错时你能看到自己填了什么去改,同时知道现在实际在用哪个。

⚠️ 改路径不搬动已有的对话。 它们留在原来的文件夹,只有之后新建的用新路径。
这是唯一安全的做法——宿主在采用已存在会话时比对 cwd,不一致会抛 ApiSessionCwdConflict,那个会话就永远接不回来了。

文件夹布局

| 用途 | 路径 |
| 会话工作区(桌面端显示为「QQ 会话」) | $DSH_HOME\dsh_qq(可用 workspacePath 改) |
| 入站媒体 + 长回复 .md | <会话工作区>\媒体 |
| 插件状态与日志 | $DSH_HOME\qq\state.json、$DSH_HOME\qq\boot.log |

出问题了看哪里

| 现象 | 先看哪里 |
| 设置页看不到 QQ 区块 | 客户端插件没加载。看 %APPDATA%\@deepseek-ai\dsh-desktop\logs\crash-*-web-boot.log 的 renderer console 段 |
| 整个应用起不来 | 同上。那条致命错误本身信息量很少,真正的原因在 renderer console 里 |
| 机器人不回消息 | boot.log 里有没有 入站;GET /.dsh-qq-plugin/status 的 errors 数组 |
| 图片/语音没反应 | boot.log 里找 附件下载失败 或 附件已停靠 |
| 「发不出去」 | 看 boot.log 里有没有 待发已入队——主动推送的规则可能变,插件不假设额度;没送达的消息会在你下次说话时补发 |

调试用的 HTTP 端点都在 /.dsh-qq-plugin/ 下:status、log、settings、 permission-presets、accounts、login、start、stop 等。

与微信版的差异

功能上对齐,但有几处是有意不同,因为 QQ 协议给了微信那边没有的东西:

| 引用消息 | QQ 的 msg_elements 直接给被引正文,所以微信那套 quoteHistory 缓存不需要 |
| 语音 | QQ 服务端直接给 voice_wav_url + asr_refer_text,不需要 SILK 解码,也没有随之而来的那句免责 |
| 待发队列 | 微信因为 iLink 不允许主动发而必须排队;QQ 主动推送可用,队列的用途是把没送达的消息补发(网络、平台拒绝、规则变化都算),不是某一种失败的兜底 |
| 工具名 | 见上文(宿主作用域全局唯一) |
| 安装 | 没有构建步骤,也没有 allowBuilds 询问:本插件就是普通 JavaScript,Git 安装直接打包就能跑 |

安全

只有你能碰到它。 通道只跟腾讯官方的 QQ 机器人服务说话,没有别的东西——没有第三方服务,中间也没有自建中转。机器人是一个独立的应用,管理员是你的 QQ 账号,而且是你自己扫码创建的;未认证的机器人仅管理员可用。它不是一个能发出去的 QQ 名片:没有地方能搜到它,也没有人能加它。不存在「别人也能给它发消息」这个面,所以这里没有白名单——平台自己的规则就是白名单。

AppSecret 是长期密钥,就按长期密钥对待。 它以 grant 记录写进 DSH 的凭据存储,而不是写进插件的明文状态文件(那里只有 AppID)。要轮换就回设置页重新绑定一次。

还有三件事是真的,值得知道:

QQ 来的对话默认全权限运行——agent 动手前不问。这是有意的:权限提示会发到 QQ,然后任务就在那里等你,于是在手机上每条命令都会卡在你早已走开的那个对话里。
想要和坐在电脑前一样的护栏,就把设置页里的「QQ 会话的权限预设」改成 auto (或改成跟随 profile 自己的策略)。

agent 以你的身份运行。 它能执行命令、读写文件,用的是你这个用户的权限——它本来就是干这个的,也就是说这台机器上你能做的事它都能做。所以:走开之前扫一眼你让它干的是什么,离开时锁屏。锁屏不会让 agent 停下来,但能挡住路过的人。

默认任意会话都能推送到你的 QQ。 这是「干完了告诉我」能成立的原因:干活的那个会话通常不是你 QQ 对话绑定的那个,不放开这一条它就报不了自己的结果。关掉 allowCrossSessionNotify 就回到更严的规则:只有绑定的那个会话能发。

文档

| docs/HANDBOOK-USER.md | 用户手册——设置页那个帮助按钮打开的就是它,指令与设置项都以它为准(中文) |
| docs/POSTMORTEM.md | 每一个真实踩过的坑——每一条都付了代价,也每一条都是一个检查器存在的理由(中文) |
| docs/SETTINGS-CONTRACT.md | 设置页背后的宿主/客户端路由契约,逐条读自真实调用点(中文) |
| docs/RELEASING.md | 一次版本怎么发:tag、OIDC,以及一次性的 Trusted Publisher 配置(中文) |
| docs/STEP3-能力调研与实现规格.md | QQ 交互消息与流式的能力调研。状态:暂缓,未实现——当前代码里没有任何按钮、也没有流式;调研结论是真的,留着给将来重启这项工作用(中文) |

开发

普通 JavaScript,没有构建步骤,没有转译器。CI 跑 Node 24;manifest 里不写 engines 范围——本插件只需要跑在已经在场的那个 DSH 宿主里。

npm ci

node scripts/verify.mjs # 宿主侧
node scripts/verify-client.mjs # 客户端注册形状(不是视觉验证)
node scripts/verify-send-path.mjs # 发送路径,跑在假 SDK 上

822 项宿主侧检查、108 项客户端检查、60 项发送路径检查。

这三个数字是从上面那几条命令的实际输出里读出来的,不是手打的: tools/check-doc-counts.mjs 拿它们和脚本真正打印的数比,对不上时 CI 会失败并点名是哪个文件。
改了测试就改这里的数字,否则这道闸会拦住构建。

常设检查器

tools/ 里有四个检查器,每一个都对应一次真实事故,改动前请先跑:

node tools/check-unbound.mjs . # 用了但没导入
node tools/check-unused-imports.mjs . # 导入了但没用
node tools/check-doc-counts.mjs --run # 文档里的测试数量,以及 publish.yml 里的仓库名
node tools/check-cross-plugin.mjs <profileDir> # 跨插件共享资源

check-doc-counts.mjs 从三个测试套件的实际输出里读出那三个数,再和本文件、README.md、 docs/RELEASING.md 里写的比,对不上就点名是哪个文件、写的多少、实际多少。CI 里它读的是三个测试步骤已经落盘的输出,所以只多花一秒,而不是再跑一遍。--run 是本机用法:它自己把套件跑一次。

它还顺带核对第二样东西,理由相同:publish.yml 文件头那四个 Trusted Publisher 字段也是手抄的,抄错的表现只是发布时 403,所以它拿那一块和 package.json(属主与仓库名)、工作流自己的文件名与 name:、以及两版 README 的 CI 徽章逐个比。这里曾经写着 dsh-qq,而其它每一处都是 dsh-qq-plugin——这道闸就是为那次而加的。

check-cross-plugin.mjs 是本地检查,不进 CI:它要读一个真实的 DSH profile—— dsh.profile.bundles 那份列表,以及该 profile node_modules 下已装好的插件—— CI 的 runner 上两样都没有。它查的是所有插件共用的两样东西:客户端插件的顶层作用域 (shell 会把每个已启用 bundle 的 client.js 拼进同一个脚本,一份文件顶层的 const 就会和别人的撞车),以及宿主作用域的工具名(全局唯一)。

每个检查器都带反向对照:它必须能抓住它为之而写的那次故障,抓不住就判定为不可信并以非零码退出。一个永远报「通过」的检查器,比没有检查器更糟——它让人以为已经验过了。

smoke/ 里两个探针(step3-probe.mjs、step4-probe.mjs)连的是腾讯的线上服务,需要真实凭据与真实机器人;另外两个(step4-surface.mjs、check-sdk-surface.mjs)是离线表面核对,凭据和网络都不需要。四个都不进 CI——两个探针是因为凭据不该出现在公开仓库的 CI 里,两个表面核对是因为它们是一次性的调研脚本,只打印观察结果、不做通过/失败判定。

许可

MIT —— 见 LICENSE。
预览分享卡片长什么样 ↓xcisxc29/dsh-qq-plugin
分享 · DeepSeek Harness Hub
xcisxc29/dsh-qq-plugin

在 QQ 里用手机指挥这台电脑上的 DeepSeek Harness agent。

回到顶部