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

聊天桥接入 aitcmhk-web/DSH-bot

DeepSeek Harnessv1.0.8
aitcmhk-web16 天前有提交已提供中文文档扫描:含敏感能力

把 Telegram / 微信变成 DSH 聊天入口的插件。三大功能:Telegram 入口、微信入口、handoff…

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

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

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

状态速览

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

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

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

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

✓npm 包dsh-botplugin @ 1.0.8
✓Node 引擎要求 >=18 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/16 14:07:48

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

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 70 处,展示前 58 条)
  • 写入本地文件
    src/index.js:216
    await writeFile(lockPath, String(process.pid), { flag: 'wx' });
  • 读取本地文件
    src/index.js:224
    const raw = String(await readFile(lockPath, 'utf8').catch(() => '')).trim();
  • 写入本地文件
    src/index.js:232
    await writeFile(lockPath, String(process.pid));
  • 读取本地文件
    src/index.js:254
    const raw = await readFile(lockPath, 'utf8').catch(() => null);
  • 删除本地文件
    src/index.js:257
    await unlink(lockPath);
  • 读取本地文件
    src/index.js:321
    const saved = JSON.parse(readFileSync(pickedKeyFile, 'utf8'));
  • 写入本地文件
    src/index.js:333
    writeFileSync(pickedKeyFile, JSON.stringify({ hostPickedKey: key }, null, 2));
  • 读取本地文件
    src/index.js:609
    memoryScript: config.memoryScript || (existsSync(vendorMemoryScript) ? vendorMemoryScript : null),
  • 读取本地文件
    src/index.js:821
    hardRulesText = readFileSync(HARD_RULES_PATH, 'utf8').trim();
  • 写入本地文件
    src/index.js:1316
    await writeFile(wav, bytes);
  • 删除本地文件
    src/index.js:1318
    await unlink(wav).catch(() => {});
  • 读取本地文件
    src/index.js:1406
    .find((p) => existsSync(p));
  • 执行外部命令来自配置/变量
    src/index.js:1648
    const child = spawn(bashPath, [helper], {
  • 执行外部命令固定命令
    src/index.js:1685
    const child = spawn('bash', [helper], {
  • 写入本地文件
    src/index.js:1849
    appendFileSync(logPath, `\n──── ${new Date().toISOString()} 探测开始 ────\n`);
  • 执行外部命令来自配置/变量
    src/index.js:1852
    const child = spawn(process.execPath, [script], {
  • 发起网络请求
    weixin-login.mjs:79
    const res = await fetch(url, { method: 'POST', headers: authHeaders(token), body: JSON.stringify(body) });
  • 发起网络请求
    weixin-login.mjs:87
    const res = await fetch(url, { method: 'GET', headers: authHeaders(token) });
  • 写入本地文件
    weixin-login.mjs:148
    writeFileSync(ACCOUNT_FILE, JSON.stringify(account, null, 2) + '\n', { mode: 0o600 });
  • 读取本地文件
    weixin-login.mjs:162
    const old = JSON.parse(readFileSync(ACCOUNT_FILE, 'utf8'));
  • 发起网络请求
    src/telegram.js:32
    const response = await fetch(`${this.base}/${method}`, {
  • 发起网络请求
    src/telegram.js:138
    const response = await fetch(url);
  • 读取本地文件
    src/telegram.js:153
    return readFileSync(tmp);
  • 删除本地文件
    src/telegram.js:157
    unlinkSync(tmp);
  • 读取本地文件
    src/weixin.js:99
    if (!accountFile || !existsSync(accountFile)) return false;
  • 读取本地文件
    src/weixin.js:102
    parsed = JSON.parse(readFileSync(accountFile, 'utf8'));
  • 发起网络请求
    src/weixin.js:148
    const res = await fetch(url, {
  • 读取本地文件
    src/memory.js:85
    if (existsSync(cur)) return readFileSync(cur, 'utf8');
  • 读取本地文件
    src/memory.js:85
    if (existsSync(cur)) return readFileSync(cur, 'utf8');
  • 读取本地文件
    src/memory.js:87
    const all = readdirSync(this.ledgerDir)
  • 读取本地文件
    src/memory.js:93
    if (existsSync(p)) return readFileSync(p, 'utf8');
  • 读取本地文件
    src/memory.js:93
    if (existsSync(p)) return readFileSync(p, 'utf8');
  • 读取本地文件
    src/memory.js:116
    if (!this.memoryScript || !existsSync(this.memoryScript)) return;
  • 执行外部命令来自配置/变量
    src/memory.js:117
    const child = spawn(
  • 写入本地文件
    src/memory.js:249
    mkdirSync(handoffDir, { recursive: true });
  • 写入本地文件
    src/memory.js:297
    writeFileSync(file, lines);
  • 读取本地文件
    src/web-patch.js:138
    if (!existsSync(p)) return null;
  • 读取本地文件
    src/web-patch.js:139
    const doc = parseYaml(readFileSync(p, 'utf8'));
  • 读取本地文件
    src/web-patch.js:164
    if (!existsSync(p)) return null;
  • 读取本地文件
    src/web-patch.js:165
    const doc = parseYaml(readFileSync(p, 'utf8'));
  • 执行外部命令固定命令
    src/asr.js:80
    const out = execFileSync('which', [name], { timeout: 3000 });
  • 执行外部命令来自配置/变量
    src/asr.js:139
    execFileSync(bin, ['-c', 'import funasr'], { timeout: 60_000, stdio: 'ignore' });
  • 执行外部命令固定命令
    src/asr.js:196
    const out = execFileSync('/usr/bin/vm_stat', [], { timeout: 5000 }).toString();
  • 执行外部命令来自配置/变量
    src/asr.js:251
    const child = spawn(
  • 执行外部命令来自配置/变量
    src/asr.js:320
    return execFileSync(
  • 执行外部命令来自配置/变量
    src/asr.js:359
    const out = execFileSync(bin, ['-c', script, wavPath], {
  • 执行外部命令固定命令
    qr-terminal.mjs:335
    const res = spawnSync('osascript', args, { encoding: 'utf8', timeout: 15000 });
  • 读取本地文件
    qr-terminal.mjs:337
    const bmp = readFileSync(out);
  • 删除本地文件
    qr-terminal.mjs:344
    try { unlinkSync(out); } catch {}
  • 执行外部命令固定命令
    qr-terminal.mjs:350
    const qrRes = spawnSync('qrencode', ['-l', 'M', '-s', '1', '-m', '2', '-o', '-', text], {
  • 删除本地文件递归
    test-route-display.mjs:403
    rmSync(WORKDIR, { recursive: true, force: true });
  • 写入本地文件
    test-sticky-pick.mjs:40
    writeFileSync(STATE_FILE, JSON.stringify({ hostPickedKey: PICKED }, null, 2));
  • 读取本地文件
    test-sticky-pick.mjs:44
    return JSON.parse(readFileSync(STATE_FILE, 'utf8'));
  • 写入本地文件
    test-sticky-pick.mjs:70
    mkdirSync(dir, { recursive: true });
  • 写入本地文件
    test-sticky-pick.mjs:71
    writeFileSync(join(dir, 'cordis.patch.yml'), renderPatch(providers));
  • 执行外部命令来自配置/变量
    test-sticky-pick.mjs:78
    const r = spawnSync(process.execPath, args, {
  • 删除本地文件递归
    test-sticky-pick.mjs:82
    rmSync(home, { recursive: true, force: true });
  • 删除本地文件递归
    test-sticky-pick.mjs:201
    rmSync(WORKDIR, { recursive: true, force: true });
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

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

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

功能亮点

  • 绑定机器人到工作区
  • Telegram微信接入
  • 会话接力续接

README

由 DeepSeek 最新模型翻译生成
dsh-botplugin 把 Telegram / 微信变成 DSH 聊天入口的插件。三大功能:Telegram 入口、微信入口、handoff 记忆接续,外加语音转文字。 🔰 第一次接触、想知道「这东西到底能干什么」 → 先看 功能说明.txt(大白话版,不用懂技术)。 装的时候怎么填、怎么启动 → 看 使用说明.txt。下面这份是给要自己动手的人的完整文档。 环境要求 - Node ≥ 18 - 机器上装好 DSH(有 dsh 命令;没装的话先跑下面第 0 步) - 一个 Telegram bot token(在 Telegram 里找 @BotFather 发送 /newbot 新建,不要和其他 bot 共用) 安装分成两件事,一个脚本管一头,互不越界: setupdsh = 升级(Git、Node、DSH 本体,外加已经装过机器人的工作区里的插件:装 + 升级); setupbot = 建/选工作区、首次装插件、绑 TG / 微信、生成工作区里那 5 个文件(英文名,双击或终端里跑都行)。 机器上没有 dsh 时 setupbot 会自己把 setupdsh 跑一遍,所以顺序不用记。
展开完整文档(README 剩余 1 节)
dsh-botplugin

把 Telegram / 微信变成 DSH 聊天入口的插件。三大功能:Telegram 入口、微信入口、handoff 记忆接续,外加语音转文字。

🔰 第一次接触、想知道「这东西到底能干什么」 → 先看 功能说明.txt(大白话版,不用懂技术)。
装的时候怎么填、怎么启动 → 看 使用说明.txt。下面这份是给要自己动手的人的完整文档。

环境要求

- Node ≥ 18
- 机器上装好 DSH(有 dsh 命令;没装的话先跑下面第 0 步)
- 一个 Telegram bot token(在 Telegram 里找 @BotFather 发送 /newbot 新建,不要和其他 bot 共用)

安装分成两件事,一个脚本管一头,互不越界:
setupdsh = 升级(Git、Node、DSH 本体,外加已经装过机器人的工作区里的插件:装 + 升级);
setupbot = 建/选工作区、首次装插件、绑 TG / 微信、生成工作区里那 5 个文件(英文名,双击或终端里跑都行)。
机器上没有 dsh 时 setupbot 会自己把 setupdsh 跑一遍,所以顺序不用记。

安装方式一:在线安装(两条命令,推荐)

0. 先装/升级本体(Git、Node、DSH 一起办,可重复跑):

curl -fsSL https://raw.githubusercontent.com/aitcmhk-web/DSH-bot/main/setupdsh.sh | sh

1. 再装机器人 —— 把下面这条整段贴进终端,回车:

curl -fsSL https://raw.githubusercontent.com/aitcmhk-web/DSH-bot/main/setupbot.sh | sh

它自己列出/新建工作区、自己把插件装好,然后只问你三件事:工作区叫什么(直接回车就叫 mybot)、Telegram token(@BotFather 那串)、微信怎么绑(可选)。
每样都是「输个编号」或「粘一下回车」,不用你编辑任何文件。

2. 跑完它会把两个词装进 PATH —— 以后升级(本体 + 插件)敲 setupdsh;重新绑 TG、重新绑微信敲 setupbot:

setupdsh
setupbot

3. 启动:照着它最后打出来的那行,或者跑 ~/DSH/<工作区名>/start.command (同目录里另有 stop.command、restart.command、install-autostart.command、uninstall-autostart.command)。

那五个文件名字一律英文:有桌面双击,没桌面(云主机 / 只有终端)就
cd ~/DSH/<工作区名> && ./start.command。中文文件名在纯终端里得切输入法,太别扭。

开发者:本地安装(用你手上这份源码)

已经有一份源码(比如你自己 clone 下来的、或者要改着调试的),就用 file: 指向那个目录:

dsh plugin --profile mybot add file:/绝对路径/dsh-botplugin

例如源码在 ~/DSH/BOT/botplugin:

dsh plugin --profile mybot add file:$HOME/DSH/BOT/botplugin

⚠️ file: 后面不能写 ~ —— 它不会展开波浪号,会当成字面路径找不到。用 $HOME/ 或完整绝对路径。

用 file: 装出来的是软链 —— 改完源码不用重装,重启 profile 就生效。
调试的时候用这个;平时用上面的 git 方式。两种选一种,别都装(会装出两份同名插件,加载哪份不好说)。

⚠️ 路径必须是绝对路径,且指向含 package.json 的那一层(也就是仓库根),不要指到 src/ 或上一层。

安装方式二:下载安装包(不想敲命令的)

1. 下载安装包:dsh-mybot-安装包.zip(在本页文件列表里,点它再点 Download / Download raw)。
2. 解压,双击里面的 安装-mybot.command。
3. 接下来和在线方式完全一样:问你工作区名字(直接回车就叫 mybot)→ 粘 token → 微信要不要绑。
窗口最后会停住等你按回车,结果不会一闪而过。
4. 以后每次使用:跑 ~/DSH/<工作区名>/start.command(stop.command / restart.command / install-autostart.command / uninstall-autostart.command 是同一个目录里的另外四个文件)。
想重新绑 TG / 微信:把 安装-mybot.command 再双击一次(或在终端敲 setupbot)。
想升级(Git / Node / DSH 本体 / 已经装过机器人的工作区里的插件):在终端敲 setupdsh(安装包里也带了这个脚本)。

两种方式装出来的是同一个插件,跑的是同一个 setupbot.sh,选一种就行。
安装包方式适合完全不想碰命令行的人;在线方式第一次要粘两条命令,之后也只剩 setupdsh / setupbot 两个词。

怎么确认装对了

脚本跑到最后会打「✅ 复核通过:配置已经生效」—— 看到这句就是装对了,它紧接着会给你启动命令。

没看到这句、或者它报「插件没装上」= 没装成,插件不会生效(而且不报错,只会静默什么都没发生)。

配置项速查

| 配置 | 说明 |
| telegramToken / telegramApiRoot | TG 必填;apiRoot 指向代理时改 |
| telegramAllowedUsers | 允许的 TG 用户 ID;空 = 首个发消息者认领为主人 |
| weixinToken / weixinApiRoot / weixinAccountFile | 微信入口(通常用扫码登录,不用填 token) |
| routes + defaultRouteKey | 手工指定模型档位;留空 = 自动跟随 web 端「设置 → 模型」 |
| cwd | 模型的工作目录 |
| memoryDir / memoryScript | handoff 记忆接续:默认开启(<工作目录>/memory + 插件自带的记账程序),不用配;要关闭把 memoryDir 设成空串 |
| restartCommand | 重启用的启动器 .command 路径;不填默认找工作目录里的 start.command(兼容老的 启动-<工作区名>.command / 启动-mybot.command) |
| turnTimeoutMs | 单轮超时,默认 30 分钟 |
| asrBackend / asrWhisperBin / asrPythonBin | 语音转文字。默认 sensevoice(阿里 FunASR,中文准),不填路径就自动找 /opt/homebrew/bin/python3.11;本机没装时,安装收尾和发语音都会回一条可粘贴的安装命令(⛔ 不自动装)。whisper 中文差,只有显式填 asrBackend: whisper 才用 |

远程审批(手机点按钮,不用守着电脑)

DSH 的审批服务用 waterfall 广播 approval/request,插件把它桥接到 Telegram——推一张和 web 端审批面板同口径的卡片(等待审批 / 已允许 / 已拒绝 / 已取消 / 已超时
+ 命令、工作目录、原因),下面挂两个内联按钮【✅ 允许一次】【❌ 拒绝】。
点完卡片收成终态并去掉按钮。

桥是只读旁路:卡片渲染失败、编辑失败、按钮超时,统统只记日志,绝不影响审批本身的结果(该通过的照常通过)。
行动端入口在 src/approval-bridge.js,默认超时 10 分钟。

多端互通(TG ⇄ 微信,同一个大脑)

src/hub.js 是所有端点的唯一交汇点,纯逻辑、零依赖。两条规则,都是「同步到所有」:

| 方向 | 行为 |
| 端点到 hub | 同步给 ① DSH ② 其他所有端点 |
| DSH 到 hub | 同步发到所有端点 |

新增端点 = 加一个数组项(O(n)),不是两两镜像(O(n²))。
微信消息并入主人的 TG 会话,所以两边聊的是同一段上下文,在微信里 /new、/model 操作的是同一个会话。

⛔ 这里刻意不做去重/合并:TG 和微信各进来一条就是两次真实输入,进来几条算几条。

指令

/whoami /status /model /new(新会话) /restart(重启进程,先留档) /help

/restart 与老 bot 同路:先把进展写进 handoff,再由进程外的接力脚本延迟几秒杀掉宿主并重新拉起(有 start.command(兼容老的 启动-<工作区名>.command / 启动-mybot.command)就重开终端窗口;没有就按原始命令行后台拉起)。两者都没有时退化为只重开会话。重启完成后发条消息,新会话自动带上刚才的记忆。

记忆(流水账 + handoff)

默认开启,什么都不用配:

- 流水账:每轮对话原文追加到 <工作目录>/memory/conversation-cache/raw/ledger/,按月一个文件,只增不删。
- handoff:/new、切换模型(本次会话满 20 条才写,调试期反复切不会覆盖)、/restart(无条件)和启动补写时,把最近 20 条进展落盘到 <工作目录>/memory/handoff/handoff.md。
- 冷启动注入:新会话的第一条消息会自动带上最近一次 handoff,模型直接接着上段干,不用你复述上文。
- 记账程序随插件自带(vendor/conversation-cache/),不依赖机器上是否装过 DSH 的其它项目。
- 想换位置或关闭:配置里写 memoryDir(自定路径;空串 = 关闭)、memoryScript(自定程序路径)。

微信入口(扫码绑定)

1. 运行(本目录下):

node weixin-login.mjs --out 你的账号文件路径

2. 手机微信扫终端二维码(约 2 分钟过期,自动刷新;备用链接发到手机微信里点开)。
3. 凭据写入账号文件(0600)→ 在配置里加 weixinAccountFile: 那个路径 → 重启即启用。
4. 扫码的这个微信就是主人,只有它能和 bot 对话。

⚠️ 三条硬注意事项

1. 一个 token 只能一个进程。两个进程抢同一个 token,先启动的会 409 冲突。
2. Telegram 游标在内存里:重启后从当前时刻开始拉消息,不补发离线期间的旧消息。
3. 409 冲突时插件只停自己的轮询并打日志,不会拖垮宿主;原因要去启动日志里看(通常是同一个 token 另有进程在用)。

已知限制

- 微信扫码工具用 macOS 原生 CoreImage 渲染二维码(零依赖),Windows/Linux 机器上会退化为只打印链接。
- Telegram 限流(429)不丢答案:收尾交付会照 Telegram 给的 retry_after 排队重发(单次最多等 90s、一轮最多 3 分钟);编辑占位消息与整条重发都发不出去时,整篇回答落盘到 DSH_BOT_DIR/未送达/(可用 DSH_BOTPLUGIN_UNDELIVERED_DIR 指定别的目录),同时把占位消息改成「❌ 回答未送达…已存到 <路径>」——旧版遇限流会留下永远的「⏳ 正在处理…」并丢掉答案。
等待总预算可用 DSH_BOTPLUGIN_RATE_LIMIT_BUDGET_MS 调整(默认 180000)。
- 进度消息只显示「正在做什么」(2026-10-18 口径,同日修订):正文里带 [进度] … 标记的行,加工具的中文动作标签,标签后面接具体在干什么——如「🏃 跑命令:grep -rn notes src/index.js」「🛠 改文件:服务.mjs」(只留文件名,不带目录)。模型思考(reasoning 块)一律不上屏;口令类字面量自动打码(PGPASSWORD=、Bearer )。抠不出细节的工具只留标签、不编占位词;认不出的工具原样给个 🔧 名字。
工具标签可用 DSH_BOTPLUGIN_PROGRESS_TOOLS=0 关掉,只留进度行。
- 进度占位消息每 4s 编辑一次(旧版 2s),上屏最近 3 条动态;长回合里编辑太频会撞限流。

许可

MIT License(全文见 LICENSE):可以自由使用、修改、再发布,保留版权声明即可;软件不提供任何担保。
预览分享卡片长什么样 ↓aitcmhk-web/DSH-bot
分享 · DeepSeek Harness Hub
aitcmhk-web/DSH-bot

把 Telegram / 微信变成 DSH 聊天入口的插件。三大功能:Telegram 入口、微信入口、handoff…

这是你的仓库?认领条目

回到顶部