dsh-native-notifications:讓 DSH 的審批、提問與任務完成在系統層彈通知

前言

DSH 跑一個長任務時,人常離開窗口去別處。審批來了要確認權限,提問來了要選答案,任務跑完要看結果——這幾類事件如果只在頁面裏體現,人不在就錯過了。已有做法是靠輔助進程發通知,系統會把橫幅歸屬到那個腳本運行器上,點回去也落不到 DSH 會話。

下面介紹的 tommy00748-tech/dsh-native-notifications 換一種方式:通知由 DSH 頁面自己發出來,操作系統把它歸屬到 DeepSeek Harness,點一下橫幅回到會話,並且可以選或自己寫鈴聲。

這是什麼

DSH 插件,目錄頁歸在「客戶端」分類,維護者 tommy00748-tech。解決的問題是:讓 DSH 在需要人介入或跑完一輪時,彈一條歸屬正確、可點擊回到會話的桌面通知,避免人一直盯着窗口或錯過審批。

倉庫顯示 0 星,許可證 MIT,npm 包名 dsh-native-notifications。

觸發哪些事件

插件監聽以下 Harness 事件,事件含義和默認開關見 README 的表格:

Harness event 橫幅內容 默認
agent/status → idle after a turn(root session) 任務完成 · 用時 … on
approval/request 在 approvalDelayMs 後仍掛着 需要你確認權限 · tool · reason on
user-questions/request 仍掛着 正在等待你的選擇 · question on
agent/error 執行出錯 · message on
deepseek-account/model-sign-in-required / session-expired 需要登錄 / 登錄已過期 on
subagent/end、workflow/end child agent / workflow finished off

橫幅標題用會話名稱,正文示例:

<會話名稱>
任務完成 · 用時 5 分 43 秒,可以回來查看結果了。

幾個防噪邏輯:

  • 被自動處理掉的審批(例如 Auto 權限預設裏的 LLM reviewer)不會響,橫幅會延遲,只在請求還在等你時觸發。
  • 出錯之後那一輪完成的通知被抑制,一次失敗不會響兩次。
  • 目標輪次和後續 turn 很快回到 running,完成通知要在會話空閒超過 idleGraceMs 後才觸發。
  • 隊友、子代理和 workflow 子進程按 onlyRootSessions 過濾,多智能體長跑只在 root session 真結束時響一次。

鈴聲配置

鈴聲由插件用 Web Audio 合成,沒有音頻文件,也不用系統默認音,系統音會被抑制,不會響兩次。所有預設共用同一套動機,含義可辨:完成是上行的 do-mi-so,”需要你”是兩聲高頻短音,出錯下行。

打開 Settings → General → Notification sound,可選預設:

preset 音色
Playful bubbles(默認) triangle 主體,帶小幅上滑和一個高音閃爍
Soft bell sine 主體,加一個輕的八度泛音
Bright pluck 短 triangle 撥絃,沒有滑音
Custom 自己的音符序列,用 playful 音色播放
Muted 無聲

這一行有 Preview 按鈕。Custom 用文本框輸入,最多八個以空格或逗號分隔的音符,可以是音名(C6 E6 G#6、Bb5)也可以是頻率(1046.5 1318.5):

C6 E6 G6          ← do-mi-so
G6 G6             ← double boop
1046.5 1318.5     ← 同上兩個音符的頻率寫法

偏好存頁面 localStorage 的 dsh-native-notifications:sound,所以是按設備/瀏覽器生效的,下一次橫幅即生效,不需要走 Host 往返。

安裝與啓用

安裝命令來自倉庫 README,按 profile 區分 Web 和桌面:

# from GitHub
dsh plugin --profile web add github:tommy00748-tech/dsh-native-notifications
dsh plugin --profile desktop add github:tommy00748-tech/dsh-native-notifications

# from npm(npm 發佈後可用)
dsh plugin --profile web add dsh-native-notifications

# from a local checkout
dsh plugin --profile desktop add link:/absolute/path/to/dsh-native-notifications

裝完在 Settings → Plugins 確認 desktop-notifications 那一行是啓用的,bundle patch 會插入並默認啓用它。沒有構建步驟、沒有依賴、沒有原生模塊:Host 半部分是普通 ESM,Client 半部分是一個純 JS bundle。

要求:

  • 有提供 Web UI 的 DSH profile(desktop 或 web);
  • 頁面在安裝時自動加載 Client 半部分(Host graph 重建會同步給已連接的頁面);如果手工拷貝後橫幅一直沒出現,重載一次窗口;
  • 操作系統裏要爲 DeepSeek Harness 允許桌面通知(macOS 在 System Settings → Notifications)。Electron 會授予頁面權限,但 OS 層面的允許是獨立的。

配置項

所有開關都在那一行的 config 上,默認值連同說明寫在 cordis.patch.yml 裏。注意 patch 會整體替換 config,所以只想改一個字段時要把想保留的字段一併寫回去:

- id: desktop-notifications
  config:
    notifyComplete: true
    notifyQuestion: false      # do not ring for questions
    idleGraceMs: 2000
    onlyRootSessions: true
    delivery: client           # client | osascript | both

可用字段:notifyComplete、notifyApproval、notifyQuestion、notifyError、notifyAccount、onlyWhenUnfocused、silent、idleGraceMs、errorSuppressMs、approvalDelayMs、onlyRootSessions、notifyOnMount、logPath。

delivery: osascript 是給頁面無法展示 Web 通知的宿主的遺留回退,macOS 下這類橫幅歸屬到 Script Editor,默認關閉。

診斷日誌

每次橫幅和每次客戶端上報都會追加到審計日誌,默認 ~/.dsh/dsh-native-notifications.log,可用 logPath 改路徑。日誌樣例:

2026-11-05T08:58:26.102Z mounted :: pid=9027 :: delivery=client :: epoch=... :: platform=darwin
2026-11-05T08:58:26.178Z client :: boot :: permission=granted protocol=dsh-app: path=/ visibility=hidden sound=cute chime=v5-robust
2026-11-05T08:59:47.177Z banner :: 能不能做個DSH原生的通知插件 :: 任務完成 · 用時 5 分 43 秒,可以回來查看結果了。
2026-11-05T08:59:47.186Z client :: shown :: kind=complete permission=granted
2026-11-05T08:59:47.188Z client :: sound :: kind=complete preset=cute

針對”爲什麼沒彈橫幅”,按日誌判斷:

  • 沒有 client :: boot → Client 半部分沒加載,重載窗口;
  • client :: permission :: denied → 系統/瀏覽器不允許通知;
  • client :: suppressed → onlyWhenUnfocused 跳過了已聚焦的窗口;
  • 有 banner :: 但沒有 client :: shown → 頁面沒輪詢到(看 poll-failed / unauthorized);
  • 有 client :: shown 但沒有 client :: sound → 鈴聲沒響(音頻仍被鎖,或靜音了)。

想直接發一條通知驗證 osascript 通道:

node scripts/notify-test.mjs "title" "body"

工作原理

一個 bundle,兩半:

  • Host(index.js)監聽上面那些事件,維護一個小的環狀緩衝區存橫幅事件。它在 ctx.webServer 上提供兩個同源路由:/native-notifications/events(長輪詢)和 /native-notifications/report(客戶端診斷),和 Host 其他 Web 路由一樣用 ctx.connection.requestRejection 做門禁,所以只有已認證頁面能讀。
  • Client(client.js,無渲染、始終掛載)長輪詢這兩個路由,通過平臺通知 API(new Notification(...))展示每個事件,點擊時聚焦 DSH 並調用 uiWorkspace.openSession(sessionId)。游標和 Host epoch 存在 localStorage,所以重載不會重放舊橫幅,Host 重啓從”現在”開始。

長輪詢在 wait + 10s 後中斷並重試,所以 Host 重掛不會卡住客戶端。插件不追加 session 事件、不 import Harness Client 包,只貢獻一個 bundle 行和一個 Settings 行。

兼容性

README 標明在 dsh 0.2.1-rc.5 和 0.2.2-rc.1 上測試過。運行時兼容性檢查讀的是頂層 engines.dsh 字段,package.json 裏是 >=0.2.1-rc.5 <0.3.0,Node 要求 >=20。

適用場景與注意

適合需要在 DSH 上跑長任務、又不想一直守着窗口的人,以及團隊裏跑多智能體長任務、希望只在 root session 結束時響一次的場景。如果你的宿主頁面無法展示 Web 通知,delivery: osascript 是備選,但要接受橫幅歸屬到 Script Editor。

兩點提醒:通知以當前 DSH 進程的權限發出,OS 層面要爲 DeepSeek Harness 打開通知授權;插件來源是社區維護的 GitHub 倉庫(社區目錄站上也有它的條目,該目錄與 DeepSeek / 幻方無官方從屬關係),裝之前建議先過一遍源碼和 MIT 許可證。

結尾

一句話回顧:它把 DSH 的審批、提問、完成、出錯和登錄橫幅歸到 DeepSeek Harness 名下,可選或自定義合成鈴聲,並提供審計日誌方便排查沒響的原因。目錄頁在 https://www.skillhub.cn/plugins/tommy00748-tech/dsh-native-notifications,倉庫在 https://github.com/tommy00748-tech/dsh-native-notifications。

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

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

小夜