Back to home

21hbguo

dsh-feishu-bridge-plugin

飞书机器人 ↔ DSH 对话桥:DSH 进程内 Cordis 插件,流式卡片 / 问答卡片 / 审批卡片 / 斜杠命令

Stars
1
Language
TypeScript
Created
Aug 15, 2026
Updated
Aug 15, 2026

Introduction

@dsh-external/dsh-feishu-bridge

飞书机器人 ↔ DSH 对话桥:把 DeepSeek Harness(DSH)装进飞书,聊天即算力。

License Platform Version Language Messaging

DSH(DeepSeek Harness)的进程内 Cordis 插件:飞书 IM 收发消息,流式卡片实时呈现 DSH 的思考与工具调用进度;问答卡片、工具审批卡片直接在飞书里点按完成;斜杠命令全量遥控会话——无需打开 Web GUI,也能完整使用 DSH。

✨ 功能特性

  • 🚀 飞书 IM ↔ DSH 对话桥:基于 WebSocket 长连接收发消息,私聊即聊即答,群聊 @ 机器人触发。
  • 流式卡片:DSH 输出逐字实时渲染到飞书卡片,思考过程「看得见」。
  • 🔧 工具调用进度:agent 调用工具时卡片实时显示「🔧 正在调用工具:xxx…」,多步回合不再干等。
  • 🎯 问答卡片:agent 的 ask_user_question 以交互卡片呈现——按钮单选、勾选多选、聊天自由文本作答,点按即答。
  • 🛡️ 工具审批卡片:agent 请求工具时推送「✅ 允许一次 / 🚫 拒绝」卡片,决策在飞书内完成;10 分钟未响应自动过期撤卡。
  • 扫码一键配置:装好插件后发 /setup(飞书内)或调用 feishu_setup 工具(DSH 内),扫码即自动完成「创建应用 + 获取凭据 + 重连飞书」,免去手动开放平台配置。
  • 🧠 思考强度调节/effort 查看当前模型支持的思考档位,/effort <档位> 切换,下一回合生效、偏好持久化。
  • ⌨️ 斜杠命令:17 个命令覆盖模型切换、思考强度、工作区管理、会话恢复、流式开关、免审批模式、扫码配置等(见下方命令表)。
  • 🔀 每会话串行队列 + 插队:同一聊天内消息按序处理;新消息可打断运行中的慢回合(阈值可配),也可强制排队。
  • 🐕 看门狗:单回合超过时限自动取消该回合并回复错误卡片,绝不退出进程
  • 📦 消息突发批处理:短窗口内连发的普通消息合并为一次进入 DSH,省调用、省 token。
  • 💾 状态持久化:会话代次、工作区绑定等持久化到本地状态文件,重启后记忆保留。
  • 🔁 断线自愈:长连接异常自动退避重连;重连后向所有已知会话广播恢复通知。
  • 🧠 会话记忆管理/reset /new 开启新的记忆代次,/resume 带摘要恢复历史会话,/workspace 绑定工作区。
  • 📊 用量透明:回复卡片底部显示本会话累计 token 用量(输入 / 输出,K/M 格式化)。

📐 架构

本插件是运行在 DSH 进程内的 Cordis 插件(inject: ['agents']),通过 ctx 服务直调驱动 DSH:

  • 消息注入走 agents 服务的 create / resume / followup / steer / cancel,全程进程内直调,不另起进程、不走网络;
  • 审批卡片与问答卡片订阅宿主的进程内事件帧,经 approval / questions 服务交互,点按结果直接提交回宿主;
  • 不注册任何 provider / answerer,不与宿主自带实现冲突,卸载即净。
flowchart LR
    subgraph Feishu["飞书开放平台"]
        IM["IM 消息 · 卡片按钮回调"]
        CARD["流式卡片 · 问答卡片 · 审批卡片"]
    end

    subgraph Plugin["@dsh-external/dsh-feishu-bridge(DSH 进程内 Cordis 插件)"]
        CH["飞书 Channel(src/lark.ts)<br/>WebSocket 长连接 · 去重 · 安全策略 · 流式节流"]
        CORE["核心运行时(src/index.ts)<br/>串行队列 · 插队 · 看门狗 · 突发批处理"]
        APPC["审批卡片(src/approval.ts)"]
        QSC["问答卡片(src/questions.ts)"]
        ST["状态持久化(src/state.ts)"]
    end

    subgraph Host["DSH 宿主"]
        AGS["agents 服务"]
        APRS["approval 服务"]
        QSS["questions 服务"]
        AGT["DSH Agent 会话"]
    end

    IM -->|"消息 / @提及 / 回调"| CH
    CH --> CORE
    CORE -->|"followup / steer / cancel"| AGS
    AGS --> AGT
    AGT -->|"session/event 事件流"| CORE
    CORE -->|"流式增量 / 状态更新"| CH
    CH -->|"卡片推送与更新"| CARD
    AGT -->|"工具调用审批"| APRS
    APRS -->|"审批事件帧"| APPC
    APPC -->|"允许一次 / 拒绝卡片"| CH
    APPC -->|"决定(进程内提交)"| APRS
    AGT -->|"ask_user_question"| QSS
    QSS -->|"提问事件帧"| QSC
    QSC -->|"问答卡片"| CH
    QSC -->|"回答(进程内提交)"| QSS
    CORE <-->|"持久化"| ST

模块一览:

模块职责
src/index.ts插件入口与核心运行时:消息入口、每 chat 串行队列与插队、看门狗、流式 / 非流式回复管线、生命周期
src/lark.ts飞书 Channel:WebSocket 长连接、消息去重、聊天队列、陈旧消息窗口、流式卡片节流
src/commands.ts斜杠命令表与分发
src/approval.ts工具审批卡片:订阅审批事件、发卡、按钮回调路由、过期回收、YOLO 自动放行
src/questions.ts问答卡片:单选 / 多选 / 自由文本、答案提交、过期回收
src/batching.ts消息突发批处理:滑动窗口合并普通消息
src/state.ts状态持久化:会话代次 / 会话列表 / 工作区绑定 / 会话覆盖
src/text.ts文本处理:@ 提及剥离、超长截断、token 数量格式化

🚀 快速开始

从零到用上大约 10 分钟:把插件装进 DSH(方式 A / B / C 任选),扫码一键配置(或手动)拿到应用与凭据,最后在飞书里与机器人对话。

前提

  • 已部署 DSH(DeepSeek Harness) 环境。
  • 本插件 peerDependencies 依赖 DSH 内部包(@deepseek-ai/dsh-llm@deepseek-ai/dsh-tools,不发布于公开 npm)以及 cordisschemastery必须运行在 DSH 进程内,无法独立安装或独立部署。
  • 一个可登录飞书开放平台的账号。

第一步:获取飞书应用

本插件使用长连接模式与飞书通信:插件主动发起 WebSocket 连接收发消息,不需要公网回调地址,也不需要配置任何 webhook。飞书应用有两种获取方式,推荐扫码一键配置。

✅ 首选:扫码一键配置

装好插件后(方式 A / B / C 任一),无需手动去开放平台创建应用。首次配置(插件还没连上飞书)只能走 DSH 入口——此时机器人无法收发消息,飞书里的 /setup 发不出去;DSH 入口不依赖飞书连接,是唯一的从零路径:

  1. 发起配置(二选一):
    • DSH 内(首次配置必选):在 DSH 的会话里对 agent 说「配置飞书」或「生成飞书授权链接」,agent 会自动调用 feishu_setup 工具,返回一个授权链接(含过期时间,如 3600 秒)。把链接复制到浏览器打开,或用飞书扫码,授权完成后工具自动写入凭据并重连,直接在会话里看到结果——全程无需离开 DSH;
    • 飞书内:给机器人发 /setup(需已有凭据连接、桥正常运行),返回同样的授权链接。适合已连接后换应用 / 刷新凭据
  2. 打开链接,用飞书 App 扫码确认。应用名预填为「{user} 的 DSH 飞书桥」,权限预填 im:message / im:message:send_as_bot、消息事件与卡片回调。
  3. 授权完成后插件自动获取 App ID / Secret,写入 ~/.dsh/dsh-feishu-bridge/credentials.json(权限 0600),并自动重连飞书(等价热重载:内存态偏好重置,持久化状态保留),无需重启 DSH。

⚠️ 平台灰度可能忽略预填的权限:若扫码授权成功但机器人不回复,按下方排错表到开发者后台补开权限并重新发布版本。 ⚠️ 每次 /setup / feishu_setup 都会创建新应用(createOnly 设计),重复执行会累积多个应用;介意可在开发者后台删除旧应用。

进阶:手动创建飞书应用(可选)

不想扫码时,也可以手动把应用信息准备好:

  1. 打开飞书开放平台 → 进入「开发者后台」→ 点击创建企业自建应用,填写名称与描述后创建。
  2. 在应用详情页的「添加应用能力」中启用机器人
  3. 在「权限管理」中搜索并开通以下两个权限:
    • im:message —— 读取用户发给机器人的消息(含群聊 @ 消息);
    • im:message:send_as_bot —— 以机器人身份发送消息。
  4. 在「可用范围」中添加需要使用机器人的成员与群组(默认可能为空,不加则任何人都用不了)。
  5. 在「版本管理与发布」中创建版本并发布,等待审核通过后应用才真正生效。⚠️ 大量「机器人不回复」的案例都是只保存了配置、忘了发布版本。
  6. 在「凭证与基础信息」中记下 App ID(形如 cli_xxxxxxxx)与 App Secret,第三步会用到。

第二步:安装插件(三种方式任选其一)

方式 A:标准装配(无注入器);方式 B:注入器一键安装(已有 dsh-super-injector);方式 C:命令行一键安装(推荐给熟悉命令行的用户)。三种方式任选其一即可。

方式 C:命令行一键安装(推荐给熟悉命令行的用户)

支持 Linux / macOS(bash)。Windows 用户请使用下方「只下载不安装」命令拿到 tgz 后,按方式 A 手动安装。

一条命令自动完成「下载最新 Release → 解压到 ~/dsh-plugins/dsh-feishu-bridge → 装配进 web profile → 建软链」:

curl -fsSL https://raw.githubusercontent.com/21hbguo/dsh-feishu-bridge-plugin/main/scripts/install.sh | bash

或分步执行(建议先下载查看脚本内容再运行):

curl -fsSL -o install.sh https://raw.githubusercontent.com/21hbguo/dsh-feishu-bridge-plugin/main/scripts/install.sh
bash install.sh

默认装配到 web profile;可用参数自定义,例如:

bash install.sh --profile my-profile --dir ~/dsh-plugins/dsh-feishu-bridge
bash install.sh --help    # 查看全部参数与示例

只下载不安装(把最新 tgz 下载到当前目录;资产名以 Release 页为准):

curl -fsSL -O https://github.com/21hbguo/dsh-feishu-bridge-plugin/releases/latest/download/dsh-external-dsh-feishu-bridge-0.0.2.tgz

脚本自动完成下载 / 解压 / 装配 / 建软链,完成后完全重启 DSH 即生效;想手动控制每一步,参考方式 A。

方式 A:标准装配(无注入器,推荐)

不需要任何注入器或开发工具,手动装配 4 步:

  1. 下载并解压:在 GitHub Releases 下载最新 .tgz 包(如 dsh-external-dsh-feishu-bridge-0.0.2.tgz,资产名以 Release 页为准),解压到固定目录(示例 ~/dsh-plugins/dsh-feishu-bridge):

    mkdir -p ~/dsh-plugins/dsh-feishu-bridge
    tar -xzf dsh-external-dsh-feishu-bridge-0.0.2.tgz -C ~/dsh-plugins/dsh-feishu-bridge --strip-components=1
    
  2. 编辑 profile 配置:打开 ~/.dsh/profiles/<profile>/package.json<profile> 为你的 profile 名,如 web),把插件加入依赖与装配清单:

    {
      "name": "dsh-profile-web",
      "dependencies": {
        "@dsh-external/dsh-feishu-bridge": "link:/home/xxx/dsh-plugins/dsh-feishu-bridge"
      },
      "dsh": {
        "profile": {
          "bundles": ["@deepseek-ai/dsh-base", "@dsh-external/dsh-feishu-bridge"]
        }
      }
    }
    

    link: 后面的路径替换为第 1 步的解压目录。

  3. 建立 node_modules 软链:在 profile 的 node_modules/@dsh-external/ 下创建指向解压目录的链接(目录不存在先创建):

    # Linux / macOS
    mkdir -p ~/.dsh/profiles/<profile>/node_modules/@dsh-external
    ln -s ~/dsh-plugins/dsh-feishu-bridge ~/.dsh/profiles/<profile>/node_modules/@dsh-external/dsh-feishu-bridge
    
    # Windows(PowerShell)
    New-Item -ItemType Directory -Force "$env:USERPROFILE\.dsh\profiles\<profile>\node_modules\@dsh-external"
    New-Item -ItemType Junction -Path "$env:USERPROFILE\.dsh\profiles\<profile>\node_modules\@dsh-external\dsh-feishu-bridge" -Target "$env:USERPROFILE\dsh-plugins\dsh-feishu-bridge"
    
    # Windows(cmd,管理员权限)
    mkdir "%USERPROFILE%\.dsh\profiles\<profile>\node_modules\@dsh-external"
    mklink /D "%USERPROFILE%\.dsh\profiles\<profile>\node_modules\@dsh-external\dsh-feishu-bridge" "%USERPROFILE%\dsh-plugins\dsh-feishu-bridge"
    
  4. 重启 DSH:完全退出并重新启动 DSH(不是刷新页面),插件随 profile 装配自动加载。

已安装 dsh-super-injector 注入器的用户请直接用方式 B,一行命令完成装配与软链,无需手动编辑。

方式 B:注入器一键安装(已有 dsh-super-injector)

  1. GitHub Releases 下载最新 .tgz 包,解压得到包目录(方法同方式 A 第 1 步)。
  2. 在 DSH 管理端对包目录使用注入器:
    • dev_install_package <包目录> —— 热装配并写入装配清单,重启后依然生效(推荐);
    • dev_inject_plugin <包目录> —— 运行时注入,免重启(重启后失效)。

可选:从源码构建(进阶)。git clone https://github.com/21hbguo/dsh-feishu-bridge-plugin 后,需在 DSH checkout 环境下执行 DSH_CHECKOUT=<dsh-checkout-路径> bash scripts/build.sh(产物为 lib/),随后按方式 A 或方式 B 安装。构建依赖 DSH 内部包,脱离 DSH checkout 无法独立构建,绝大多数用户无需走这条路。

第三步:配置凭据(二选一)

两种方式二选一:一键扫码(推荐) 见第一步——扫码完成后插件自动把凭据写入 ~/.dsh/dsh-feishu-bridge/credentials.json(权限 0600),无需手动配置;或手动用环境变量 / 插件 Config 配置:

方式 1:环境变量 —— 在启动 DSH 的终端(或启动脚本)中导出:

export FEISHU_APP_ID="cli_xxxxxxxxxxxxxxxx"
export FEISHU_APP_SECRET="xxxxxxxxxxxxxxxx"

方式 2:插件 Config —— 在 DSH 插件配置中填写:

字段说明
feishuAppId飞书应用 App ID(未填时回退 FEISHU_APP_ID,再回退扫码凭据文件)
feishuAppSecret飞书应用 App Secret(未填时回退 FEISHU_APP_SECRET,再回退扫码凭据文件)

凭据优先级:Config > 环境变量 > 扫码凭据文件;三种来源都缺失时插件启动才报缺凭据错误。

第四步:验证

  1. 在飞书里搜索机器人(应用名称),私聊发送一条消息,如 你好
  2. 机器人应回复流式卡片:DSH 的思考与工具调用进度逐字实时渲染,回复底部显示本会话 token 用量,即链路正常。
  3. 群聊里测试:必须 @机器人 才会触发回复(私聊无需 @)。

常见问题排错表

现象原因解决
机器人完全不回复应用未发布版本(只保存了配置)开放平台 → 版本管理与发布 → 创建版本并发布,等待审核通过
机器人完全不回复当前用户/群不在应用可用范围开放平台 → 可用范围 → 添加测试成员与群组
报错 403 / 权限不足未开通 im:message / im:message:send_as_bot「权限管理」开通后需重新创建版本并发布再试
群聊不回复消息没有 @ 机器人群聊必须 @ 机器人才会进入处理,私聊无需 @
启动报缺凭据App ID / App Secret 未配置或填错核对环境变量 / Config 与开放平台「凭证与基础信息」是否一致
插件未生效(无日志、无机器人)profile 装配 / 软链 / 重启未完成核对 dependenciesbundles 是否包含插件、node_modules 软链是否指向解压目录、是否完全重启 DSH
回复不是逐字刷新流式开关被关闭私聊发送 /stream on 开启流式回复
扫码授权成功但机器人不回复平台灰度未预填权限到开发者后台补开机器人能力与 im:message / im:message:send_as_bot 权限,并重新创建版本并发布
/setup 多次执行累积多个应用属预期行为:每次扫码都创建新应用(createOnly 设计)介意可在开发者后台删除旧应用

⚙️ 配置项

字段类型默认值说明
feishuAppIdstring''(回退 FEISHU_APP_ID飞书应用 ID(未填时回退 FEISHU_APP_ID,再回退扫码凭据文件)
feishuAppSecretstring''(回退 FEISHU_APP_SECRET飞书应用密钥(未填时回退 FEISHU_APP_SECRET,再回退扫码凭据文件)
streambooleantrue流式卡片总开关(每个会话可用 /stream 覆盖)
maxTurnMsnumber600000看门狗时长:单回合超过该毫秒数则取消该回合,并回复错误卡片
interruptAfterMsnumber0插队阈值:运行中回合超过该毫秒数,新消息打断它优先处理(0 = 立即打断)
streamThrottleMsnumber40流式卡片推送节流间隔(毫秒)
streamThrottleCharsnumber12流式卡片推送触发字符数
maxReplyCharsnumber4000非流式回复截断阈值(字符)
batchWindowMsnumber800消息突发批处理窗口(毫秒):窗口内同一聊天的连续普通消息合并为一条进入 DSH;0 = 禁用

⌨️ 斜杠命令

命令参数说明
/help列出所有可用命令
/ping连通性自检(回复 pong 🏓
/status查看桥与当前会话状态:机器人、模型、会话 ID、工作区、流式开关、队列深度、运行时长、最近回答摘要
/reset清空本会话记忆,开启新的 DSH 会话
/new/reset,开启新会话
/workspace[序号 | 路径]列出 / 切换工作区;/workspace 0 解除绑定(未分组,宿主默认 cwd);<路径> 为已存在目录时自动创建并绑定;切换即开新会话(记忆清空)
/model[序号]列出可用模型,或 /model <序号> 切换(下一回合生效,记忆保留)
/effort[档位]查看/切换思考强度:/effort 或 /effort <档位>
/streamon | off本会话流式回复开关(无参查看当前状态)
/cancel取消当前运行中的回合(回合卡住时自救)
/resume[序号]列出最近 10 个会话(带摘要)或 /resume <序号> 切换恢复记忆;支持恢复同一工作区内 web 端创建的会话,已归档自动隐藏
/restart重连飞书长连接(不退出进程)
/setup扫码授权飞书应用(生成授权链接,打开后扫码即完成配置)
/yolo[off]本会话免审批模式:权限预设切换为 danger-full-access,工具调用自动放行;/yolo off 恢复 workspace-write。内存态,重启自动关闭
/squeeze<内容>以「强制排队」模式处理内容(等待当前回合完成后处理)
/steer<内容>以「强制插队」模式处理内容(打断当前回合优先处理)
/ai<内容>显式把内容发给 AI(以 / 开头的内容会被当作命令,需要发送给 AI 时请使用它)

普通消息(非 / 开头)直接进入对话管线;同一聊天内连续发送会先经过突发批处理窗口,再合并进入 DSH。

🔐 安全说明

  • 凭据不硬编码:App ID / App Secret 通过环境变量、插件 Config 或扫码一键配置写入的凭据文件注入(~/.dsh/dsh-feishu-bridge/credentials.json,权限 0600),仓库与源码中不含任何凭据;日志只记录机器人名称与消息摘要,不记录密钥。
  • 无遥测、无外部上报:插件只在 DSH 进程内与飞书开放平台通信,不向任何第三方发送数据。
  • 运行时数据本地存储open_id、chat id、会话代次 / 工作区绑定 / 思考强度偏好等仅写入本地状态文件(~/.dsh/dsh-feishu-bridge/state.json),不发送到任何远端。
  • 权限可控/yolo 免审批模式需用户显式开启,且为内存态——重启自动关闭,不会悄悄长驻高权限。

❓ 常见问题

Q1:为什么不能独立 npm install / 独立部署?

本插件的 peer 依赖包含 DSH 内部包 @deepseek-ai/dsh-llm@deepseek-ai/dsh-tools,它们不发布到公开 npm;同时插件运行时依赖 DSH 进程内的 agents / approval / questions 等服务。因此它只能作为 DSH 进程内的 Cordis 插件运行——请使用 Releases + 注入器安装。

Q2:状态文件在哪?删了会怎样?

状态文件位于 ~/.dsh/dsh-feishu-bridge/state.json,保存每个聊天的会话代次、会话列表、工作区绑定与会话覆盖。删除后插件会以全新状态启动(各聊天从新会话开始);历史会话的记忆内容由 DSH 的会话持久化管理,不受影响。

Q3:为什么源码构建需要 DSH checkout?

scripts/build.sh 需要把 DSH checkout 中的 cordisschemastery@deepseek-ai/* 内部包目录链接进 node_modules,并使用 checkout 自带的 tsc 编译。这些依赖不在公开 npm 上,脱离 DSH 环境无法解析,因此构建必须在 DSH checkout 环境下进行。

Q4:群聊里 @ 了机器人不回复?

群聊消息必须 @ 机器人才会进入处理(私聊无需 @);另外机器人自身发出的消息会被忽略,不会自我对话。

Q5:为什么 /setup 每次都会创建新应用?

扫码流程采用 createOnly 设计,每次 /setup(或 feishu_setup)都会注册一个全新应用,因此重复执行会累积多个应用——这是预期行为。后续版本可支持在已有应用上更新(复用 App ID)。介意的话可到开发者后台删除旧应用。

📄 License

本项目基于 BSD-3-Clause 协议开源发布。

致谢:感谢 DeepSeek Harness(DSH) 提供的进程内 agent 运行时,以及飞书开放平台提供的 IM 与卡片能力。