dsh-hooks:爲 DeepSeek Harness 聲明式接入生命週期鉤子

前言

在 DSH 的插件化工作方式裏,很多自動化需求並不複雜:一輪對話結束後發通知、某個工具被調用時寫日誌、審批請求出現時彈桌面提示。這些動作通常需要監聽事件、解析上下文、再執行命令或通知。dsh-hooks 把這類邏輯放在 profile 配置裏聲明:在 cordis.patch.yml 中寫清楚事件、匹配條件和要執行的 run 或 notify,不需要額外寫插件代碼。

這是什麼

dsh-hooks 是一個由 PeterBon 維護、採用 MIT 許可的 DeepSeek Harness 插件。它的定位是 config-driven lifecycle hooks:用配置聲明 event -> command/notify 的鉤子。

它包含兩部分:

  1. 鉤子引擎:根據配置監聽 DSH 事件,並執行命令或內置通知。
  2. Web GUI 設置頁:安裝後,dsh web 的設置面板會增加 Hooks 區域,提供歷史時間線、手動測試、notify 測試、hook editor 和 Feishu connect。

核心能力

下面列出 dsh-hooks 的主要能力:

  1. 在 profile 的 cordis.patch.yml 中聲明 event -> command 或 event -> notification 鉤子。
  2. 不需要編寫插件代碼,配置即可觸發命令或通知。
  3. 一個包同時提供鉤子引擎和 Web GUI 設置頁。
  4. Web GUI 設置面板增加 Hooks 區域,包括 history timeline、manual tester、notify tests、hook editor 和 Feishu connect。
  5. 內置通知渠道:
    - desktop:平臺氣泡/提示。
    - webhook:向 HTTP endpoint 發送 JSON,可配置 slack: true 生成一行摘要。
  6. 支持以下事件:
    - turn/start
    - turn/end
    - tree/settled
    - step/end
    - tool/call
    - tool/result
    - user/message
    - approval/asked
    - approval/decided
    - session/title
    - session/created
    - session/disposed
    - agent/created
    - agent/disposed
    - agent/error
    - agent/status
    - hook/failed
  7. 上下文通過 DSH_HOOK_* 環境變量傳遞;如果配置 input: stdin,完整 context JSON 會寫入命令 stdin。

安裝與啓用

dsh-hooks 要求 Node.js:

node >=22

安裝插件可以從 npm 添加:

dsh plugin --profile web add dsh-hooks

也可以直接從 GitHub 倉庫添加:

dsh plugin --profile web add github:PeterBon/dsh-hooks

安裝後,需要重啓 dsh web。重啓完成後,設置面板會增加 Hooks 區域,用於查看和配置鉤子。

基本配置

配置寫在 profile 的 cordis.patch.yml 中。下面是幾個典型條目:

- id: dsh-hooks
  name: dsh-hooks
  config:
    hooks:
      - on: 'turn/end'
        when: 'completed'
        run: 'node examples/notify-feishu.mjs'
        timeoutMs: 10000

      - on: 'approval/asked'
        notify:
          channel: 'desktop'

      - on: 'turn/end'
        when: 'completed'
        notify:
          channel: 'webhook'
          url: 'https://hooks.slack.com/services/…'
          slack: true

      - on: 'tool/call'
        match:
          tool: '^(rm|git|ssh)'
        run: 'node examples/notify-webhook.mjs --slack'

上面的配置做了四件事:

  1. 當 turn/end 以 completed 結束時,執行 node examples/notify-feishu.mjs。
  2. 當出現 approval/asked 時,發送桌面通知。
  3. 當 turn/end 完成時,通過 webhook 發送通知,並使用 Slack 風格的一行摘要。
  4. 當模型請求匹配 rm、git、ssh 的工具調用時,執行 webhook 通知腳本。

配置字段

dsh-hooks 的 hook 字段覆蓋事件觸發、條件過濾、執行方式、通知、重試、併發和防抖。常見字段如下:

  1. on:觸發事件名,例如 turn/end、tool/call、approval/asked。
  2. when:過濾 turn/end 的結束原因,例如 completed。
  3. match:對上下文字段做條件過濾,例如按工具名正則匹配。
  4. run:要執行的命令。run 和 notify 二選一。
  5. notify:內置通知,支持 channel: desktop 和 channel: webhook。
  6. input:控制上下文傳遞方式。使用 stdin 時,會把完整 context JSON 寫入命令 stdin。
  7. timeoutMs:單條命令的超時時間,單位是毫秒。
  8. retries:對非零退出碼的重試次數。
  9. retryDelayMs:重試間隔,單位是毫秒。
  10. enabled:設爲 false 時,配置保留但不觸發。
  11. cwd:命令工作目錄,可以是 session 或絕對路徑;僅用於 run。
  12. maxConcurrent:同一 hook 的最大併發進程數。
  13. debounceMs:高頻事件的防抖窗口,單位是毫秒。

典型用法

1. 執行命令

當某個事件發生時,執行本地命令:

- on: 'turn/end'
  when: 'completed'
  run: 'node examples/notify-feishu.mjs'

這條配置在 turn/end 且結束原因爲 completed 時,啓動 node examples/notify-feishu.mjs。

2. 使用桌面通知

當審批請求出現時,直接發送平臺氣泡/提示:

- on: 'approval/asked'
  notify:
    channel: 'desktop'

這條配置不需要額外腳本,直接由 dsh-hooks 的內置通知處理。

3. 使用 webhook 通知

將事件信息 POST 到 HTTP endpoint:

- on: 'turn/end'
  when: 'completed'
  notify:
    channel: 'webhook'
    url: 'https://hooks.slack.com/services/…'
    slack: true

如果目標是 Slack,可以配置 slack: true,發送一行摘要。

4. 按工具名過濾

只監聽匹配特定工具名的 tool/call:

- on: 'tool/call'
  match:
    tool: '^(rm|git|ssh)'
  run: 'node examples/notify-webhook.mjs --slack'

這裏的 match.tool 是一個正則表達式,用於過濾模型請求調用的工具名。

5. 通過 stdin 傳遞完整上下文

默認情況下,上下文通過 DSH_HOOK_* 環境變量傳遞。如果腳本需要完整 JSON,可以使用:

- on: 'turn/end'
  input: 'stdin'
  run: 'node my-hook.mjs'

配置後,完整 context JSON 會寫入 node my-hook.mjs 的 stdin。

6. 控制重試

對非零退出碼進行有限次後臺重試:

- on: 'turn/end'
  when: 'completed'
  run: 'node examples/notify-feishu.mjs'
  retries: 2
  retryDelayMs: 1000

這裏的重試只針對非零退出碼。spawn 失敗和超時不會進入重試。

7. 控制併發與防抖

對高頻事件,可以限制併發並做防抖:

- on: 'step/end'
  run: 'node examples/log-step.mjs'
  debounceMs: 500
  maxConcurrent: 2

debounceMs: 500 會在 500 毫秒窗口內合併高頻觸發;maxConcurrent: 2 會限制同一 hook 的併發進程數。超出上限的觸發會被丟棄,並記錄爲 skipped。

8. 臨時禁用某條 hook

不想刪除配置時,可以保留聲明並關閉它:

- on: 'turn/end'
  enabled: false
  cwd: 'session'
  run: 'node examples/log-turn.mjs'

enabled: false 表示這條 hook 不觸發,但配置仍然保留。cwd: session 表示命令在 session 的工作目錄中運行。

行爲說明

dsh-hooks 的執行模型偏向“觸發外部動作,但不阻塞主流程”:

  1. 命令執行是 fire-and-forget。
  2. 命令失敗只會 console.warn,默認不會阻塞 DSH 的 agent loop。
  3. run 和 notify 必須二選一。
  4. retries 只用於非零退出碼的後臺重試;spawn 失敗和超時不重試。
  5. maxConcurrent 限制同一 hook 的併發進程數;超出上限的觸發會被丟棄並記錄爲 skipped。
  6. cwd 僅用於 run,可以設爲 session 或絕對路徑。

依賴與許可證

dsh-hooks 的 package 信息中包含以下 peer dependencies:

@deepseek-ai/cordis
@deepseek-ai/dsh-session
@deepseek-ai/schemastery
react

運行時要求:

node >=22

許可證爲 MIT。

適用場景

dsh-hooks 適合這些場景:

  1. 希望把 DSH 生命週期事件接到本地腳本或通知系統。
  2. 需要在 turn/end、tool/call、approval/asked 等事件發生時執行輕量自動化。
  3. 希望發送桌面通知、Slack 風格 webhook 通知,或調用自研腳本。
  4. 不想爲一次事件監聽額外維護插件代碼,希望直接在 profile 配置裏管理。

需要注意:插件中的 run 命令會以當前 DSH 進程擁有的權限執行。安裝前建議檢查源碼、示例腳本和許可證,並確認要執行的命令不會執行危險操作。

結尾

dsh-hooks 的價值在於把 DSH 生命週期事件轉成低代碼的自動化入口:配置 cordis.patch.yml 後,就能在 turn、step、tool、approval、session、agent 等事件上執行命令或發送通知,同時通過 dsh web 的 Hooks 設置頁進行管理和測試。

相關鏈接:

  1. GitHub 倉庫:https://github.com/PeterBon/dsh-hooks
  2. 插件目錄頁:當前資料未提供獨立 URL;安裝後可在 dsh web 的設置面板中查看 Hooks 區域,或在當前 DSH 插件目錄入口中檢索 dsh-hooks。
羽毛球分组比赛记分
小程序二维码

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

小夜