dsh如何连接飞书插件
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.0 | fetch、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 秒)
- 打开「设置 → 飞书桥」或
http://127.0.0.1:3080/api/feishu-bridge/panel - 点「生成二维码」
- 手机飞书扫码 → 确认
- 面板轮询到结果后会自动写入凭据并建立长连接
扫码走的是飞书官方 App Registration(设备码) 流程,archetype=PersonalAgent,会自动创建应用并预配常用权限。
二维码有效期约 1 小时,但面板按 5 分钟倒计时提醒你重新生成(
verification_uri_complete也可直接复制到浏览器打开)。
路线 2:手工建应用
-
open.feishu.cn → 开发者后台 → 创建企业自建应用
-
「添加应用能力」→ 启用 机器人
-
「权限管理」至少勾选:
权限 用途 im:message.p2p_msg:readonly接收单聊消息 im:message.group_at_msg:readonly接收群里 @ 机器人的消息 im:message:send_as_bot以机器人身份发消息 im:message.reaction处理中表情(可选,缺了会降级) im:resource下载用户发来的图片/文件(入站媒体必需) -
「事件与回调」→ 订阅方式选 使用长连接接收事件 → 添加事件
im.message.receive_v1 -
「版本管理与发布」→ 创建版本并发布(不发布则权限不生效)
-
回到 DSH 面板 → 「手动添加」填 App ID / App Secret / 工作区路径 → 保存
把机器人拉进群
- 飞书里建/选一个群 → 群设置 → 机器人 → 添加你的机器人
- 群里 @机器人 发一句话,应能看到流式卡片回复
单聊不需要 @;群聊默认必须 @(可用策略里的
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
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)