dsh-feishu-bridge

项目地址 https://gitee.com/zwyqz/dsh-feishu-bridge
把飞书(Lark)机器人接进 DeepSeek Harness(DSH):飞书里 @ 机器人 → DSH 里跑一个独立会话 → 回复以 Markdown 卡片流式发回。

不需要公网 IP、不需要域名、不需要内网穿透——用飞书官方 SDK 的长连接收发。

飞书 App ──WS 长连接──▶ dsh-feishu-bridge(跑在 dsh web 进程里)
                              ├─ 每个聊天一个独立 DSH 会话
                              ├─ 流式卡片回复 / 图片文件双向
                              └─ 设置页里的扫码接入 + 机器人列表

目录


功能

分类能力
消息文本、富文本(post)、@ 提及解析;群里只响应 @ 机器人
会话每个飞书聊天独立会话池,互不串台;重启自动恢复
命令/new /switch /list /rename /fork /export /stop /help
回复流式卡片(打字机效果),失败降级为整卡;处理中加 OnIt 表情
媒体入站图片/文件落盘到 <workspace>/.feishu-attachments/ 并注入 prompt;出站支持图片/视频/音频/文件
工具feishu_send(发文本卡片)、feishu_send_media(发媒体)
策略requireMention、dmMode、dmAllowlist、respondToMentionAll、groupAllowlist
稳定性单实例互斥、事件 3 秒 ack、断线自动重连、健康检查
接入扫码接入(飞书设备码流程,免去开放平台手工建应用)

环境要求

项要求说明
DSH≥ 0.2.0-rc.2依赖 ctx.webServer / ctx.agents / ctx.tools / agentPresets / agentDefaultModel / 客户端 ctx.slots.inject,旧版宿主会加载失败
Node.js^22.19.0 || >=24.0.0fetch、AbortController、全局 WebSocket
pnpm任意近期版本dsh plugin 内部用 pnpm 安装
网络能访问 open.feishu.cn 与飞书长连接网关无需公网入口
飞书一个企业自建应用(扫码可自动创建)需要「机器人」能力

宿主版本很关键:本插件深度使用 0.2.x 的插件 API,0.1.x 装不上或加载即失败。装完可用 dsh --version 核对。


安装

三种方式任选其一,装完都要重启 dsh web(插件与客户端 UI 都在启动时装配)。

方式 A:本地目录(开发 / 内网)

dsh plugin --profile web add link:D:\path\to\dsh-feishu-bridge

link: 会在 profile 里建立目录联接(Junction / symlink),源码留在原处,改完重启即生效。

方式 B:npm(公开发布后)

dsh plugin --profile web add dsh-feishu-bridge
# 若发布成 scope 包:
dsh plugin --profile web add @your-name/dsh-feishu-bridge

方式 C:直接装 Git 仓库

dsh plugin --profile web add git+https://gitee.com/your-name/dsh-feishu-bridge.git

⚠️ 仓库根目录必须是本插件包(package.json 在根上)。monorepo 子目录无法直接这样装。

安装后自检

dsh --profile web --dump-config | Select-String "feishu-bridge"     # 应有一条 loader 条目

然后重启:

dsh web

打开 http://127.0.0.1:3080 → 设置 → 左侧应出现「飞书桥」。


接入飞书

有两条路:扫码(推荐) 和 手工建应用。

路线 1:扫码(30 秒)

  1. 打开「设置 → 飞书桥」或 http://127.0.0.1:3080/api/feishu-bridge/panel
  2. 点「生成二维码」
  3. 手机飞书扫码 → 确认
  4. 面板轮询到结果后会自动写入凭据并建立长连接

扫码走的是飞书官方 App Registration(设备码) 流程,archetype=PersonalAgent,会自动创建应用并预配常用权限。

二维码有效期约 1 小时,但面板按 5 分钟倒计时提醒你重新生成(verification_uri_complete 也可直接复制到浏览器打开)。

路线 2:手工建应用

  1. open.feishu.cn → 开发者后台 → 创建企业自建应用

  2. 「添加应用能力」→ 启用 机器人

  3. 「权限管理」至少勾选:

    权限用途
    im:message.p2p_msg:readonly接收单聊消息
    im:message.group_at_msg:readonly接收群里 @ 机器人的消息
    im:message:send_as_bot以机器人身份发消息
    im:message.reaction处理中表情(可选,缺了会降级)
    im:resource下载用户发来的图片/文件(入站媒体必需)
  4. 「事件与回调」→ 订阅方式选 使用长连接接收事件 → 添加事件 im.message.receive_v1

  5. 「版本管理与发布」→ 创建版本并发布(不发布则权限不生效)

  6. 回到 DSH 面板 → 「手动添加」填 App ID / App Secret / 工作区路径 → 保存

把机器人拉进群

  1. 飞书里建/选一个群 → 群设置 → 机器人 → 添加你的机器人
  2. 群里 @机器人 发一句话,应能看到流式卡片回复

单聊不需要 @;群聊默认必须 @(可用策略里的 requireMention 关掉,但不建议)。


使用

命令

在飞书聊天里发(支持中文/英文,lang 可配):

命令说明
/new [名称]新建会话并切换过去
/switch <序号>切到本聊天的第 N 个会话
/list列出本聊天的所有会话
/rename <名称>重命名当前会话
/fork [名称]复制当前会话上下文到新会话
/export导出当前会话为 Markdown 文件回传到聊天
/stop中断当前这一轮
/help命令帮助

模型可调用的工具

工具用途
feishu_send({ text, chat_id? })主动发一条 Markdown 卡片;缺省发到最近收到消息的聊天
feishu_send_media({ paths, chat_id?, kind? })发本地图片/视频/音频/文件,kind 可强制类型

正常回答当前会话不需要调 feishu_send——模型这轮输出的文字会自动回投。

媒体

  • 入站:群里发图片/文件 → 自动下载到 <workspace>/.feishu-attachments/ → 路径注入 prompt → 模型可读(图片会用视觉能力看)
  • 出站:让 agent 调 feishu_send_media,或直接在面板「测试发送」

配置

配置文件

~/.dsh/feishu-bridge/config.json(热读,改完 2 秒内生效,不用重启):

{
  "bots": [
    {
      "name": "我的机器人",              // 显示名
      "appId": "cli_xxxxxxxx",           // 必填
      "appSecret": "xxxxxxxx",           // 必填
      "workspace": "D:\\my-project",     // 会话工作目录(必填,否则用宿主 cwd)
      "domain": "",                      // 国际版填 https://open.larksuite.com
      "reactionEmoji": "OnIt",           // 处理中表情,"none" 关闭
      "requireMention": true,            // 群里是否必须 @
      "groupAllowlist": [],              // 只服务这些 chat_id(空=不限)
      "dmMode": "open",                  // open | allowlist | pair | disabled
      "dmAllowlist": [],                 // dmMode=allowlist 时生效
      "respondToMentionAll": false,      // 是否响应 @所有人
      "lang": "zh",                      // zh | en
      "stream": true,                    // 流式卡片开关
      "enabled": true,
      "ownerOpenId": ""                  // 扫码接入自动填
    }
  ]
}

运行态文件

路径说明
~/.dsh/feishu-bridge/state-<appId>.json每聊天的会话映射(chatId → 会话列表 + 当前选中)
~/.dsh/feishu-bridge/instance.lock单实例互斥(pid + 心跳),防止两个实例抢事件

飞书长连接是集群模式:同一应用多个客户端只有一个收到事件。所以同一个 appId 只能有一个 DSH 实例在连;锁检测到冲突会让后启动的实例只读不连,并在面板显示警告。


管理入口

入口内容
设置 → 飞书桥(嵌在 DSH 设置页)只保留:扫码接入 + 机器人列表(状态、最近事件)
http://127.0.0.1:3080/api/feishu-bridge/panel完整面板:扫码、机器人增删、策略编辑、运行看板、健康自检

完整面板的看板会给:消息收/回/错、轮次与平均延迟、token 入出、最近 20 条事件(脱敏)。


排障

先看三个地方

# 1. 连接状态
curl http://127.0.0.1:3080/api/feishu-bridge/status

# 2. 健康检查
curl http://127.0.0.1:3080/api/feishu-bridge/health

# 3. 宿主编排有没有它
dsh --profile web --dump-config | Select-String "feishu-bridge"

常见现象对照表

现象原因处理
设置页没有「飞书桥」装完没重启宿主 / 客户端插件加载失败重启 dsh web;页面顶部若报 Failed to load plugins,看宿主日志
面板显示 未启动 / 缺少 App Secret凭据缺失(扫码写入失败时会出现)在该行粘贴 App Secret 保存,或重新扫码
状态 connected 但发消息没反应① 事件订阅没设为「长连接」② im.message.receive_v1 没订阅 ③ 应用版本没发布 ④ 群里没 @逐项核对接入飞书
报 230027 Lack of necessary permissions缺对应权限(如读群消息 im:message.group_msg)后台加权限 → 重新发布版本
报 99991672 / access denied应用未发布,或权限未审批发布版本;等待管理员审批
入站图片提示下载失败缺 im:resource 权限补权限并发布
卡片发不出、报 230099 / 11310单卡片元素超长插件会自动续卡;若仍报错,缩短回复或关掉 stream
两个实例互相抢事件长连接集群模式只保留一个宿主;锁文件在 ~/.dsh/feishu-bridge/instance.lock
回复里出现 <||DSML||> calls> 之类的标记agent 没挂上 preset(宿主版本不匹配或 preset 解析失败)检查宿主版本;看 /status 里 preset 字段是否为 standard

看宿主日志

插件所有关键动作都打在宿主 stdout,前缀 [feishu-bridge]:

[feishu-bridge] plugin loaded (m4-2); config at C:\Users\<you>\.dsh\feishu-bridge\config.json
[feishu-bridge] bot 我的机器人 connected (open_id=ou_xxx)
[feishu-bridge] inbound chat=oc_xxx type=text content={"text":"..."}
[feishu-bridge] attachment saved: D:\...\.feishu-attachments\xxx.png (55452 bytes, image)
[feishu-bridge] skip bot xxx: App Secret 缺失

自测接口

不依赖飞书就能验证核心链路(开发/排障用):

路由用途
GET /api/feishu-bridge/status运行态快照(bot 状态、模型、preset、看板)
GET /api/feishu-bridge/health探活(连接数、最近事件、计数)
GET /api/feishu-bridge/stats看板数据
POST /api/feishu-bridge/selftest跑一轮 agent(不碰飞书,返回模型回复)
GET /api/feishu-bridge/simulate?chat=<chat_id>&text=...伪造一条入站事件(可加 &key=<file_key>&type=image 测媒体)
GET /api/feishu-bridge/push?chat=<chat_id>&text=... | &media=<路径>主动发文本/媒体
POST /api/feishu-bridge/onboard/{begin,poll,cancel}扫码接入

调试变量:FEISHU_BRIDGE_IGNORE_LOCK=1 可绕过单实例锁,便于另起探针实例(例如 3099 端口)验证新代码而不打扰正式宿主。


架构与文件

lib/index.js      插件入口:配置读写、实例锁、路由、agent 工具注册(薄装配层)
lib/bot.js        单机器人运行时:LarkChannel 连接、事件入队、会话池、流式回复、命令
lib/onboard.js    设备码扫码:begin / poll / cancel / 状态机
lib/client.js     浏览器半侧:注册 settings.section「飞书桥」
lib/panel.html    完整管理面板(服务端渲染单页,无需构建)
cordis.patch.yml  bundle 补丁:把自己插入宿主 loader 名单

加载链路(排查「装没装上」用):

dsh web
 └─ 读 ~/.dsh/profiles/web/package.json 的 dsh.profile.bundles
     └─ 本包 dsh.bundle.patch → cordis.patch.yml → insert { id: feishu-bridge }
         └─ 按包名解析 → node_modules 里的 junction → 本目录
             └─ main: lib/index.js → apply(ctx)   (与宿主同进程)

文档:


升级 / 卸载

# 升级(npm 方式)
dsh plugin --profile web add dsh-feishu-bridge@latest && dsh web

# 卸载
dsh plugin --profile web remove dsh-feishu-bridge

卸载后残留(可手动删):~/.dsh/feishu-bridge/(配置与状态)、<workspace>/.feishu-attachments/、<workspace>/.feishu-exports/。


安全说明

  • 插件在宿主进程内执行,等同任意代码;只安装你信任的版本。
  • 凭据落盘在 ~/.dsh/feishu-bridge/config.json(权限 0600),API 只回掩码;仓库里不含任何凭据。
  • 入站附件会写入工作区 .feishu-attachments/,出站媒体会把文件上传到飞书——注意工作区里的敏感文件。
  • 建议在策略里配 groupAllowlist,避免机器人被拉进陌生群后乱回。

已知限制

  • 群里只响应 @ 机器人的消息(requireMention 默认开);不支持群内全量消息监听。
  • agents.resume() 不接受 agentPreset,实现改为恢复后再挂 preset。
  • 卡片按钮回调(cardAction)在长连接下是否派发未验证,审批按钮类功能暂不作为承诺。
  • 语音/视频理解未做,仅文件透传。

License

MIT

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐