DeepSeek Harness plugin

dsh-lark-bridge-leolab20

DeepSeek Harness plugin: real-time Feishu/Lark notifications when a DSH session pauses for user interaction (permission asks, questions, fatal errors).

Jump to install

Source facts

Repository
leo-lab-2026/dsh-lark-bridge
Latest update
Aug 17, 2026
Category
Remote & Mobile
GitHub stars
1
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/leo-lab-2026/dsh-lark-bridge
Plugin: dsh-lark-bridge-leolab20
Author: leo-lab-2026

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer3 files
README.mdSource · read only

dsh-lark-bridge

![npm version](https://www.npmjs.com/package/dsh-lark-bridge) ![npm downloads](https://www.npmjs.com/package/dsh-lark-bridge) ![license](./LICENSE)

DeepSeek Harness 插件:当 DSH 会话停止工作——因等待使用者交互而停顿、任务完成、被阻塞/中止、请求退避、进程停滞,甚至进程死亡——都会实时调用 lark-cli 发送飞书/Lark 通知,实现「DSH 停止工作 = 必收到通知」的完整覆盖。

功能

类别触发通知时机
权限申请工具申请审批(如沙箱升级)等待审批期间(约 0.5s 宽限期内被秒批则不打扰)
向用户提问模型调用 ask_user_question(含 plan mode 计划评审)等待回答期间
错误致停轮次以致命错误结束(模型 400/401/403/配额/重试耗尽等 4xx-5xx)立即(每会话 5 分钟节流)
任务完成轮次 completed 结束且 agent 进入 idle(5s 宽限期过滤 goal 自动续轮//loopidle 宽限后(每会话 30 分钟节流)
目标阻塞turn/end blocked(goal 阻塞 / 预步骤拒绝;详情取最近 update_goalblocked_reasonidle 宽限后
令牌上限turn/end max-tokensidle 宽限后
轮次被中止turn/end aborteduser/parent 抑制;hook/disposed/legacy 通知)idle 宽限后
异常中断闭合turn/end interrupted(崩溃孤儿轮在重载时闭合)idle 宽限后
请求退避llm/retry 事件达到重试阈值(默认第 2 次起)达到阈值即发(每会话 5 分钟节流)
无进展停滞agent 保持 running 但长时间无任何事件(默认 10 分钟判定)判定即发(默认 60 分钟重复提醒)
正常退出插件 dispose(仅整个应用树卸载时,HMR/重载不误报)退出时告别通知
进程死亡进程外监督者:插件写心跳文件,scripts/lark-watchdog.mjs 检测心跳丢失心跳超时即发

插件是纯只读观察者:只监听 DSH 持久事件流与 agent/status 生命周期,不拦截任何执行链、不代答任何审批/提问;lark-cli 缺失或发送失败时 fail-soft(只告警、绝不影响 DSH)。所有类别独立开关,默认全部开启(噪音由宽限窗口与节流控制)。

安装

前置要求:Node ^22.19 || >=24、pnpm、DeepSeek Harness(dsh)。

# 从 npm(发布后)
dsh plugin --profile <name> add dsh-lark-bridge

# 从 GitHub(源码安装;需要授权构建脚本,见下方「发布与安装说明」)
dsh plugin --profile <name> add github:<you>/dsh-lark-bridge#<sha>

# 本地 tarball / 目录
dsh plugin --profile <name> add ./dsh-lark-bridge-0.1.0.tgz
dsh plugin --profile <name> add link:/path/to/dsh-lark-bridge

验证安装:dsh --profile <name> --dump-config 应出现 dsh-lark-notify 行。重启 dsh 生效。

> 默认无通知目标:插件安装后的目标为空(不携带任何聊天/用户 id——那是属于你的个人数据)。首次使用时通过下面的「方式 A(/lark-notify setup)」或「方式 B(设置面板)」指定一次,写入 settings.yaml 持久生效;之后换机器/换会话重新指定即可。

更新插件

插件作为 npm 依赖装在 profile 目录里($DSH_HOME/profiles/<name>/node_modules),dsh plugin 是 pnpm 转发器;更新后重启 dsh 生效。

查看当前安装版本:

dsh plugin --profile <name> list dsh-lark-bridge

① 小版本/补丁更新(同 semver 范围内)

dsh plugin --profile <name> update dsh-lark-bridge

update 只在安装时声明的版本范围(如 ^0.1.0)内找新版本——不跨 minor、默认也不装预发布版。

② 跨版本 / 预发布版升级(推荐,如 0.1.0 → 0.2.0-beta.1)

dsh plugin --profile <name> add dsh-lark-bridge@0.2.0-beta.1

add 带显式版本会重写 profile 的依赖声明为该版本,一步完成升级(pnpm 会把它写入 profile 的 minimumReleaseAgeExclude,刚发布的新版本也立即生效)。已装 0.1.0 想升到 0.2.0-beta.1 就用这一条;直接跑 update 只会停在 0.1.x。

> 为什么不用 add dsh-lark-bridge@next:npm 的 latest 只指向稳定版,预发布版挂在 next 标签下;且 pnpm ≥ 11.21 的 minimumReleaseAge 保护会在标签解析时跳过刚发布的新版本(实测 @next 可能解析到更旧的 beta),显式版本号最可靠。

③ 回滚到旧版:同样用显式版本:

dsh plugin --profile <name> add dsh-lark-bridge@0.1.0

更新后验证

dsh --profile <name> --dump-config   # 应出现 dsh-lark-notify 行

重启 dsh 后进入会话运行 /lark-notify status,核对启用的通知类别(0.2.0-beta.1 新增 complete/stop/retry/stall 等)与发送统计。

首次配置(三步,约 5 分钟)

1. 准备飞书应用与 lark-cli

1. 在飞书开放平台创建企业自建应用(或使用已有应用),拿到 App IDApp Secret;在「应用能力」里启用机器人; 2. 在「权限管理」开通发送消息权限(三选一即可):im:message(获取与发送单聊、群组消息)或 im:message:send_as_bot(以应用的身份发消息)或 im:message:send(历史版本)——参考官方发送消息文档; 3. 若想用 setup 自动配置:在「事件与回调」开通 im.message.receive_v1 事件订阅,并授予 im:message:readonlyim:message.p2p_msg:readonly 权限; 4. 安装并配置 lark-cli(凭据存于 lark-cli 自身,插件从不接触 App Secret): ``sh npx @larksuite/cli@latest install lark-cli config init # 交互输入 App ID / App Secret lark-cli auth status --json --verify # 确认 bot identity: ready ``

2. 配置通知目标(三种方式任选)

方式 A(推荐):/lark-notify setup 自动配置 — 在 DSH Web 里输入:

/lark-notify setup

然后去飞书给机器人发任意一条消息(默认 3 分钟窗口)。插件会自动捕获你与机器人的会话 chat_id 并写入设置(持久化到 settings.yaml,无需改任何 YAML),同时发送一条测试通知确认链路。

方式 B:DSH Web 设置面板手动填写 — 打开 DSH 设置 → 「lark-notify」分节 → 填入 chatIdoc_ 开头)或 userIdou_ 开头),保存即生效(无需重启)。chat_id 可这样获取:

lark-cli event consume im.message.receive_v1 --max-events 1 --timeout 60s
# 与此同时给机器人发一条消息,输出 NDJSON 里的 chat_id (oc_...) 即目标

方式 C:YAML(部署默认值 / CI / 高级用户) — 在 profile 的 cordis.patch.yml 覆盖插件行(patch 按 id 整行替换 config):

- id: dsh-lark-notify
  name: 'dsh-lark-bridge'
  config:
    target:
      chatId: 'oc_xxxxxxxxxxxxxxxx'
    # dryRun: true              # 只打日志不真发(调试)
    # webUrl: 'http://127.0.0.1:3080'
    # bin: '/path/to/lark-cli'  # 不在 PATH 时指定绝对路径

优先级:Web 设置面板(用户层)> YAML(部署层)> 默认值。方式 A/B 写入的用户设置会覆盖方式 C 的部署默认值。

3. 验证

  • /lark-notify test 你好 → 飞书收到测试通知;
  • /lark-notify status → 一键诊断:通知目标、lark-cli 存在性与认证状态、发送统计、启用的通知类别、setup 进度与可执行提示;
  • 真实触发:让模型执行一个需要审批的操作 / 调用 ask_user_question / 制造一次模型错误 / 完成任务 / 制造重试退避,飞书应收到对应通知;
  • 想一次触发全部场景(提问/权限/完成/停滞/中止反例等):把 [docs/11-notify-test-script.md](./docs/11-notify-test-script.md) 的测试脚本粘贴给 DSH,按对照表逐条核对。

按工作区/项目路由通知(可选)

一个项目对应一个飞书群时,可以让每个工作区的通知发到各自的群,互不干扰。默认所有工作区共用全局通知目标(方式 A/B/C 配置的那个);只有显式绑定了路由的工作区才走专属目标。

绑定(推荐,零 YAML):在目标工作区对应的 DSH 会话里输入:

/lark-notify route

然后去目标飞书群给机器人发送任意一条消息(机器人需先被拉进该群;默认 3 分钟窗口)。插件捕获该群的 chat_id,自动绑定「当前工作区 → 该群」,并回发一条测试通知确认。多工作区各绑一次即可;重新绑定同一工作区即覆盖。

管理:打开 DSH 设置 → 「lark-notify」分节 → routing 列表可查看/增删改每条绑定(title 工作区名、path 路径、chatId 群 id);/lark-notify status 显示 route 进度。

YAML 部署层(CI/批量):在 cordis.patch.yml 写死映射:

- id: dsh-lark-notify
  name: 'dsh-lark-bridge'
  config:
    routing:
      - title: '项目 A'          # 工作区显示名
        path: '/srv/projects/a'  # 工作区路径(重命名后仍按此匹配)
        chatId: 'oc_xxx_a'
        userId: ''
      - title: '项目 B'
        path: '/srv/projects/b'
        chatId: 'oc_xxx_b'
        userId: ''

匹配规则:按工作区标题精确匹配优先,标题对不上时回退按路径匹配——因此重命名工作区不会断路由(路径不变);删除工作区后会话仍会通过 cwd 路径命中旧绑定,直到你手动清理。未绑定目标的工作区走全局默认目标,通知不丢失。

进程死亡看门狗(可选)

进程内观察者无法报告自己的死亡(OOM/崩溃/断电/误杀)。开启插件心跳 + 进程外监督者即可覆盖:

# cordis.patch.yml(或作为部署层 config 覆盖)
config:
  watchdog:
    enabled: true
    heartbeatFile: '/tmp/dsh-heartbeat'   # 插件每 5s 更新一次

再任选一种方式运行监督者脚本:

# 常驻模式(默认每 staleMs/4 检查一次)
node scripts/lark-watchdog.mjs --heartbeat-file /tmp/dsh-heartbeat --stale-ms 60000 --chat-id oc_xxx

# 定时任务模式(cron / systemd timer 每 30s 跑一次)
node scripts/lark-watchdog.mjs --heartbeat-file /tmp/dsh-heartbeat --stale-ms 60000 --chat-id oc_xxx --once

心跳丢失超过 stale-ms 即发「DSH 进程死亡」通知;同一死亡事件按 --repeat-ms(默认 60 分钟)去重,状态记录在 <heartbeat-file>.alerted--once 退出码:0 心跳正常(或重复窗口内抑制)、2 已发送告警、3 告警发送失败。

配置参考

完整配置项、模板变量、每类别开关见 [docs/09-notify-plugin.md](./docs/09-notify-plugin.md)。

模板变量:公共 {sessionId} {sessionTitle} {workspace} {workspaceTitle} {workspacePath} {cwd} {webUrl} {time};permission {tool} {reason};question {header} {question} {options} {questions} {number};error {errorLabel} {errorCode} {errorStatus} {errorMessage} {turn};complete {turn};stop:blocked {turn} {reason};stop:max-tokens {turn};stop:aborted {turn} {cancelCause};stop:interrupted {turn};retry {retry} {maxRetries} {maxRetriesLabel} {delaySec} {provider} {mode} {errorLabel} {errorCode} {errorStatus} {errorMessage} {turn};stall {stalledMin};goodbye {time}。当 {options} 为空时,仅由 Options: {options} 构成的整行自动省略;工作区: {workspace} 在无法解析出工作区/项目时整行省略(避免空标签噪音)。

工作区/项目信息:通知首行默认显示 工作区: {workspace}(DSH 工作区名称,或回退为会话工作目录的目录名),帮助在多个工作区/项目并行工作时一眼分辨通知属于哪个项目。解析优先级:DSH 工作区注册表标题(ctx.workspaceRegistry,Web 版内置)→ 会话 header.cwd 的 basename → 无(该行省略)。{workspaceTitle}{workspace} 相同,{workspacePath} 为工作区路径(或 cwd),{cwd} 为会话工作目录。

按工作区路由routing 数组(每条含 title/path/chatId/userId)把指定工作区的通知定向到专属目标;按标题精确匹配、回退路径匹配;未命中走全局 target。用 /lark-notify route 或设置面板绑定,详见上文「按工作区/项目路由通知」。

常见问题

现象处理
status 显示「无法执行 lark-cli」npx @larksuite/cli@latest install;若二进制不在 PATH,在 config 里设置 bin 绝对路径
status 显示 bot 不可用lark-cli config init 重新配置应用凭据(App ID/Secret)
setup 窗口内没捕获到消息确认开发者后台已开通 im.message.receive_v1 事件订阅,且已授予 im:message.p2p_msg:readonly;再给机器人发一次消息重试
/lark-notify route 群里发消息没反应机器人需先被拉进该群;确认开发者后台事件订阅包含群消息(im.message.receive_v1 的群聊场景),且机器人具备在群内收发消息权限
发送失败(status 的最近错误)错误信息含飞书 error 信封与 hint:常见为缺 scope(im:message/im:message:send_as_bot)或机器人不在会话中
飞书提示「Bot can NOT be out of the chat」该 chat_id 不属于机器人可发送的会话;用方式 A/B 重新获取正确的 p2p chat_id

发布与安装说明(维护者)

完整发布方案(发布渠道决策、发布前门禁、npmjs 发布流程、dist-tag 政策、回滚预案、CI 自动化)见 [docs/10-publish-checklist.md](./docs/10-publish-checklist.md)。要点:

  • npm 发布pnpm build && npm publish --registry=https://registry.npmjs.org/prepublishOnly 自动跑 typecheck+test,prepack 自动构建 lib/);用户安装时不会执行构建;
  • GitHub 源码安装prepare 脚本负责转译;用户需按 pnpm 提示在 profile 的 pnpm-workspace.yaml 中授权 allowBuilds(参见 DSH 官方插件分发文档);
  • 锁定 lark-cli 版本:输出/错误契约随 lark-cli 迭代,README 建议用户锁定 @larksuite/cli 版本;
  • 本地开发:devDependencies 通过 link: 指向同机的 deepseek-harness checkout(需位于 ../deepseek-harness 且已构建);pnpm test(含真实子进程 fixture)、pnpm typecheckpnpm build

开发

架构与设计(停顿检测模型、grace 竞态、Category/Notifier 两条接缝、Phase 2A/2B/2C 路线图、安全)见 [docs/09-notify-plugin.md](./docs/09-notify-plugin.md);DSH/Lark 调研背景见 [docs/README.md](./docs/README.md)。