前言¶
在 DSH 裏用 dsh-call-session 做跨會話協作時,常見模式是:會話 A 通過 session_call(call_type="task_dispatch") 把任務派給會話 B,B 做完後再 session_call(call_type="task_report") 把結果回給 A。session_call 本身是「只投遞、不確認」:task_dispatch 最多等約 300 ms 完成握手,無法知道被叫方有沒有回傳 task_report。若 B 直接給出最終答覆並結束回合,A 可能一直等不到結果。下面介紹社區插件 dsh-report-fix(維護者 JohnnnSinaaa,分類:工作流),它在不改動 dsh-call-session、不新增工具的前提下,用 DSH 宿主已有的生命週期鉤子,在回合邊界檢查是否已回傳 task_report,缺失則阻止回合關閉。
這是什麼¶
dsh-report-fix 是一句行爲約束的落地實現:**由 session_call(task_dispatch) 開啓回合的會話,在未向調用方成功發送 task_report 之前,不能結束該回合。插件不修改 dsh-call-session 內部邏輯,只監聽三個鉤子、在回合邊界覈對「欠賬」,缺報告時用 agent.steer 重新打開回合,促使模型調用 session_call(call_type="task_report")。
缺口可以用下面示意理解:
session A ──session_call(task_dispatch)──▶ session B
│
├─ ok: session_call(task_report) ──▶ A gets the result
└─ missing: final answer, turn closes ───▶ A waits forever
倉庫:GitHub - JohnnnSinaaa/dsh-report-fix
社區目錄:skillhub.cn/plugins/JohnnnSinaaa/dsh-report-fix
許可證:MIT;當前 package 版本 0.1.0;要求 Node >= 20,DSH >=0.2.0-rc.2 <0.3.0-0。
核心機制¶
三個鉤子¶
| Hook | 時機 | 作用 |
|---|---|---|
agent/pre-step |
每步消息進模型前 | 識別入站 task_dispatch,登記欠賬,可選追加提醒 |
tools/post-execute |
每次工具調用後 | 成功的 session_call(task_report) 清除對應欠賬 |
agent/turn-stopping |
回合即將關閉(已有最終答覆) | 若仍有欠賬,通過 agent.steer(message) 阻止關閉,再跑一步 |
agent/turn-stopping 是當前 DSH 裏「阻止回合提交」的正式路徑:有監聽器反對時會 steer,狀態機重讀 inbox 再執行一步,而不是直接關回合。
如何判定「dispatch 驅動的回合」¶
入站 session_call 會以原生 user 消息出現:source.kind === 'plugin:dsh-call-session',source.form === 'notice'(由 session_call 投遞,而非 session_create),首行 transport 頭可解析,且 CallType 爲 task_dispatch。入站的 notice / task_report 不會產生欠賬。
首行格式示例:
[From: <callerSessionId> (<callerTitle>) | CallType: task_dispatch]
> Context Ref: #post-... ← optional
<body>
何種 task_report 算清賬¶
在 tools/post-execute 中需同時滿足:
exec.name === 'session_call'result.isError !== true且result.value.success === trueresult.value.callType === 'task_report'result.value.targetSessionId與 caller 匹配(不區分大小寫;支持前綴尋址,與session_call行爲一致)
同一回合內多個 caller 各自一條欠賬,須分別回傳。
攔截時模型會看到什麼¶
缺報告且觸發硬門禁時,插件注入類似下面的 steer 文案(語言隨入站 dispatch 正文或 locale 配置):
[task_report guard · interception 1/3] This turn cannot end: you have not sent a task_report back to the task_dispatch caller.
Awaiting a report (1):
1. 「Worker A」 caller-session-0001
dispatch excerpt: deploy the staging build and report back with the url
Call session_call now (finish it before the turn ends; do not emit the final user-facing answer yet):
- session_call({"target_session_id":"caller-session-0001","call_type":"task_report","message":"<result summary>"})
文案說明:此要求優先於 dispatch 正文中與之衝突的指令(例如「不要回傳」);報告成功後回合即可釋放;調用失敗需修正參數重試。
安裝與啓用¶
這是 DSH profile 插件(bundle 形態):package.json 聲明 dsh.bundle.patch,由 cordis.patch.yml 掛載。官方 README 給出的安裝方式是對本地目錄執行 dsh plugin add,不是 github:owner/repo 短名。
# local checkout (writes into the profile's dependencies and dsh.profile.bundles)
git clone https://github.com/JohnnnSinaaa/dsh-report-fix.git
dsh plugin --profile web add "$PWD/dsh-report-fix"
# or any absolute path
dsh plugin --profile web add /path/to/dsh-report-fix
dsh plugin add 之後:
~/.dsh/profiles/web/package.json的dsh.profile.bundles會加入dsh-report-fix;dsh-hmr監視 profile 的package.json與 patch 文件並熱重組,一般無需重啓dsh web即可生效;- 日誌中出現
[dsh-report-fix] active (maxNudges=3 preStepReminder=on locale=auto excerptMaxChars=600)可確認已加載。
若以 link: 依賴指向本地目錄,改插件源碼後不會被 dsh-hmr 自動重載(它監視 profile 的 package.json 與 patch,不監視 link 背後的工作區),需重啓 dsh web。
卸載:
dsh plugin --profile web remove dsh-report-fix
配置¶
在 profile 的 cordis.patch.yml 中按 id 覆蓋(dsh-hmr 會重組 profile,改配置通常不必重啓進程):
- id: dsh-report-fix
config:
maxNudges: 5
locale: zh
| 鍵 | 默認 | 含義 |
|---|---|---|
enabled |
true |
總開關;false 時不註冊任何鉤子 |
maxNudges |
3 |
每回合攔截次數;0 關閉硬門禁,僅保留 pre-step 提醒 |
preStepReminder |
true |
首步追加提醒,多數回合在門禁前即合規 |
locale |
auto |
auto 跟進入站語言;zh / en 強制 |
excerptMaxChars |
600 |
nudge 中引用的 dispatch 摘要最大字符數 |
典型用法與邊界¶
典型流程:工作流裏 A 派任務給 B(task_dispatch),B 在插件約束下必須先對 A 發起成功的 task_report,回合才允許結束;與 dsh-call-session 的消息格式約定一致,插件不 import 該包,只讀 source.kind / source.form 與首行頭。
已知限制(摘自上游文檔):
- 最終 assistant 文本可能在
agent/turn-stopping之前已提交併流式展示;保證的是「回合不會因未報告而結束」,不是「用戶一定看不到未報告前的最終文本」。 maxNudges用盡後回合會釋放並打warn,避免模型死循環佔住回合;maxNudges: 0僅提醒、不硬攔。- 欠賬按回合計,新回合不繼承。
- 工具報錯、
success: false或 report 發錯 session 均不清賬。 - 上游
dsh-call-session消息格式變更時,本插件需同步適配。 - dispatch 正文若與 guard 衝突,仍由模型抉擇,測試中可能出現燒完
maxNudges才釋放的情況。
適用場景與注意¶
適合已經在用 session_call + task_dispatch / task_report 做多會話編排的 DSH 開發者,希望被叫方「漏報告就關回合」這類缺口有宿主側兜底。插件以當前 dsh 進程權限運行,安裝前請自行審閱 源碼與 MIT 許可證。社區目錄 skillhub.cn 與 DeepSeek / 幻方無官方從屬關係,屬於 DSH「一切皆插件」生態裏的第三方條目。
結尾¶
dsh-report-fix 用三個生命週期鉤子把「dispatch 驅動的回合必須以 task_report 收尾」寫成可執行的回合邊界檢查,配置項少、與 dsh-call-session 解耦。需要細節與測試說明時,以倉庫 README(含 簡體中文)爲準。
- 目錄頁:https://www.skillhub.cn/plugins/JohnnnSinaaa/dsh-report-fix
- GitHub:https://github.com/JohnnnSinaaa/dsh-report-fix