DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Qq Bot — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
Q

dsh-qq-bot

Qq Bot

A plugin that connects QQ to DSH Agent: sends and receives messages through OneBot 11 implementations such as NapCat, with each QQ session corresponding to one DSH Agent.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:arrow1031/dsh-qq-bot#a70539df6dd359e00118400288f5eba19cb28e74
READMECompatibilityVersions

Compatibility and provenance

Qq Bot is published as dsh-qq-bot and currently resolves to version 0.6.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
9/21/2026

Versions

0.6.0stable
9/21/2026

Related plugins

Loading related plugins…

Latest
0.6.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
9/20/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

README

dsh-qq-bot —— 把 QQ 接到 DSH Agent

⚠️ 维护状态:已封版,不承诺更新

功能完整、123 项测试全绿,但作者不做持续性维护——不修 bug、不适配上游变更、不接受功能请求。 遇到问题请 fork 下来自己改(MIT 许可,随便改随便发)。 为方便动手,仓库里有 ARCHITECTURE.md:文件职责、数据流、设计决策原因、分步改动指南。

作者 @arrow1031 · 许可 MIT · AI 生成声明与已知限制 AI-DISCLOSURE.md · 更新日志 CHANGELOG.md

个人网站 sputnikzaychik.icu · QQ 群 1091766276

一个可以装进 DSH profile 的插件:QQ 消息进来 → 交给 DSH Agent → 回复发回 QQ。

复用现成生态,不自造协议:

QQ 客户端
   │ QQ NT 协议
   ▼
NapCat(或 OneDisc / Lagrange 等 OneBot 11 实现)   ← 登录、收发、风控
   │ OneBot 11:正向 WS / 反向 WS + HTTP API
   ▼
lib/onebot-adapter.mjs(本插件自带,零 npm 依赖)    ← 协议翻译层
   │ stdin/stdout 换行分隔 JSON
   ▼
lib/index.js(Cordis 插件)                          ← 每个 QQ 会话一个 DSH Agent
   ▲ 设置面板读写(lib/client.js)                        ← 「设置 → QQ 机器人」选项卡
   │ sessionController → agent.followup → whenIdle
   ▼
DSH Agent(默认模型 + preset 人格 + 工具)

一、已验证的东西(不是设计稿)

全部在本机实跑:

测试命令结果
正向 WS 适配器回归node test/test-adapter.mjs19/19
反向 WS 适配器回归node test/test-adapter-reverse.mjs12/12
打包后插件端到端(Host)node test/test-plugin.mjs25/25
客户端设置页(含真实渲染冒烟)node test/test-client.mjs31/31
权限·群管理·访客工具闸node test/test-admin.mjs36/36
组合能否加载dsh --profile web --dump-config --patch <补丁>通过(行被正确插入)
装到 profile 后的模块解析解包到 profile 后 import('@deepseek-ai/dsh-tools')通过

test-plugin.mjs 用假 ctx(自己实现了 subprocess / sessionController / timer / effect / tools)加载真正的 lib/index.js,配一个真的假 OneBot 服务,跑完整条链路:假 QQ 消息 → 假 OneBot → 真适配器 → 真插件 → 假 Agent → 回复 → 真适配器 → 假 OneBot。所以不需要 DSH、不需要 QQ 号、不需要网络就能回归。

另外,本插件的前身(examples/dynamic-package-host.js)曾用动态 Cordis Package 的形式在真 DSH 里跑过完整链路:真模型回复、会话落盘、qqbot 工具注册都验过。所以 Cordis 服务接线本身也是验证过的。

二、快速开始

1. 起一个 OneBot 11 实现(推荐 NapCat)

NapCat 官方 Docker 镜像(支持 amd64 与 arm64):

docker run -d --name napcat --restart=always \
  -e NAPCAT_GID=$(id -g) -e NAPCAT_UID=$(id -u) \
  -p 3000:3000 -p 3001:3001 -p 6099:6099 \
  mlikiowa/napcat-docker:latest
  • WebUI:http://<主机IP>:6099/webui,用手机 QQ 扫码登录;登录 token 默认在 docker logs napcat 里。
  • 容器内配置目录 /app/napcat/config,QQ 数据目录 /app/.config/QQ(想固化登录就挂这两个卷)。
  • 在 NapCat 的「网络配置」里确认 OneBot 11:
    • HTTP 服务器 3000 —— 用来发消息
    • 正向 WebSocket 3001 —— 用来收事件
    • 若设了 access_token,记下来填进插件配置
  • 端口默认就是 3000/3001,和本插件默认值一致,不用改代码。

2. 安装插件

dsh plugin --profile web add /path/to/dsh-qq-bot-<版本>.tgz

dsh plugin 本质是 pnpm 的前置封装:装完包后,它会自动把声明了 dsh.bundle.patch 的依赖加入 profile 的层栈(本包的 package.json 已声明)。然后重启 dsh web 生效。

升级注意(重要):dsh plugin add 转发给 pnpm,而 pnpm 按 tarball 的完整性哈希缓存。 改了代码必须打成新的版本号文件名再装(0.3.0 → 0.3.1);沿用同一个文件名会被判成“lockfile 已最新”而跳过,装的还是旧内容。 npm pack 默认就带版本号,所以正常发版流程不会踩到。

客户端改动要多一步:lib/client.js 是浏览器侧代码,装好并重启 dsh web 之后, 还要刷新浏览器页面才会加载新的客户端 bundle。

不想打包也行,直接 dsh plugin --profile web add <你的 git 仓库或 tarball 地址>。

3. 在 QQ 里试

  • 群聊:默认要 @机器人 才有反应,@ 会被去掉再交给 Agent。
  • 私聊:默认直接回。
  • 长回复按换行切成 ≤1200 字多条发送。
  • 每个群/每个人是独立的 DSH 会话(id 形如 qqbot-group-33333),会落盘并出现在 Web UI 会话列表里,可以像普通会话一样打开继续聊。

三、两种连接模式,怎么选

场景用哪个配置
NapCat 和 DSH 在同一台机器/同一容器正向 WS(默认)mode: forward,我们连 ws://127.0.0.1:3001
NapCat 在别的容器/主机,或网络方向只允许 NapCat 连出来反向 WSmode: reverse,我们在 0.0.0.0:6199 监听,NapCat 里填 ws://<DSH主机IP>:6199/

反向 WS 的鉴权:请求头 Authorization: Bearer <token> 或 URL 上的 ?access_token=<token> 都接受(后者是因为浏览器/Node 的标准 WebSocket 客户端无法自定义请求头)。

四、配置

方式一:在 DSH 设置里改(推荐)

重启 dsh web 后,打开 设置 → QQ 机器人,所有配置都在这一个选项卡里: 连接方式、WS/HTTP 地址、access_token、群聊开关与 @ 要求、白名单、命令前缀、 回复分片长度、慢回复提示、来源前缀、每会话独立、preset、工作目录、逐帧日志。

  • 改完点「保存」;连接方式那几项(模式/地址/token)保存后会自动重启适配器,其它项下一条消息生效。
  • 类型映射:布尔是勾选框;白名单是逗号分隔的文本框;连接方式是下拉框。
  • 配置分两层:composition 行配置是 base 层,设置面板里改的是 用户层(存在 $DSH_HOME 的设置文档里)。
  • 连接状态不在设置页里显示,在对话里让 Agent 调用 qqbot 工具(action=status)看。
  • access_token 是只写字段:已设置时页面显示「已设置;留空则保持不变」,只有输入新值才会覆盖。 Host 侧把它声明成 schema 的 secret,值不会下发到浏览器,保存时也不会被空值清掉。

方式二:改 composition 行配置(当 base 层用)

不要改包内的 cordis.patch.yml(升级会覆盖)。写进你自己的 $DSH_HOME/profiles/web/cordis.patch.yml —— 它在所有 bundle 之后应用,按 id 定向覆盖:

- id: dsh-qq-bot
  config:
    mode: forward                 # forward | reverse
    workspace: '/home/dsh'        # 每个 QQ 会话 Agent 的工作目录
    onebot:
      wsUrl: 'ws://127.0.0.1:3001'      # mode=forward 用
      listen: '0.0.0.0:6199'            # mode=reverse 用
      httpUrl: 'http://127.0.0.1:3000'  # 留空则改用 WS action 发消息
      accessToken: ''
    group:
      enabled: true
      requireAt: true             # 群里是否必须 @
      allow: []                   # 群号白名单,空数组 = 所有群
    private:
      enabled: true
      allow: []                   # 用户号白名单,空数组 = 所有人
    commandPrefix: ''             # 例如 '/ai',空串 = 不限制
    reply:
      maxChars: 1200
      ackAfterMs: 8000            # 慢回合先回「正在处理」;0 关闭
      ackText: '正在处理,请稍候…'
      contextHeader: true         # 给消息加 "[QQ群 123 · 小明(22222)]" 前缀
      firstTurnHint: '(提示:这是一次 QQ 聊天。请用简体中文、简洁自然的口语作答;不要输出 Markdown 表格,代码块保持简短。)'
    auth:                         # 权限,见「五、权限与群管理」
      owners: []                  # 拥有者 QQ:全权限 + 永久授权 + 可走独立会话
      superAdmins: []             # 后台设定的高级管理员(不可永久授权)
      ownerPreset: ''             # 填了才把拥有者/非拥有者分成两条会话
      guestPreset: ''             # 非拥有者用的 preset(仅人格分离,非安全边界)
      guestDshTools: false        # 是否允许访客用 DSH 内部工具(默认否)
      guestToolAllow: ['qqbot', 'qqgroup']   # 访客仍可用的工具白名单
      grantTtlMinutes: 60         # 群管理员动态授权默认时长
      grantMaxTtlMinutes: 1440    # 群管理员单次可授最长
    admin:
      enabled: true
      manageGroups: []            # 可管理的群;空 = 回退用 group.allow
      requireGroupAdmin: true     # 是否承认「本群管理员」这一路权限
      prefix: '/'                 # 指令前缀(必须在消息首位)
      dryRun: false               # true = 只回复将执行什么
      allowConsole: false         # 允许 Web UI 会话直接调用管理工具
    perChatSession: true          # true=每个 QQ 会话一个 DSH 会话
    agentPreset: ''               # ''=部署默认 preset;可填自定义 preset id 换人格/工具
    adapterPath: ''               # ''=用包内自带适配器
    nodePath: ''                  # ''=自动解析 node
    logAdapterFrames: false       # 排查时开,会打印每一帧 JSON

agentPreset 是换人格的正规做法:给 QQ 机器人做一个专属 preset,把 id 填进来。

五、权限与群管理

权限是三路并行取并集(不是"先命中先返回"):

路径谁能做什么
静态名单 auth.owners拥有者全部权限 + 永久授权 + 可走独立的拥有者会话
静态名单 auth.superAdmins后台设定的高级管理员群管理权限(不能永久授权)
动态授权被临时授权的人仅被授予的那几项,仅限本群、带时限
本群身份该群的 admin / owner群管理权限(可用 admin.requireGroupAdmin 关掉这一路)

任一路给到某项权限即拥有它;来源会在 /whoami、/perms 里如实列出,便于排查"他为什么有权"。

权限项:query(查询)、mute(禁言)、kick(踢人)、recall(撤回)、settings(群名/名片/管理员/全员禁言)、grant(给本群成员授权),拥有者另有 permanent(永久授权)。

动态授权(群维度,不可跨群)

  • 拥有者或本群管理员可以给本群成员临时授权:/grant @某人 mute 30(30 分钟)
  • 只有拥有者能永久授权:/grant @某人 kick forever(非拥有者发这条会被拒)
  • 群管理员单次最长 auth.grantMaxTtlMinutes(默认 1440 分钟)
  • 授权键是「群号 + QQ 号」:在 A 群授的权,在 B 群一律无效
  • /revoke @某人 [权限] 撤销、/grants 列出本群全部授权

非拥有者不使用 DSH 内部功能:执行级工具闸

用一个 tools.guard 硬闸,只在建会话时注册一次,判据是闭包里的可变标志位:

  • 注册在 agent.ctx 上 → 只作用于该会话的 agent
  • 每次工具执行时才求值 → 拥有者/访客交替说话不需要增删限制
  • 用白名单(auth.guestToolAllow,默认 qqbot,qqgroup)→ run_code(PTC 保留传输)这类"不在全局层"的特殊工具也会被自动挡住
  • 被拦时返回拒绝原因,模型会把它转达给用户(最多多一次"被拒绝的调用"往返)

因此它同时满足:0 额外 token(不注入提示词、不改工具表、不记 request/header)、单会话单历史、不改 DSH 本身。

想放开就设 auth.guestDshTools: true(不建议)。

为什么不用"每条消息增删 tools.restrict":restrict 是静态过滤器,想按说话人变就得反复增删,工具面抖动会让 agent loop 多记 request/header,反而更费 token、代码也更多。guard 是每次执行才求值的函数,配一个可变标志位就够。

会话分流(可选,仅供人格分离)

auth.ownerPreset / auth.guestPreset 都留空时,拥有者与非拥有者共用一条会话(默认,也是推荐)。填了 preset id 才分成两条:

  • 拥有者走 qqbot-group-<群号>,挂 ownerPreset
  • 非拥有者走 ...-guest,挂 guestPreset

这只是换人格,不是安全边界——工具隔离由上面的 guard 负责。分流要付代价:同一个群会有两条历史,拥有者看不到访客说了什么。除非确实要给访客不同的说话风格,否则别开。

上下文头会带身份,例如 [QQ群 33333 · 小明(22222) · 身份:访客|本群管理员+动态授权[mute 至 ...]],让 Agent 自己决定怎么对待这个请求。

指令的严格性(防"聊天内容夹带指令样内容"被误执行)

  1. 前缀必须位于消息首位(前面只允许空白)——你好 /mute @x 不会被当成指令
  2. 动词必须完全匹配已知指令,未知动词照常交给模型
  3. token 数量必须落在该指令声明的 [min,max] 内,多余内容判为用法错误、不执行
  4. 权限不足直接拒绝,且不做任何动作

指令不需要 @ 机器人(刻意放在 requireAt 之前),但上述规则一条都不放宽。

指令表

指令权限作用
/help—列出全部指令
/whoami—看我在本群的身份与权限来源
/perms [@某人]query看某人在本群的权限来源(三路)
/grantsgrant列出本群的动态授权
/grant @某人 权限[,权限] [分钟|forever]grant临时授权(仅本群)
/revoke @某人 [权限]grant撤销授权
/membersquery成员列表(最多列 30 条)
/infoquery群信息
/mute @某人 [分钟=10]mute禁言(0 = 解禁)
/unmute @某人mute解除禁言
/kick @某人kick移出本群
/recall [消息id]recall撤回;回复某条消息再发 /recall 可省略 id
/banall on|offsettings全员禁言开关
/card @某人 新名片settings改群名片
/admin @某人 on|offsettings设/撤管理员
/rename 新群名settings改群名

Agent 工具(与指令共用同一套鉴权)

qqgroup 的 action:只读 group-list/group-info/member-list/member-info,写操作 mute/unmute/kick/whole-ban/set-card/set-admin/rename/recall/poke。

工具的"说话人"取自本会话最近一条消息,所以群里普通成员没法靠一句话驱动管理动作——这一点是提示注入的主要防线。group_id 留空时默认用当前会话所在的群。

群事件

适配器会把完整事件字段透传上来(operator_id 谁操作的、duration 禁言时长、target_id、card,以及被引用消息的 reply_to)。当前版本只做透传与计数(qqbot status 里能看到),自动治理尚未实现。

建议的上线顺序

  1. 在设置里填 auth.owners(至少填自己)
  2. 打开 admin.dryRun,在群里发几条指令确认解析与回执
  3. 关掉 dryRun,再按需加 auth.superAdmins
  4. 非拥有者用 DSH 功能由访客工具闸默认拦截,无需额外配置;确实想放开再改 auth.guestDshTools

六、Agent 能用的工具

插件注册了一个动态工具 qqbot:

  • {action:'status'} —— 连接状态、模式、适配器 pid/端口、各 QQ 会话的回合数、统计计数
  • {action:'send', message_type:'group'|'private', target_id:'123', text:'...'} —— 主动发一条 QQ 消息
  • {action:'interrupt', conversation:'group-123'|'all'} —— 中断正在跑的回合

qqgroup(群管理)

见「五、群管理」一节。工具路径的授权依据是「当前会话最近一条消息是否来自管理员白名单」。

七、排错

现象检查
日志一直「OneBot 未连接」NapCat 的「正向 WebSocket」是否开在 onebot.wsUrl;reverse 模式下 NapCat 是否指向了 ws://<DSH>:6199/;防火墙;token 是否一致
能连上但收不到消息OneBot 版本要选 v11;不能只开 HTTP,必须开正向或反向 WS
群里 @ 了也不回group.enabled;group.allow 白名单;self_id 与消息里的 self_id 是否一致(logAdapterFrames: true 能看到原始帧)
回「(本轮没有产生文字回复:...)」括号里是从会话日志读出的 turn/end 原因,据此定位(模型路由、额度、工具报错等)
发送失败NapCat 的 HTTP 服务器(默认 3000)是否开着;accessToken;看日志里的「发送失败」
日志在哪插件前缀 [dsh-qq-bot],适配器前缀 [dsh-qq-bot]/adapter,都打到 DSH Host 的 stdout

八、无 QQ 号自测

裸克隆即可运行:需要 DSH 运行时才能成立的少数断言(动态工具注册)会自动跳过,而不是判失败。 整套 123 项:

npm test

或分开跑:

# 适配器回归(正向 19 项 + 反向 12 项)
node test/test-adapter.mjs
node test/test-adapter-reverse.mjs

# 打包后插件的端到端(假 ctx + 真适配器 + 假 OneBot)
node test/test-plugin.mjs    # Host 半边(25 项)
node test/test-client.mjs     # 客户端设置页(31 项)
node test/test-admin.mjs      # 权限·群管理·访客工具闸(36 项)

也可以手动拿假 OneBot 试(端口正好是 NapCat 默认值):

node test/mock-onebot.mjs --http-port 3000 --ws-port 3001
# 另开一个终端,伪造一条 @机器人的群消息
node -e "fetch('http://127.0.0.1:3000/__inject',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({message_type:'group',group_id:33333,user_id:22222,nickname:'小明',message:[{type:'at',data:{qq:'10000'}},{type:'text',data:{text:'你好'}}]})}).then(r=>r.json()).then(console.log)"
# 看机器人回了什么
node -e "fetch('http://127.0.0.1:3000/__sent').then(r=>r.json()).then(j=>console.log(JSON.stringify(j.messages,null,2)))"

九、关于 AstrBot(容易搞混,单独说)

AstrBot 不是 OneBot 的提供方,它是消费方。 它的 aiocqhttp 适配器是 OneBot v11 的反向 WS 服务端(默认 6199 端口、/ws 路径),由 NapCat 连进去推事件——也就是说 AstrBot 本身就是「大脑」,和本插件的角色重叠。

所以:

  • 想用 DSH 当大脑 → 只需要 NapCat 这类 OneBot 实现,对端不要再接 AstrBot,否则两边都会抢着回复同一条消息。
  • 想用 AstrBot 的插件生态当大脑 → 那就不需要本插件了。
  • 两者可以共存于同一个 DSH 里(NapCat 同时开正向 WS 给本插件、反向 WS 给 AstrBot),但同一条消息会被两个大脑各回一次,一般不是你要的。

对端是「OneBot 11 实现」就行,NapCat / OneDisc / Lagrange / LLOneBot 都可以,只要开正向或反向 WS + HTTP。

十、在手机容器里跑 NapCat 的注意事项

  • NapCat 官方镜像有 arm64 版本,所以理论上能在 arm64 容器里跑;但容器里再跑 Docker 通常需要 privileged 权限,不一定允许。
  • 备选:不用 Docker,直接在容器里跑 NapCat.Shell(需要对应的 Linux QQ + NapCat 版本)。
  • 同容器时用 forward 模式连 127.0.0.1:3001 最省事;如果 NapCat 在别的容器,用 reverse 模式,让 NapCat 连到 ws://<DSH主机IP>:6199/。
  • 端口 6099 是 NapCat 的 WebUI(扫码登录用),不要暴露到公网。

十一、文件清单

文件作用
lib/index.jsCordis 插件本体(Host 侧)。导出 name / inject / apply,并注册 qq-bot 设置命名空间
lib/client.js客户端半边(手写 bundle):在「设置」里加「QQ 机器人」选项卡
lib/onebot-adapter.mjsOneBot 11 传输适配器。零依赖(Node 22 内置 WebSocket/fetch),正向/反向 WS + HTTP,自动重连、发送限速
cordis.patch.ymlbundle 补丁:把插件插入 profile 组合树
test/mock-onebot.mjs零依赖 OneBot 11 模拟器(手写 RFC 6455 帧编解码)
test/test-adapter.mjs正向 WS 适配器回归(19 项)
test/test-adapter-reverse.mjs反向 WS 适配器回归(12 项)
test/test-plugin.mjsHost 插件端到端(25 项,假 ctx + 真适配器 + schema 契约)
test/test-client.mjs客户端设置页(31 项,模拟模块加载器 + 最小 React 渲染 + 只写密钥护栏)
test/test-admin.mjs权限·群管理·访客工具闸专项(36 项)
examples/dynamic-package-host.js同一个桥接的「动态 Cordis Package」版本:不想装包、只想在当前 DSH 进程里临时跑时用
ARCHITECTURE.md改动指南(给要 fork 的人):文件职责、数据流、设计决策原因、分步改动指南、调试手册、术语表
AI-DISCLOSURE.mdAI 生成内容声明、验证情况、尚未验证清单、第三方归属、安全免责
CHANGELOG.md版本演进(0.1.0 → 0.6.0)
LICENSEMIT

十二、设计说明(踩过的坑)

为什么中间要一个子进程? DSH 动态插件的沙箱里没有 fetch / WebSocket / require(都被拦成报错)。所以插件用 ctx.subprocess 拉起一个真 Node 进程,两者用换行分隔 JSON 通信。好处是协议层可以独立测试(test-adapter.mjs),换 QQ 框架不影响插件。

为什么用 sessionController 建会话? 直接 agentLoop.create() 建出来的 Agent 没有安装模型路由(agentOptions 为空、没挂 preset),第一次模型请求必然失败。sessionController.create() + resolveAgent() 才是官方组装路径:它从 agentDefaultModel 装上 provider/model,并挂载 Agent preset(人格 + 工具)。这个坑在代码注释里标注了。

为什么用 whenIdle() + deriveMessages() 取回复? 每个会话的回合是串行排队的,回合结束后会话日志里最新一条有文本的 assistant 消息就是这一轮的回复。比订阅作用域流式事件更简单也更稳。

访客工具闸为什么是 guard 而不是拆会话 / restrict? 拆会话会把一个群变成两条历史,破坏对话一致性;restrict 是静态过滤器,按说话人变就要反复增删,工具面抖动会多记 request/header、更费 token。tools.guard 是每次执行才求值的函数:只在建 agent 时注册一次,判据是可变标志位,于是同时做到 0 额外 token、单会话单历史、不用改 DSH。另外标志位必须在串行回合内部设置——放在接收入口会被排队的两条消息互相覆盖,导致用错权限。

为什么用动态 import('@deepseek-ai/dsh-tools')? @deepseek-ai/* 是 peerDependency,由 DSH 运行时提供(安装后在 $DSH_HOME/profiles/node_modules 里能解析到)。用动态 import + try/catch,即使这个包不在,桥接本身照样工作,只是少一个 qqbot 工具。

十三、不想重启 DSH 也能先跑起来(动态 Cordis Package)

装包需要重启 dsh web。如果你想在当前进程里立刻试,用动态 Package:

动态插件的沙箱里没有 import/require,但可以用一个小加载器把磁盘上的同一个源文件当函数体求值:

const SOURCE_FILE = '/home/dsh/qq-bot/examples/dynamic-package-host.js';

return {
  name: 'qq-bot-bridge (dynamic source loader)',
  inject: ['fs', 'subprocess', 'sessionController', 'timer'],
  async apply(ctx) {
    const target = await ctx.fs.resolve(SOURCE_FILE);
    const source = await ctx.fs.readText(target);
    const factory = new Function('harness', 'console', 'TextDecoder', 'TextEncoder', 'btoa', 'atob', source);
    return factory(harness, console, TextDecoder, TextEncoder, btoa, atob).apply(ctx);
  },
};

这样动态路径和常驻插件共用同一份磁盘源码,不用把逻辑复制两遍。把这段交给 cordis_define(code.host)再 cordis_run 即可。

  • 优点:立刻生效,不用重启;inject 和沙箱 ctx 的语法和常驻插件一致。
  • 限制:只活在当前 DSH 进程里,DSH 一重启就没了,要长期在线还是得装包。
  • 动态沙箱里没有 require/fetch/setTimeout,所以传输层必须靠 ctx.subprocess 拉子进程(这也是 lib/onebot-adapter.mjs 存在的原因)。

十四、许可、成本与维护状态

许可与作者

MIT,见 LICENSE。作者 @arrow1031。

项目成本

由一次连续会话完成(2026-09-20),全部代码 + 测试 + 文档:

时间Token费用
约 5 小时 10 分约 110M约 ¥7.2

成本大概是一杯咖啡,以及一个无聊的下午。

时间由文件系统时间戳推算,含人工真机确认与等待;会话中途切换过多个模型。

维护状态:不承诺更新(请自行 fork)

本项目到此封版。 作者不做持续性维护:不承诺修 bug、不适配上游破坏性变更、不接受功能请求。

  • 遇到问题:fork 下来自己改。MIT 许可,随便改、随便发,不用打招呼。
  • 上游变了(DSH 升级 / NapCat 改字段 / OneBot 实现换代):自己跟。
  • 想加功能(自动治理、更多指令、别的 IM):自己加。

为了让你改得快,这些文档是专门为你写的:

文档内容
ARCHITECTURE.md改动指南:文件职责地图、一条消息的完整旅程、关键数据结构、每个设计决策的原因、加一条指令 / 加一个工具 / 加一个设置项的分步写法、调试手册、术语表、8 条"不要做的事"
AI-DISCLOSURE.mdAI 生成方式、人类决策点、验证到什么程度、尚未验证的清单、第三方归属、安全免责
CHANGELOG.md0.1.0 → 0.6.0 的完整演进,含每个修复的原因

致谢

  • NapCat —— 提供灵感、OneBot v11 接口与文档。 没有它把 NTQQ 的能力按 OneBot 规范暴露出来,这个项目根本无从起步。
  • 梁圣 —— 忠!橙!

联系

  • 个人网站:https://sputnikzaychik.icu
  • QQ 群:1091766276(点这里加群)
  • GitHub:@arrow1031

AI 生成内容声明见 AI-DISCLOSURE.md,使用前请务必读一遍(尤其"已知限制"一节)。

运行时依赖:零 npm 依赖。适配器只用 Node 22 内置的 WebSocket 与 fetch;唯一可选的 @deepseek-ai/dsh-tools 仅用于注册一个动态工具,缺失时自动降级。

Related plugins

More verified plugins in integrations-communication.

Acp App@deepseek-ai/dsh-acp-appThe dsh ACP profile bundle: automation-only JSON-RPC stdio and process lifecycle over dsh-baseRemote Web Ui@linxin666/dsh-remote-web-uiScan-to-pair remote access for the dsh web GUI that shares one official interface: a QR beside the settings button pairs phones and PCs into the same Web GUI (a portrait-touch adaptation layer for phones, full desktop on PCs) through one-time tokens and rPocketdsh-pocketPut DeepSeek Harness in your pocket: one package, one settings page, and scan a QR code on your phone to access DSH on your computer in sync (LAN + public network, real-time screen mirroring).DSCODE@toddzheng024/dscode-bundleA complete DeepSeek coding agent with persistent shell, Ultra collaboration and automatic permission review.