前言¶
DSH 的日常交互主要在桌面端完成。人离开工位时,想用手机或 IM 给正在跑的 Harness 会话发一条指令、看模型结论,或处理一次 ask 档审批,往往需要额外搭回调、内网穿透或自建桥接。dsh-plugin-im-remote-control(维护者 raven3005672)把飞书(Lark)机器人和 DSH 宿主绑在一起:消息经 sessionController.prompt 进入会话,回合结束把 assistant 文本回帖;审批和 ask_user_question 可在飞书里用卡片或斜杠命令处理。当前交付的是 direct 模式——插件进程内持有飞书 WebSocket 长连接,不需要公网 IP。包版本 0.2.0,许可证 MIT,在 DSH 插件目录中归类为客户端。
下面按定位、能力、安装配置、典型用法和注意事项说明。
这是什么¶
插件全称 dsh-plugin-im-remote-control,一句话定位:用飞书机器人远程控制一个 DSH 会话。飞书侧私聊或群聊 @ 机器人发消息,等价于在桌面输入框投递 user turn;插件监听会话事件,在聊天里回帖、发回执,并把审批与提问转发到飞书。中控会话还可通过 HTTP dispatch 把任务投到其他会话,由插件负责把执行结果绑回对应聊天。
设计细节(状态机、竞速、卡片协议等)见仓库 docs/DESIGN.md。微信接入与 gateway 冷启动模式代码保留但未启用。
核心功能¶
资料中已核实的能力如下。
| 能力 | 说明 |
|---|---|
| 飞书长连接 | 插件内 WebSocket,无需公网回调地址 |
| 私聊 / 群聊 | 私聊直接处理;群聊须 @ 机器人 |
| 消息进会话 | 走 sessionController.prompt,不绕过 session log |
| 回合回帖 | 回合结束发送最后一步 assistant 文本;dispatch 任务首行带 【会话名】 |
| 表情回执 | 收到消息贴 Get;会话忙时贴 OneSecond(可由 ack 关闭) |
| 分发接口 | Bearer token + chat allowlist,POST /im-remote-control/dispatch |
| 审批转发 | ask 档审批以卡片发到飞书,按钮或 /approve、/deny,与桌面弹窗竞速 |
| 卡片提问 | ask_user_question 以卡片展示选项;多选或自定义用 /answer |
| 图片输入 | 下载飞书图片作为 image part(PNG/JPEG/GIF/WebP,单张 ≤10 MB,单条最多 4 张) |
| 引用回复路由 | 引用机器人某条结果回复时,消息回到产生该结果的会话 |
| 设置页 | DSH「设置 → 远程控制」可编辑凭据、allowlist、渠道等(改动需重启生效) |
/whoami |
返回发送者 open_id,用于配置 allowlist |
尚未交付:非图片文件、语音/音频、微信、gateway 冷启动、超限重试、多实例等。
工作方式概览:
飞书(私聊 / 群聊 @)
│ WebSocket 长连接(插件持有)
▼
dsh-plugin-im-remote-control(Host)
├─ sessionController.prompt → 目标会话 user 消息
├─ ctx.on('session/event') → 回合结束回帖
├─ ctx.on('approval/request') → 卡片审批
├─ ctx.on('user-questions/request') → 卡片提问
├─ card.action.trigger → 按钮点击
└─ ctx.webServer → /dispatch、/check、/status
消息按 session 队列(mode: 'queue' 对应宿主 agent.followup())串行处理;只有经插件投递的回合会回帖,桌面手动发起的回合不受影响。
安装与启用¶
安装命令¶
从 npm 安装(将 <profile> 换成你的 profile 名):
dsh plugin --profile <profile> add dsh-plugin-im-remote-control
或从本地构建目录安装(lib/ 不入库,需先构建):
cd /path/to/dsh-plugin-im-remote-control && npm install && npm run build
dsh plugin --profile <profile> add /path/to/dsh-plugin-im-remote-control
运行环境要求(来自 package.json):Node ^22.19.0 || >=24.0.0,DSH >=0.2.0 <0.3.0;与 DSH 0.2.1-rc.2 标注为 compatible。
profile 配置¶
包的 dsh.bundle.patch 已 insert 插件行。你在 profile 的 cordis.patch.yml 里只需加一条同 id 的覆盖行(不要再次 insert 同 id,否则会挂两份长连接且设置页找不到配置):
- id: dsh-plugin-im-remote-control
name: dsh-plugin-im-remote-control
config:
feishu:
appId: cli_xxxxxxxxxxxxxxxx
appSecret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
controllerSessionId: session-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
channels: [feishu]
allowedChats:
- oc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
allowedUsers:
- name: 我自己
openId: ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ack: true
reply: true
覆盖行的 config 是整体替换,不是深合并,需要的键要一次写全。
配置改完后重启 DSH:Host 半边与飞书连接仅在启动时加载;设置页的修改同样要重启后才应用到连接。
可选兜底文件 $DSH_HOME/im-remote-control.json(默认 ~/.dsh/im-remote-control.json)可补充凭据与 allowlist;行内显式配置优先,allowlist 数组取并集。
飞书应用准备¶
- 在飞书开放平台创建企业自建应用,开启「机器人」。
- 权限:
im:message、im:message.group_msg、im:message:send_as_bot。 - 事件订阅选长连接,订阅
im.message.receive_v1(无需公网地址)。 - 在回调配置页把
card.action.trigger也设为长连接(卡片按钮交互);缺这一步点按钮会报200340。 - 发布并把机器人加入目标群或私聊使用。
- 在飞书里对机器人发
/whoami,把返回的open_id填入allowedUsers或allowedOpenIds。
访问控制(fail-closed)¶
allowedChats、allowedUsers、allowedOpenIds 至少配一项,否则插件只注册设置页探测、不连飞书(日志 no access control configured),也不会处理 dispatch。数组写错会直接报错,不能当成「空 = 不限制」。
主要配置项:
| 字段 | 说明 |
|---|---|
feishu.appId / feishu.appSecret |
自建应用凭据;设置页 Secret 只显示掩码,不留存明文回显 |
controllerSessionId |
中控会话 ID(兼容旧字段 sessionId) |
channels |
默认未设置即飞书;[] 表示不连飞书 |
ack / reply |
默认 true,控制表情回执与回合回帖 |
enabled |
false 时不启动插件 |
典型用法¶
日常对话¶
私聊机器人直接发文字;群聊须 @ 机器人。文本与图片(在模型支持 image 输入时)进入 controllerSessionId 指定的中控会话,或由引用回复路由到产生某条机器人结果的执行会话。
斜杠命令¶
| 命令 | 作用 |
|---|---|
/whoami |
返回发送者 open_id |
/approve <id> |
批准审批(allowed-once) |
/deny <id> |
拒绝审批 |
/answer <id> <文本> |
回答提问;多选用逗号分隔选项 |
群聊发命令也要 @ 机器人。
审批卡片约 120 秒内有效,超时自动拒绝;提问卡片约 5 分钟内有效,超时只撤回卡片,桌面仍可作答。飞书与桌面竞速:谁先决定谁生效。
引用回复¶
对机器人发出的回合结果做「引用回复」,下一条消息进入该结果所属会话,适合 dispatch 出去的任务在飞书里做追问;不引用时消息仍进中控。
中控分发¶
中控会话可通过 POST /im-remote-control/dispatch 把任务投给任意会话。鉴权为 Authorization: Bearer <token>,且 chatId 须在 allowedChats 中。token 每次挂载随机生成,写入 $DSH_HOME/im-remote-control.token(权限 0600)。仓库提供 scripts/dispatch.mjs 可读该 token 调用。
设置页通过 POST /im-remote-control/check(头 x-imrc-check: 1)做只读探测,GET /im-remote-control/status 查看哪些字段已配置(不含 Secret 明文)。
适用场景与注意¶
适合谁:需要在飞书里收发 DSH 回合、远程点审批或答 ask_user_question 的开发者;希望用长连接、不暴露公网回调的小型自建部署。
权限与安全:allowlist 中的飞书账号等价于能在 DSH 进程权限下驱动 agent(含 shell、读写文件)。插件以当前 DSH 进程的系统用户权限运行;安装前应自行审阅 源码 与 MIT 许可证。官方建议从飞书驱动的会话使用 workspace-write + ask,避免 danger-full-access + never 让远程消息无刹车执行。
飞书账号即执行权,宜开启二次验证并保持 allowlist 尽量小。/im-remote-control/* 路由由插件挂在 Host web server 上,不走 GUI 的 cookie 认证:dispatch 靠 Bearer token;若 Host 绑定非回环地址,这些路由会一并暴露(/status 最坏仅泄露布尔状态与 Secret 末四位掩码)。
已知限制:非图片文件不转发;回帖仅最后一步 assistant 文本,超过约 3500 字符会截断;一个飞书应用只应有一条长连接、一个实例对应一个中控 sessionId;审批仅对 ask 档有意义(never 档不产生审批请求)。
DSH 生态强调「一切皆插件」;SkillHub 目录 为社区站点,与 DeepSeek / 幻方无官方从属关系。
结尾¶
dsh-plugin-im-remote-control 把飞书长连接、会话 prompt、回合回帖、审批与提问卡片和 dispatch 串成一条可落地的远程控制链路,direct 模式无需公网回调。查阅安装细节与更新说明见 GitHub 仓库,在 SkillHub 插件页 可浏览分类与简介。