前言¶
用 DSH 跑長任務時,常見三個麻煩:會話列表裏分不清哪個是哪條;進程停下來等人拍板時,那個「點」散在日誌或輸出裏;以及你不在時,例行問題要麼堆着要麼被自動放過。下面介紹的 dsh-watchkeeper 就是針對這三點的插件。它把會話編號、人工待答、可插拔評審這三件事收到一個 watch 循環裏,由 Maravetech 維護,歸在 DSH 社區插件目錄的「工作流」分類下。
這是什麼¶
一句話定位:dsh-watchkeeper 是一個 DSH 插件,替你守着無人值守的會話——給每個會話一個穩定編號、把需要人拍板的 decision card 集中到一個待答視圖、並允許用可插拔的 judge 代答例行問題。
開源、純 JavaScript、無構建步驟。倉庫標註 Alpha,版本 0.2.0,插件 API 和配置在 1.0 前可能變化。許可證 MIT。
先做下面的事:確認你的 Node 大於等於 22.5,確認 DSH 版本落在 engines.dsh 聲明的範圍內;不滿足時 dsh plugin add 會直接拒絕安裝。
三個能力¶
可以按三件事理解它做了什麼。
會話編號¶
每個會話拿到一個穩定編號,顯示在會話列表該行開頭。編號從 1 遞增,重啓後會話仍保留原編號,只要 WATCHKEEPER_HOME 下的 ledger 沒丟。
待答席¶
需要人決策的卡片會收集到一個位置。你答一次,答案回送到發起那張卡片的會話。插件的卡片是包裹在 [DECISION_POINT] 與 [/DECISION_POINT] 之間的 JSON,且必須放在代碼圍欄外面。
看護循環與可插拔 judge¶
watch 循環裏配置的 judge 可以代答會話中途的例行提問。低置信度、輸出損壞、紅線話題始終轉給人。
插件明確區分了默認行爲:沒有配置 judge 就等於沒有任何自動決策卡應答;配置了 fallbackEnabled 也只是處理 judge 實際跑完後一小類不確定性結果,紅線情況和 judge 不可用仍轉給人。回覆提供方默認也是關閉的。
安裝¶
插件分兩部分:插件(宿主行爲)和 skill(agent 指令)。skill 只是解釋插件,不裝插件的話它不會做任何事。
插件¶
DSH 自己的插件命令已經轉發到 profile 目錄的 pnpm,並把插件註冊爲該 profile 的一個 bundle,所以不需要手工改 cordis.patch.yml。下面這行從 GitHub 安裝並固定到 tag:
dsh plugin --profile <your-profile> add github:Maravetech/dsh-watchkeeper#v0.2.0
要在本地克隆開發時,克隆後按目錄添加:
git clone https://github.com/Maravetech/dsh-watchkeeper.git
dsh plugin --profile <your-profile> add "file:$PWD/dsh-watchkeeper"
或者從 releases 下載 tarball,再 file: 安裝:
dsh plugin --profile <your-profile> add ./dsh-watchkeeper-0.2.0.tgz
需要完全固定到某個 commit,可用 github:Maravetech/dsh-watchkeeper#<commit-sha> 代替 tag。插件不依賴構建產物,所以不需要額外的 allowBuilds 項。
卸載:
dsh plugin --profile <your-profile> remove dsh-watchkeeper
裝完完全重啓 DSH。
skill¶
插件已經帶 skill,做一條符號鏈接放到 DSH 的 skills 目錄:
ln -s "$DSH_PROFILE_DIR/node_modules/dsh-watchkeeper/skills/dsh-watchkeeper" "$DSH_HOME/skills/dsh-watchkeeper"
想給 Claude Code、Codex 等其他 agent 只裝 skill,可以用 skills.sh 的 CLI(Node 22.20+):
npx skills add Maravetech/dsh-watchkeeper --skill dsh-watchkeeper -g
驗證¶
先查健康端點確認插件加載正常:
curl -s "$DSH_WEB_URL/watchkeeper/health" | python3 -m json.tool
沒有設 DSH_WEB_URL 時,用應用 URL 裏的端口,例如 http://127.0.0.1:62630/watchkeeper/health。
配置¶
配置走環境變量。最重要的三個:
WATCHKEEPER_HOME # 默認 ~/.dsh-watchkeeper,存放狀態、編號 ledger 和 SQLite 庫
WATCHKEEPER_JUDGE_CMD # judge 命令;不設則所有提問都轉給人
WATCHKEEPER_CONTROL_TOKEN # watch 控制 POST 路由的獨立 bearer token;不設則這些路由不可用
還有回覆提供方的二進制:WATCHKEEPER_CODEX_BIN、WATCHKEEPER_AGY_BIN、WATCHKEEPER_CUSTOM_CMD。完整的變量表、judge 契約、provider 命令見倉庫 docs/configuration.md。
用 HTTP 控制接口時,寫路由需要 WATCHKEEPER_CONTROL_TOKEN,否則返回 403;web host 必須使用字面量 loopback 地址。
典型用法:一張 decision card¶
卡片最小形態如下。要點是把 JSON 放在 [DECISION_POINT] 與 [/DECISION_POINT] 之間,且在代碼圍欄外:
{
"audience": "human",
"requires_user_response": true,
"human_review": [
{
"question_id": "q-1",
"question": "Ship with the current cover image or wait for the new one?",
"type": "卡點",
"reason": "The new image is not approved yet.",
"manual_reason": "必要信息",
"blocking_scope": "Publishing is blocked until this is answered.",
"attempts": ["Checked the asset folder; the new image is still missing."],
"background": "The current image is usable but older.",
"recommendation": "Ship with the current image.",
"options": ["Ship with the current image", "Wait for the new image"],
"state": "needs_user",
"audience": "human",
"requires_user_response": true,
"agent_can_resolve": false,
"already_resolved": false
}
]
}
字段規則、選項寫法和常見錯誤在 docs/decision-cards.md。
出錯時從哪查¶
先看健康端點,再看落盤狀態,最後讀插件日誌:
curl -s "$DSH_WEB_URL/watchkeeper/health" | python3 -m json.tool
ls "$WATCHKEEPER_HOME"
ls "$WATCHKEEPER_HOME/state"
tail -n 50 "$WATCHKEEPER_HOME/probe.log"
如果卡片沒出現,通常是卡片被放進了代碼圍欄、缺少 [DECISION_POINT] 包裹,或者缺了必需字段。
適用場景與注意¶
適合這類人:用 DSH 跑長任務或需要人值班的會話,希望會話有可追溯編號、決策點集中到一處,並且把例行問題交給可替換的 judge、把關鍵問題留給自己。
兩點要先說清。其一,插件作爲該 profile 的 bundle 在 DSH 進程內運行,等於以當前 DSH 進程的權限執行;裝之前建議把源碼讀一遍(倉庫是純 JS、無構建步驟,可以直接讀 index.js、lib/ 和 cordis.patch.yml),並確認許可證。其二,它面向的是無人值守場景,自動化程度由 judge 和 provider 配置決定;默認是「沒有人就沒有自動決策」,所以先按默認值跑,再逐步放開。
小結¶
dsh-watchkeeper 解決的是無人值守時的三件小事:會話可編號、決策點有去處、例行問題可代答、關鍵問題必停給人。源碼與文檔在 GitHub:https://github.com/Maravetech/dsh-watchkeeper,社區目錄頁:https://www.skillhub.cn/plugins/Maravetech/dsh-watchkeeper。