前言¶
DSH 自帶 @deepseek-ai/dsh-schedule 這套「自動化任務」,但它是排期提醒:到點把一條消息投回任務綁定的會話,用那個會話的歷史繼續幹活。回執只表示「消息進了收件箱」,不表示模型執行完成,也沒有暫停和手動運行。
下面介紹的 dsh-routines(維護者 leinaldo,分類「工作流」)把語義換成任務運行器:到點新開一個對話跑一輪,跑完有狀態、耗時、步數和 token 回執,可以回看那輪會話。目標是照 Claude 桌面 App 本地定時任務(Routines / CCD scheduled tasks)的行爲,給 DSH 補一套定時任務。
這是什麼¶
一句話定位:一個 DSH 插件,用一份 JSON 索引管理定時任務,每次觸發都新建會話、獨立上下文跑一輪。
解決的實際問題是——內置提醒到點只投遞消息,你不知道模型到底跑沒跑完、跑得怎麼樣;而 dsh-routines 把這一輪當成一次真正的運行來記賬,失敗、超時都能查到。
與內置自動化任務的區別¶
| 維度 | @deepseek-ai/dsh-schedule(內置) |
dsh-routines(本插件) |
|---|---|---|
| 運行位置 | 投回綁定會話,複用其歷史 | 新建會話,每輪獨立上下文 |
| 執行回執 | 只表示消息進入收件箱 | turn/end 後記錄狀態/耗時/步數/token |
| 手動運行 | 無 | 「立即運行」,不改排期 |
| 停用/啓用 | 無 | 支持 |
| 一次性任務 | 無 | 支持,跑完自動停用 |
因爲每輪不共享上下文,任務裏那條指令(prompt)必須自包含——寫清楚要做什麼,不要指望它會讀到上一次的對話。
調度與運行語義¶
調度能力:
- cron:五字段,本地時區;支持
*、a、a-b、a-b/n、列表、月份和星期英文縮寫。 - 一次性:ISO 時間點,只允許未來時間;跑完自動停用;超過 7 天未跑的到點任務直接停用。
- 僅手動:cron 與一次性都不填,只保留在列表裏,點「立即運行」。
- 心跳:啓動立即掃一次,之後每 60 秒掃一次。
- 補跑:錯過時在
max(創建時間, 7 天前, 啓用時刻)之後找最近一個槽補跑一次;遲到超過 2 分鐘標記爲missed。 - 抖動:cron 任務派發延遲 =
sha256(taskId) % (min(10, 相鄰間隔-1) * 60)秒,同一任務恆定,避免整點同時觸發。 - 重試:建會話或投遞失敗按 5/15/30 分鐘重試,最多三次;模型回合失敗不重試。
- 併發:同一任務同時只跑一次。
運行一輪的過程:
ctx.sessionController.create({ cwd })新建會話,工作目錄取任務配置的,否則取最近會話的。resolveAgent後把標題改成「任務名 · 月-日 時:分」;會話 id 記進隱藏名單,從左側列表過濾掉。- 訂閱
session/event,投遞指令,等turn/end:reason.kind === "completed"記成功,其餘(error、blocked、aborted、timeout等)記失敗並保留原因;45 分鐘沒結束按超時失敗處理。 - 運行記錄寫進索引,每個任務保留最近 50 條。
- 任務由對話裏的工具創建且開着通知時,跑完向創建它的那個會話發一條完成/失敗消息;面板建的任務沒有創建會話,不發。
狀態只存在一個文件裏:
~/.dsh/routines/
scheduled-tasks.json # 任務索引:名稱、描述、指令、調度、運行記錄
舊版本寫在 <taskId>/SKILL.md 正文的任務,讀取索引時會自動搬進 prompt 並刪掉目錄。
安裝與啓用¶
從插件市場安裝,索引源是作者自己用 GitHub Pages 提供的:
https://leinaldo.github.io/dsh-routines/market/index.json
- 打開 插件 → 發現 → 添加索引源,填上面的 URL。
- 在列表裏找到 定時任務,點 安裝。
- 重啓 DSH,左側欄出現「定時任務」。
本地開發方式:
~/.dsh/plugins/dsh-routines
- 把倉庫目錄放到
~/.dsh/plugins/dsh-routines。 - 在
~/.dsh/profiles/desktop/package.json的dependencies加"dsh-routines": "file:/Users/leinaldo/.dsh/plugins/dsh-routines"(路徑按本機調整)。 - 在同一個文件的
dsh.profile.bundles末尾加"dsh-routines"。 - 在 profile 目錄執行
pnpm install,然後重啓 DSH。
宿主代碼在啓動時加載,改完必須重啓才生效;客戶端面板隨頁面刷新重載。
典型用法¶
在側邊欄面板裏操作:「新建」填名稱、描述、指令、調度方式、工作目錄;卡片上「立即運行」不改排期,只推 lastRunAt;「停用」只停自動派發,停用後手動運行也會被拒絕。「運行記錄」展開後每條都有狀態、時間、耗時、token、摘要與「查看會話」,點進去就是那次運行的會話——運行會話不出現在左側列表,只從這裏進入。
讓模型直接建任務,不必先開面板:
| 工具 | 作用 |
|---|---|
routine_create |
建任務:name、prompt 必填,cron_expression / fire_at / cwd / notify_on_completion 可選 |
routine_list |
列出所有任務、下次運行時間與指令 |
routine_update |
只改傳入的字段;enabled:false 停用 |
routine_delete |
刪任務連同運行記錄 |
routine_run |
立即跑一次,不改排期 |
在對話裏說「每天 12 點幫我總結 AI 資訊」時,模型會按工具描述在內置 schedule_* 與本插件之間選。想穩定走本插件,點名「用定時任務建」,或直接說「每次新開對話跑」。
HTTP 接口(面板底層就是這些):
| 方法 | 路徑 | 說明 |
|---|---|---|
| GET | /dsh-routines/tasks |
任務列表視圖(含下次運行、最近一次狀態、運行中標記) |
| GET | /dsh-routines/task?id= |
單個任務(含 prompt)與全部運行記錄 |
| GET | /dsh-routines/defaults |
默認工作目錄 |
| POST | /dsh-routines/tasks/create |
{name, description?, prompt, cronExpression?\|fireAt?, cwd?, notifyOnCompletion?} |
| POST | /dsh-routines/tasks/update |
同上字段 + id,另支持 enabled、disableJitter |
| POST | /dsh-routines/tasks/delete |
{id},任務文件與運行記錄一起刪 |
| POST | /dsh-routines/tasks/run |
{id},立即運行(不改排期) |
適用場景與注意¶
適合這些情況:已經有一個想在固定時間跑的獨立任務,希望每輪都是乾淨上下文、跑完能查回執;或者想用一次性任務做「跑到點就不動」的提醒。
幾個需要留意的點:
- 插件以當前 dsh 進程權限運行,裝之前應先讀一遍源碼和許可證(MIT,見倉庫
LICENSE)。 - 需要審批的任務會停在審批卡上,直到超時記失敗——沒有無人值守審批策略。
- 沒有系統通知,只有發給創建會話的完成消息和麪板狀態;也沒有費用字段,DSH 宿主只暴露 token,不暴露價格。
- 運行會話的隱藏只做在網頁端,代價是名單更新依賴這套客戶端代碼,宿主改列表實現時要跟着改。
- 存儲根目錄只取
DSH_HOME或~/.dsh,不讀ctx.baseDir——GUI 啓動時後者常是/,會導致面板永遠讀到空索引。
小結¶
dsh-routines 把 DSH 的定時動作從「提醒投遞」升級爲「運行記賬」,調度語義、補跑和抖動都按 Claude Routines 對齊,代價是指令必須自包含、每輪新開會話。
- 目錄頁:https://www.skillhub.cn/plugins/leinaldo/dsh-routines
- GitHub:https://github.com/leinaldo/dsh-routines