dsh-macos-notifier:DSH 会话结束时弹出 macOS 通知并一键回到会话

前言

在 DeepSeek Harness(DSH)里同时开多个 Agent 会话时,常见做法是盯着界面等「运行中」变成「已停止」。窗口不在前台、或在别的应用里工作时,很容易错过一轮结束。系统脚本或 osascript 可以发 macOS 通知,但往往会起子进程、把通知挂到错误的应用名下,还要自己维护状态与点击跳转。

下面介绍社区插件 dsh-macos-notifier(维护者 veritaswiki):在 DSH 渲染层里监听会话状态,会话从运行变为停止时发出标题为会话名的系统通知;点击通知通过 uiWorkspace.openSession(sessionId) 回到对应会话。通知走 Web Notification API,不起子进程、不调用 osascript、不写状态文件。

这是什么

  • 名称:dsh-macos-notifier(npm 包名与 Cordis bundle 名一致)
  • 分类:客户端(client.js 承载全部逻辑;宿主侧 index.js 为空插件,仅提供 Loader entry)
  • 版本(资料):0.1.0
  • 许可证:MIT
  • 运行要求:Node >=20,DSH >=0.2.2-rc.1

一句话:会话完成一轮(状态边沿 running: true → false)时,在 macOS 上弹出以会话名为标题的通知,点击即可打开该会话。

核心功能

何时触发

插件订阅 api-session/status(sessionId, isRunning),在 onStatus() 里只响应 prev === true && isRunning === false 的边沿,避免运行中途状态抖动重复弹窗。若 remote.$on 不可用,会退化为每 800 ms 轮询 sessions 快照中的 running 字段。

哪些会话会通知

isNotifiable() 会跳过:

  • origin === 'subagent' 的子代理会话
  • 带 parentSessionId 的会话
  • blank === true 的空白会话

通知内容与行为

  • 标题:优先 sessions 快照 byId[id].title,否则 label,再否则 'DSH'。
  • 系统通知:new Notification(title, { body, tag: 'dsh-session-' + sessionId, silent: false });同一 tag 互相替换,不会堆一列。
  • 节流:同一会话 2 秒内不重复发(THROTTLE_MS = 2000)。
  • 点击:主路径 n.onclick → ctx.get('uiWorkspace').openSession(sessionId);兜底把 sessionId 写入 localStorage['dsh.macos-notifier.pending'](有效期 PENDING_TTL_MS = 90000),在 window focus 时 takePending() 补跳。

应用内提示与小铃铛

同一事件在系统通知之外必定再发应用内提示(命令式 DOM,右下角叠加层):前台约 9 秒、后台约 60 秒自动消失,同屏最多 3 张。

会话头部工具区注入小铃铛(conversation.session.header.utilities,id: 'macos-notifier-action'):点击发测试通知,用于确认通道;首次请求系统通知权限也在点击铃铛的手势里(页面加载时自动请求会被系统拒绝)。

安装与启用

本插件是 DSH(Cordis)bundle,资料给出三种方式。

方式 A:通过 Agent 调用 plugin_manager

在 DSH 中对 Agent 说明安装 dsh-macos-notifier,由 plugin_manager 执行:

  1. action: "install_bundle",target 为安装 spec,例如已放在本地的 file:/abs/path/to/dsh-macos-notifier,或 github:veritaswiki/dsh-macos-notifier。
  2. 安装完成后 action: "set_bundle" 启用。

方式 B:手动挂到 profile

  1. 将仓库放在任意目录(下文记作 /abs/path/to/dsh-macos-notifier)。
  2. 编辑 ~/.dsh/profiles/<profile>/package.json:
    - dependencies 增加 "dsh-macos-notifier": "link:/abs/path/to/dsh-macos-notifier"
    - dsh.profile.bundles 数组增加 "dsh-macos-notifier"
  3. 在 profile 目录安装依赖后重启 DSH(DSH 下次启动也会自行安装依赖)。

方式 C:从源码目录链接

  1. 将 https://github.com/veritaswiki/dsh-macos-notifier 放到本地目录。
  2. 同方式 B,依赖改为 "dsh-macos-notifier": "file:/abs/path/to/dsh-macos-notifier"。
  3. 重启 DSH。

client.js 仅 require('react')(由宿主提供),包内无额外 npm 依赖,无需单独安装 @deepseek-ai/*。

装完后:打开系统通知权限

系统设置 → 通知 → DeepSeek Harness → 开启「允许通知」,样式选「横幅」或「提醒」。未授权时 systemNotify() 直接返回 false,此时仅能看到应用内提示。

典型用法

安装并启用 bundle 后,无需在插件里改配置项(见下一节)。日常流程如下:

  1. 保持一个或多个 DSH 会话在后台跑任务。
  2. 某会话从「运行中」变为「已停止」时,收到标题为该会话名的 macOS 通知(若已授权)及应用内提示。
  3. 点击系统通知或切回 DSH 窗口(依赖 focus 兜底)进入对应会话。
  4. 若不确定权限或通道是否正常,在会话头部点小铃铛发测试通知;denied / default 时点铃铛会打开系统通知设置而非权限对话框。

配置与可调项

插件没有设置页:index.js 的 apply() 为空,无 Config schema。能改的只有 client.js 中的常量或系统权限,例如:

键 默认值 说明
THROTTLE_MS 2000 同一会话两条系统通知最小间隔(毫秒)
PENDING_TTL_MS 90000 待跳转 sessionId 在 localStorage 的有效期
PENDING_KEY 'dsh.macos-notifier.pending' 待跳转 localStorage 键名

package.json 中 dsh.client.immediately 默认为 true,client 随宿主立即加载。

适用场景与注意

适合谁:在 macOS 上使用 DSH 桌面客户端、需要「会话跑完一轮」被动提醒,并希望通过通知快速跳回会话的开发者。

环境限制(资料原文):

  • 仅 macOS 客户端场景有意义:依赖渲染层 Web Notification;在普通浏览器打开同一 Web GUI 时,通知与权限由浏览器管理,插件不接管。
  • 未授权则无系统横幅:仅剩应用内提示。
  • 依赖宿主契约:事件名 api-session/status 与 sessions 快照字段;宿主变更可能导致仅轮询或无法触发;逻辑全程 try/catch,不挡界面。
  • 不是通知中心:不保存历史;应用内提示固定右下角,UI 不可调。
  • 插件在 DSH 进程内运行:安装前宜自行查看 GitHub 仓库 源码与 MIT 许可证,确认符合你的环境与安全要求。

DSH 生态强调「一切皆插件」;社区目录 SkillHub 插件页 为独立站点,与 DeepSeek / 幻方无官方从属关系。

结尾

经过上面的步骤,dsh-macos-notifier 把「会话结束」绑在 DSH 自己的渲染层里:边沿触发、会话名标题、点击回到会话,并辅以应用内提示与头部测试铃铛。需要安装说明与实现细节时,以仓库 README 为准。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye