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

QQ 通道 wzwei1990/dsh-napcat

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

把 QQ 私聊和群聊消息接入智能体并自动回复

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

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

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

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · platform
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/10/22·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 15 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

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

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

读写/删除本地文件发起外部网络请求
查看扫描证据(共 79 处,展示前 45 条)
  • 写入本地文件
    lib/bridge.js:1379
    void appendFile(join(dir, 'napcat-inbox', '_image-debug.log'), new Date().toISOString() + ' v0.3.7 ' + note + '\n').catch(() => undefined);
  • 读取本地文件
    lib/bridge.js:1404
    if (!existsSync(file))
  • 读取本地文件
    lib/bridge.js:1420
    const buffer = await readFile(path);
  • 写入本地文件
    lib/bridge.js:1517
    await writeFile(savedPath, buffer);
  • 写入本地文件
    lib/bridge.js:1578
    await writeFile(savedPath, buffer);
  • 写入本地文件
    lib/bridge.js:1889
    await mkdir(dir, { recursive: true });
  • 读取本地文件
    lib/bridge.js:2276
    if (!existsSync(absolute)) {
  • 写入本地文件
    lib/memory.js:112
    await mkdir(dir, { recursive: true });
  • 写入本地文件
    lib/memory.js:132
    void mkdir(this.opts.root, { recursive: true })
  • 写入本地文件
    lib/memory.js:133
    .then(() => appendFile(join(this.opts.root, '_debug.log'), new Date().toISOString() + ' [' + label + '] ' + raw.slice(0, 800).replace(/ +/g, ' ') + '
  • 写入本地文件
    lib/memory.js:140
    void mkdir(this.opts.root, { recursive: true })
  • 写入本地文件
    lib/memory.js:141
    .then(() => appendFile(join(this.opts.root, '_debug.log'), new Date().toISOString() + ' ' + what + ': ' + reason + '\n', 'utf8'))
  • 读取本地文件
    lib/memory.js:154
    const cached = JSON.parse(await readFile(join(this.dirFor(chatKey), SPACE_FILE), 'utf8'));
  • 读取本地文件
    lib/memory.js:194
    const raw = await readFile(join(this.dirFor(chatKey), SPACE_FILE), 'utf8');
  • 写入本地文件
    lib/memory.js:204
    await writeFile(join(dir, SPACE_FILE), JSON.stringify({ id: spaceId }, null, 2), 'utf8');
  • 读取本地文件
    lib/memory.js:252
    const notes = await readFile(join(this.dirFor(chatKey), NOTES_FILE), 'utf8');
  • 读取本地文件
    lib/memory.js:301
    const existing = await readFile(path, 'utf8');
  • 读取本地文件
    lib/memory.js:366
    const content = await readFile(join(this.dirFor(chatKey), RECENT_FILE), 'utf8');
  • 读取本地文件
    lib/memory.js:389
    const content = await readFile(join(this.dirFor(chatKey), RECENT_FILE), 'utf8');
  • 读取本地文件
    lib/imagecache.js:37
    const dirs = await readdir(this.root, { withFileTypes: true });
  • 读取本地文件
    lib/imagecache.js:44
    const info = await stat(dayPath);
  • 删除本地文件递归
    lib/imagecache.js:46
    await rm(dayPath, { recursive: true, force: true });
  • 读取本地文件
    lib/imagecache.js:63
    const entries = await readdir(join(this.root, dayKey(now)));
  • 读取本地文件
    lib/imagecache.js:81
    const entries = await readdir(dir);
  • 读取本地文件
    lib/imagecache.js:84
    const info = await stat(join(dir, hit));
  • 写入本地文件
    lib/imagecache.js:97
    await mkdir(dir, { recursive: true });
  • 写入本地文件
    lib/imagecache.js:103
    await rename(saved.path, target);
  • 删除本地文件
    lib/imagecache.js:110
    await rm(saved.path, { force: true });
  • 读取本地文件
    lib/imagecache.js:111
    const info = await stat(target);
  • 写入本地文件
    lib/imagecache.js:119
    await appendFile(join(this.root, 'index.jsonl'), JSON.stringify({ t: now, chat: input.chatKey, nick: input.nick.slice(0, 24), file: day + '/' + finalN
  • 写入本地文件
    lib/imagecache.js:134
    await mkdir(this.root, { recursive: true });
  • 写入本地文件
    lib/imagecache.js:135
    await appendFile(join(this.root, 'faces.jsonl'), JSON.stringify({ t: now, chat: chatKey, nick: nick.slice(0, 24), face: face.slice(0, 40) }) + '\n', '
  • 写入本地文件
    lib/imagecache.js:144
    await mkdir(this.root, { recursive: true });
  • 读取本地文件
    lib/meme.js:31
    if (!existsSync(file))
  • 读取本地文件
    lib/meme.js:33
    const raw = JSON.parse(readFileSync(file, 'utf8'));
  • 读取本地文件
    lib/meme.js:59
    if (existsSync(memeRoot) && !dirs.includes(memeRoot))
  • 读取本地文件
    lib/meme.js:62
    if (existsSync(userRoot) && !dirs.includes(userRoot))
  • 读取本地文件
    lib/meme.js:66
    for (const entry of readdirSync(root, { withFileTypes: true })) {
  • 读取本地文件
    lib/meme.js:70
    if (existsSync(dir) && !dirs.includes(dir))
  • 写入本地文件
    lib/media.js:22
    await mkdir(dir, { recursive: true });
  • 写入本地文件
    lib/media.js:28
    await mkdir(dir, { recursive: true });
  • 发起网络请求
    lib/media.js:33
    const response = await fetch(url);
  • 写入本地文件
    lib/media.js:41
    await writeFile(target, buffer);
  • 读取本地文件
    lib/media.js:46
    const buffer = await readFile(path);
  • 读取本地文件
    lib/media.js:59
    return { url: 'base64://' + (await readFile(path)).toString('base64'), bytes, name };
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-tools@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
dsh-napcat 仓库:<https://github.com/wzwei1990/dsh-napcat> 给 DeepSeek Harness 加一个 QQ 通道:通过 NapCat(OneBot 11 协议)把群聊/私聊消息送进 dsh 的智能体,再把回复发回 QQ。 QQ 用户 ──消息──> NapCat ──事件(WS)──> dsh-napcat ──> 每个会话一个 dsh agent │ QQ 用户 <──回复──── NapCat <──动作(WS)────┘ (turn/end 时把助手文本分段发回) 自己维护的一份实现:功能按需长,结构保持薄(连接层 / 会话桥 / 工具 / 配置四块,互不缠绕)。
展开完整文档(README 剩余 1 节)
dsh-napcat

仓库:<https://github.com/wzwei1990/dsh-napcat>

给 DeepSeek Harness 加一个 QQ 通道:通过 NapCat(OneBot 11 协议)把群聊/私聊消息送进 dsh 的智能体,再把回复发回 QQ。

QQ 用户 ──消息──> NapCat ──事件(WS)──> dsh-napcat ──> 每个会话一个 dsh agent │ QQ 用户 <──回复──── NapCat <──动作(WS)────┘ (turn/end 时把助手文本分段发回)

自己维护的一份实现:功能按需长,结构保持薄(连接层 / 会话桥 / 工具 / 配置四块,互不缠绕)。

功能(v0.1)

| 类别 | 支持 |
| 连接 | forward(本插件连 NapCat,NapCat 在别的机器上时用这个)/ reverse(本插件监听、NapCat 拨进来);token 校验;断线指数退避重连 |
| 入站 | 私聊 + 群聊、文本消息;[图片]/[语音]/@某人 等转成占位文本;CQ 字符串兜底解析 |
| 准入 | 私聊(仅管理员 / 任何人 / 关闭)、群聊(任何群 / 白名单 / 关闭)、管理员列表 |
| 群聊 | @机器人 才响应(可关);"回复机器人上一条消息"也算提及 |
| 会话 | 每个 QQ 会话一个稳定 session id,重启自动 resume 续上下文;可指定工作区 / preset / 模型 |
| 出站 | 回合结束后发回复;按 splitMaxChars 自动分段;可选用"引用回复" |
| 工具 | napcat_send_message(主动发消息)、napcat_list_targets(列好友/群)、napcat_api(白名单内的原始 OneBot 动作) |
| 防循环 | 忽略机器人自己发的消息;群消息未 @ 不处理 |

还没做(有意留给后续,见文末 Roadmap):图片/语音/文件入站、语音转写、t2i 文字图卡片、斜杠命令、录制回放。

需要"全家桶"(t2i 卡片、语音转写、20+ 命令、诊断包)可以直接用 dsh-onebot-qq——本项目的协议细节与若干实现思路参考了它和 dsh-im、dsh-qqbot,但代码是独立写的、按自己的需求取舍。

快速开始

1. NapCat 侧(云服务器上)

NapCat 的 WebUI 里开一个 WebSocket 服务端(NapCat 的配置文件里叫 websocketServers / "WebSocket 服务器"),记下:

- 端口(如 3001)
- token(自己设一个强随机串)

如果想反过来让 NapCat 拨过来,就配 "WebSocket 反向":上报地址填 ws://<dsh 所在机器>:8643/,token 与插件里一致。

云服务器记得放行对应端口(安全组 + 容器端口映射),并尽量只对 dsh 所在机器的 IP 开放。

2. 安装插件

从 npm(发布后)
dsh plugin --profile web add dsh-napcat

或从 GitHub(需要仓库里有 prepare 构建脚本)
dsh plugin --profile web add git+https://github.com/wzwei1990/dsh-napcat.git

或本地目录(已构建过)
dsh plugin --profile web add /path/to/dsh-napcat

容器里部署 dsh 的话,在容器里执行(profile 在 $DSH_HOME 卷里,重建镜像不丢):

docker exec -it deepseek-harness dsh plugin --profile web add dsh-napcat
或者把项目拷进容器后:
docker cp ./dsh-napcat deepseek-harness:/tmp/dsh-napcat
docker exec -it deepseek-harness dsh plugin --profile web add /tmp/dsh-napcat

3. 配置

Web UI 设置页里改(推荐),或者给 profile 的 cordis.patch.yml 里 dsh-napcat 行加 config: 覆盖:

- insert:
- id: dsh-napcat
name: 'dsh-napcat'
config:
mode: forward
url: 'ws://81.70.163.182:3001'
accessToken: '你的 token'
adminUsers: ['你的QQ号']
groupPolicy: allowlist
groupAllowFrom: ['你的群号']

最少要配三样:mode+url(或 reverse 的 port)、accessToken、adminUsers(否则私聊没人能触发)。

配置项

| 键 | 默认 | 说明 |
| mode | forward | forward=连 NapCat;reverse=监听等 NapCat 拨入 |
| url | 空 | forward 目标(NapCat 在云上就写云的公网 IP);留空 = 不连接,去设置页填 |
| accessToken | 空 | OneBot token;forward 作为 Bearer 发出,reverse 校验来者 |
| host / port | 127.0.0.1 / 8643 | reverse 监听;NapCat 在别的机器上必须 host: 0.0.0.0 |
| botQQ | 空 | 机器人自己的 QQ;留空自动学习(影响 @ 门控) |
| adminUsers | [] | 管理员 QQ |
| dmPolicy | admin | 私聊:admin 仅管理员 / open 任何人 / disabled |
| allowFrom | [] | dmPolicy=open 时的额外白名单(空=不限) |
| groupPolicy | allowlist | 群聊:open / allowlist / disabled |
| groupAllowFrom | [] | 白名单群号 |
| requireMention | true | 群聊必须 @机器人(或回复它上一条消息) |
| ignoreSelf | true | 忽略机器人自己的消息 |
| replyAsQuote | false | 回复时引用原消息 |
| splitMaxChars | 1200 | 单条消息最大字数,超出自动分段;0=不分段 |
| reconnectMaxAttempts | 0 | forward 连续失败多少次后放弃;0=无限重试(退避封顶 60s,日志限流) |
| workspacePath | 空 | QQ 会话挂载的工作区;空=宿主 cwd |
| agentPreset | 空 | 挂载的 agent preset |
| provider / model | 空 | 覆盖模型(空=宿主默认) |
| logLevel | info | debug / info / warn |

工具

| 工具 | 用途 |
| napcat_send_message | 给 private:<QQ> 或 group:<群号> 主动发文本(超长自动分段,可引用某条消息) |
| napcat_list_targets | 列出好友与群,用来确认 chat_id |
| napcat_api | 直接调 OneBot 动作(白名单:发送类 + 只读类,管理类不允许) |

工作原理(读代码前先看这四句)

1. src/onebot.ts:一条 WS 连接,上行收事件、下行发动作,echo 对请求/回执。forward/reverse 只是"谁连谁"的区别,消息格式完全相同。
2. src/chat.ts:QQ 会话 → private:<QQ> / group:<号> → 稳定的 session id(napcat-private-<QQ>),重启后 create 失败即回退 resume。
3. src/bridge.ts:入站过策略/门控 → agent.followup(createUserMessage(...));订阅 session/event,在 turn/end 把本轮 assistant/message 的文本分段发回。
4. src/tools.ts:给模型三个工具;src/config.ts:schemastery 配置(Web UI 设置页自动出表单)。

开发

npm i # 会按 peerDependencies 拉 @deepseek-ai/dsh-* 的类型
npm run build # tsc → lib/
npm run typecheck
node --test test/ # 纯逻辑单测(8 个用例)

- 宿主 API 面:@deepseek-ai/dsh-agent(ctx.agents.create/resume → Agent.followup)、@deepseek-ai/dsh-session(session/event)、@deepseek-ai/dsh-llm(createUserMessage)、@deepseek-ai/dsh-tools(defineTool)、@deepseek-ai/schemastery(配置)。
- engines.dsh 当前钉在 >=0.2.1-0 <0.3.0-0;升级 dsh 后如果宿主 API 有变,改这里并跑一遍 typecheck。

排错

| 症状 | 原因 / 处理 |
| 连不上 / 一直重连 | forward 模式下 url 不通或 token 不对;看日志 NapCat 连接错误,先在容器里 curl 一下那台机的端口 |
| 日志说 token 不匹配 | NapCat 里配了 token,插件的 accessToken 没填或填错 |
| 群里 @ 了但没反应 | groupPolicy 是 allowlist 但群号没进 groupAllowFrom;或 botQQ/selfId 还没学到(日志会提示) |
| 私聊没人理 | dmPolicy=admin 且 adminUsers 为空/不含你 |
| 机器人自己回自己 | 关掉 ignoreSelf 了;保持默认 true |
| 回复太长被截断 | 调大 splitMaxChars,或确认 NapCat 没开消息长度限制 |
| 重启后上下文断了 | 看日志里是 创建会话失败…改用 resume;session id 会打印出来 |

Roadmap

完整规划(当前能力清单、7 个同类项目横向对比、分阶段任务与验收标准)见 docs/ROADMAP.md。摘要:

| 版本 | 目标 |
| v0.1 | WS 通道 + 3 工具 + 单测 + CI(已发布,待真实 NapCat 联调) |
| v0.2 | 观感与稳定:👀 回执、markdown 清洗、消息去重、限流、过程消息、/help /status /new /stop |
| v0.3 | 多模态与交付:图片/文件入站出站、语音转写、t2i 卡片、引用展开 |
| v0.4 | 群记忆 + 每群 skills + 定时提醒 + 主动发言(默认关) |
| v0.5 | 设置页 UI、/doctor 诊断包、录制回放、HTTP 上报模式 |

不做:多渠道(飞书/微信/钉钉)、多账号矩阵、QQ 官方 Bot API、人格框架 —— 那些是 dsh-im / dsh-im-connect / dsh-onebot 的地盘。

许可证

MIT
预览分享卡片长什么样 ↓wzwei1990/dsh-napcat
分享 · DeepSeek Harness Hub
wzwei1990/dsh-napcat

把 QQ 私聊和群聊消息接入智能体并自动回复

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部