前言¶
DeepSeek Harness 的理念是「一切皆插件」,會話本身也是可以被插件操作的對象。問題在於:當你用 DSH 跑一個看起來比較大的任務,比如「把上個版本的迴歸排查掉、順手把 Lint 清理一遍」,通常的做法是在一個會話裏塞滿上下文,或者讓模型在會話內派生子代理。前者很快到壓縮邊緣,後者隨父會話的輪次結束消失,用戶既不能手動拉起,也不能接管。
下面介紹的 dsh-session-relay 走的是第三條路:不包裝子代理,而是把多個平級的根會話編成一組,其中一個作爲主會話(協調者)負責版本線和看板結論,其餘作爲工作會話各自背自己的上下文。主攻方向是「一個主會話協調多個工作會話」,附帶版本線公告、指令模板、彙報合併喚醒、任務看板覈對、會話檢查與主會話交接。插件由 SunsetRNE 維護,開源協議 MIT,當前版本 2.0.0,屬於社區目錄 SkillHub 上「工作流」分類下的條目。
它是做什麼的,以及爲什麼不直接用任務板¶
README 裏把邊界講得很清楚:單個會話的上下文有限,構建號到 300+ 之後,一個會話同時背版本線、看板、代碼、測試和彙報會很快到壓縮邊緣,早期約束和證據會丟。平級會話每個都有自己的上下文窗口,可以分別承擔調查/分析/解決/驗證/彙報,主會話只保留版本線、看板結論和合並判斷。
對比 DSH 原生子代理:子代理由模型在會話內派生、掛在父會話樹裏,用戶不能從側邊欄手動拉一個「幫我調查」的子代理,插件也不直接打開子代理——subagent routing 是宿主獨佔的。平級會話是用戶可見、可點開、可喚醒/接手/改派的根會話,出問題能直接接管,做完留下可審計的彙報和提交。插件不綁定模型廠商,只依賴 DSH 的會話與工具接口,因此 Claude、GPT、DeepSeek 等 DSH 能配置的模型都能當主會話或工作會話,也可以混用。
運行環境與安裝¶
它要求宿主是 DeepSeek Harness 0.2.2-rc.1 及以上。package.json 裏 engines.dsh 與 peerDependencies 的寫法是:
"engines": {
"dsh": ">=0.2.2-rc.1 <0.3.0-0 || >=0.2.3-rc.1 <0.3.0-0 || >=0.2.4-rc.1 <0.3.0-0"
}
README 解釋了爲什麼要寫成顯式預發佈分支:node-semver 只放行「範圍裏有同元組且帶預發佈標籤的比較符」的預發佈版本,否則 0.2.3-rc.1 這類會被靜默排除、安裝時撞 ERESOLVE。插件依賴的 @deepseek-ai/dsh-* 包由宿主提供,不單獨安裝。更老的宿主只保留基本功能,官方「更改請求與工作樹」(forge)相關的工作樹識別、聲明外置不再保證可用。
安裝不需要 npm 賬號。在 DSHA 的插件管理器裏任選一種來源:
- GitHub Release(推薦,固定版本):倉庫
SunsetRNE/dsh-session-relay的 Release,每個版本附一個dsh-session-relay-<版本>.tgz。 - 倉庫鏈接:
https://github.com/SunsetRNE/dsh-session-relay裝 main 最新提交;指定版本用https://github.com/SunsetRNE/dsh-session-relay/tree/v<版本>。 - 本地壓縮包:下載 Release 附件後導入。
需要注意:DSH 進程內加載的插件以當前進程權限運行,安裝前應自行檢查源碼與 MIT 許可證。非 DSHA 環境下,依賴設備橋的功能(手機通知,讀 /root/.dsh/.bridge_headers 與 /root/.dsh/.bridge_port)不可用。
核心能力¶
插件提供一個 /relay 命令,完整用法見 /relay help。下面只列 README 中明確寫到的場景。
分工模型¶
主會話協調,工作會話用 peer_report 彙報,彙報被批量合併成一次喚醒,避免每條彙報都醒一次主會話。全名叫「平級」會話互通,指的就是這個結構:所有參與方都是同一層根會話,沒有父子層級。
模型工具與命令¶
模型側暴露 14 個 peer_* 工具:peer_list、peer_report、peer_send、peer_spawn、peer_alias、peer_inspect、peer_tasks、peer_task、peer_mail,主會話另有 peer_line、peer_assign、peer_handoff、peer_ask_user、peer_watch。其中 peer_send 的 mode=interrupt 是主會話專用的 nudge(stop:true 用「停止並彙報」信封),取代了 1.4.0 的獨立工具 peer_interrupt。
用戶側命令覆蓋會話與協同:
/relay tasks
/relay task update --stage
/relay approve|reject
/relay inspect
/relay search
/relay repo
/relay sync
/relay task pr
/relay mail
/relay tpl save|list|show|rm
/relay wt <會話> [--from <基分支|提交>] [--name <名字>]
任務看板¶
任務與認領的事實源在插件數據目錄 tasks/<工作區>/,倉庫裏的 .agents/TASKS.md 與 claims/ 是隻讀導出快照。寫操作是 /relay task new|claim|takeover|handoff|release|done|abandon|update,模型側用 peer_task。1.9 起支持任務派發:peer_task action=split 拆父子任務(可串行依賴),action=dispatch 按任務/子樹喚醒持有者或拉起新會話,依賴未完成不派,父任務在子任務全結束後自動完成。1.10 的任務庫維護提供 /relay task import --force(把手改過的導出快照重新導入,覆蓋前備份)、/relay task export,並帶兩個容量閾值:活動庫超過 taskStoreMaxActive(默認 500)歸檔最老的終態任務,TASKS-archive.md 超過 taskArchiveMaxBytes(默認 1 MiB)把最老的整段移入 tasks-archive.jsonl 冷存。
通知與背壓¶
2.0 引入協作郵箱:覈驗成功這類公共通知只寫進工作區郵箱 mailbox.json,同一會話 5 分鐘窗口內的多條通知合併成一條短通知,需要細節時用 peer_mail read,主會話可用 send/force 推送。用戶可用 /relay mail 看未讀、讀全文、歸檔,並查看最近 7 天「短通知 / 全文」統計。
通知取走有時限和背壓機制,這部分規則比較細:
peer_send默認 3 分鐘超時,timeout可自定義 90s/5m/2h,範圍 10 秒–24 小時;對方實際取走消息(由 DSHuser/message事件按 id 確認)時只銷賬、不再給發送方發回執,避免多喚醒一輪。- 消息一直排隊、超過時限仍未取走時,對方正在運行就由插件把原消息插進當前輪;對方不在運行或
mode=queue才提醒發送方,並給出強制通知(priority:"urgent")或撤回(action=withdraw)的下一步。 - 每個會話待收消息到 8 條時拒絕普通發送(steer 可插隊);待收 ≥4 條或最早一條 ≥5 分鐘標落後,≥30 分鐘標卡住。
peer_list、看板和側欄卡片都會顯示「待收 N」。 - 明確不用回覆的待命通知用
expect_reply:false或/relay --no-reply;普通 followup 排隊超過 60 秒自動升級爲 steer。/relay all會跳過待收落後/卡住的會話並在結果裏列出。
工作區定位與主會話交接¶
右側邊欄「協作」標籤會顯示每個會話的目錄、分支、是否在 git 工作樹裏、從哪個分支哪個提交分叉,只讀、按目錄緩存 60 秒。/relay wt 走官方工作樹服務給會話建分支與新目錄並切過去,宿主沒啓用該功能時明確報錯。交接流程分交給次確認與歷史兩類,主會話交接也可以通過 peer_handoff 與 /relay 命令觸發。
指令模板與全文搜索¶
2.0 T3 加了兩層:/relay tpl save|list|show|rm 管理指令模板(設置頁同一份存儲,可編輯、重命名、刪除、複製用法,模板名小寫校驗),/relay search [--in|--re|--case|--kind|--tool|--turn|--limit] <內容> 搜本工作區最近 25 個會話的原始日誌,按會話分組顯示命中。這兩項都只由用戶操作,模型沒有調用入口。
GitHub 集成(默認關)¶
GitHub 部分全部默認關閉,且刻意把寫入權留在用戶手裏:
/relay repo只讀探測 origin 倉庫能力(issues/projects/合併方式/分支保護/sub-issues),倉庫開關按owner/repo存,只由用戶用/relay repo on|off <開關>或協作面板點開,模型沒有寫入口,開關改動寫本地審計。issues開關打開後,任務變化單向投影成 GitHub issue(marker 冪等、unknown 退避重試、重啓恢復),配套closeOnTerminal、labelSync(維護relay:*標籤)、mapIssues(sub-issues 不可用時降級爲父票正文 tasklist)。用戶命令/relay sync status|flush|backfill|retry|detach|on|off。projectStatus開關打開時,任務詳情按需讀該任務 issue 的 GitHub Projects Status(只讀、2 分鐘緩存),並可在任務詳情裏點「寫回 Projects」由用戶寫 Status;匹配不到選項不寫。- 任務 PR 只讀:
/relay task pr <任務號> <PR 號|URL>把任務關聯到 PR,只讀展示 state、可合併性、審批決定、checks,不代開 PR、不代合併,PR 狀態不會自動改任務階段或審批。
典型用法¶
假設你在 /root/relay-demo 這個工作區,下面這組步驟來自 README 的命令面,用於走通「建任務 → 派發 → 彙報 → 審批」這條鏈路。
先建任務並指派:
/relay task new --title "排查上版本回歸"
/relay task claim <任務號>
主會話想拆父子任務並派發給工作會話,用模型側工具:
peer_task action=split <父任務號> --sub "確認失敗用例" --sub "修復與驗證"
peer_task action=dispatch <子任務號>
工作會話完成需要口頭彙報時:
peer_report <任務號> --status done --summary "失敗用例已收斂到 3 個,均爲環境時序"
主會話收到彙報只銷賬、不發消息,彙報在批量窗口內合併成一次喚醒。需要用戶拍板的走到審批:
/relay task update <任務號> --stage 待審查
/relay approve <任務號>
需要臨時喚醒一個正在跑的工作會話,主會話用 peer_send mode=interrupt;明確不用回覆的待命通知用 /relay --no-reply 或 expect_reply:false。
改完代碼想把這個會話挪到新分支上繼續,用 /relay wt:
/relay wt <會話> --from develop --name fix-regression
宿主沒有啓用官方工作樹服務時,這一步會明確報錯,不會退化成手動 git worktree add。
適用場景與注意點¶
適合這幾類情況:單個會話上下文已經喫緊、任務需要跨天跨版本追蹤、希望每個子目標有獨立的可見會話和可審計彙報、需要主動喚醒或接管某個正在跑的會話。插件只依賴 DSH 的會話與工具接口,模型廠商怎麼配都行。
需要注意的邊界:
- 主會話與工作會話是平級的根會話,插件不直接打開子代理,subagent routing 仍是宿主獨佔。
- 需要 DSH 0.2.2-rc.1 及以上;更老的宿主只保留基本功能,forge 相關工作樹識別、聲明外置不再保證可用。
- GitHub 寫入(issue 投影、Projects Status 寫回)默認關閉,只有用戶顯式打開開關並手動觸發才寫。
- 部分功能讀取 DSHA 容器內的
/root/.dsh/.bridge_headers與/root/.dsh/.bridge_port,非 DSHA 環境下手機通知等依賴設備橋的功能不可用。 - 插件以當前 dsh 進程權限運行,安裝前應檢查源碼與 MIT 許可證。
- 星標數較低(SkillHub 目錄頁顯示 0 星),採用前建議先跑一遍
/relay help與/relay reload確認行爲符合預期。
小結¶
dsh-session-relay 的價值不在於又造了一個任務板,而是把協作做在根會話之間:讓上下文各自獨立、彙報合併喚醒、待收隊列可見、交接可確認、GitHub 寫入留在用戶手裏。如果你在 DSH 裏已經開始用多個會話並行幹活,它會把這些會話從「各自爲戰」變成一支可以交接的隊伍。
目錄頁:https://www.skillhub.cn/plugins/SunsetRNE/dsh-session-relay
GitHub:https://github.com/SunsetRNE/dsh-session-relay