dsh-handoff:在對話裏把當前會話交接到另一個工作區

前言

用 DSH 做長任務時,常會遇到「換個工作區繼續」。手工搬通常丟三件事:歷史、結論、下一步。複製文件帶不走對話;新開一個空會話等於讓模型從零開始;把整段記錄粘進輸入框既超長又失真。

dsh-handoff 是給 DeepSeek Harness(DSH)的會話交接插件,由 GarinZ 維護,屬於社區目錄裏的工作流分類。它讓 Agent 在對話裏直接調用 handoff_session 工具,把當前會話交接到另一個工作區的新會話,並附上一份按固定骨架寫好的交接簡報。源會話默認保持不變。

核心能力

插件做了三件事,用的都是 DSH 自身能力:

  1. fork — sessionController.fork() 把當前會話的事件前綴複製成獨立新會話(不寫 parentSession);
  2. relocate — 把新會話的存儲遷到目標工作區:重寫日誌頭行的 cwd、重綁活動寫句柄、切換工作區賬本,全程不重啓;
  3. brief — 把交接簡報追加成新會話的第一條消息,簡報按固定六節骨架寫。

交接有兩種歷史策略:

模式 history 新會話裏有什麼 什麼時候用
全文複製(默認) full 完整事件歷史 + 交接簡報 需要精確上下文,且源會話還健康
僅摘要 summary 只有交接簡報 源會話已經很大、上下文快撐爆,或用了不支持主動壓縮的插件

需要「僅摘要」的原因是:fork 是事實複製,不是壓縮。源會話若已被上下文壓力拖到邊緣,複製出來的會話會繼承同樣的壓力。摘要模式直接在目標工作區新建空白會話、只寫簡報,新會話的上下文壓力從零開始,代價是丟掉原始對話裏的細節。

安裝

從 npm 或 GitHub 安裝:

# 從 npm
dsh plugin --profile <profile> add @garinz/dsh-handoff

# 或直接從 GitHub
dsh plugin --profile <profile> add github:GarinZ/dsh-handoff

從本地檢出的源碼安裝:

dsh plugin --profile <profile> add /path/to/dsh-handoff
# 或在該目錄裏
dsh plugin --profile desktop add .

宿主半熱加載,裝完即用,不需要刷新頁面。但客戶端半是 client.js(浮層與追問按鈕),裝或升級後需要刷新一次頁面纔會加載:dsh 自帶 Web 殼打開開發者工具(⌘⌥I)執行 location.reload(),生產版沒有 ⌘R。

典型用法

插件註冊了三個命令,輸入 / 可見:/handoff <自然語言>(全文複製)、/handoff-summary <自然語言>(僅摘要)、/btw <問題>(旁問)。命令本身秒回「旁問中…」「正在生成簡報並交接…」,把輸入框讓出來,答案回來後再替換命令結果,避免看起來卡死。

例如:

/handoff-summary 交接給 ~/Project/llm/agent-skills。ESP32 那攤活先放下,下一階段只做 skill 倉庫整理:重點寫清楚哪些 skill 已經沉澱、哪些還只是草稿,以及"別自動入庫"這條約束。

斜槓命令優先走側路請求:插件取當前會話的消息快照(含 system prompt),追加「請按六節骨架寫交接簡報」的指令,用同一個 provider/model 單獨請求一次,拿到簡報後直接調用 handoff_session。這條請求不開啓回合、不往對話裏寫事件。只有當目標工作區無法唯一確定、或本次會話還沒有一問一答時,才退回「模型自己寫簡報再調工具」的路徑。

直接說人話也可以,Agent 會調用工具,參數形如:

{
  "target": "/Users/me/Project/new-repo",
  "summary": "## 目標\n…\n## 下一步\n…",
  "history": "full",
  "title": "可選:給新會話一個能認出來的標題",
  "start_turn": false
}

各字段的含義:

  • target:目標工作區的絕對路徑(或 ~ 開頭)、工作區 id 或標題。目錄不存在時會先 mkdir -p 再註冊,所以「交接給 ~/proj/新項目」可以直接開一個新工作區。
  • summary:交接簡報,六節骨架。history: "full" 時是補充;history: "summary" 時是新會話唯一的上下文。
  • history:full 複製完整歷史;summary 不復制任何事件,只開帶簡報的空白會話。
  • title:可選,避免目標工作區出現兩個同名會話。
  • start_turn:爲 true 時立刻在新會話裏跑一輪;默認只記錄,不消耗模型調用。
  • mode:copy(默認)複製出新會話,原會話不動;move(beta)把當前會話本身在回合結束後遷到目標工作區(id 不變、歷史全保留),只能搭配 history: "full"。

摘要模式的新會話會被包進一個只含簡報、不含模型回覆的回合(turn/start → 簡報 → turn/end)。這是爲了 GUI 的 sessionListMetadata.blank 判斷:該投影只在遇到 turn/start 時才翻成 false,不補這個回合,僅摘要交接出來的會話在側欄裏不可見。回合裏沒有 step、沒有 assistant 消息,不會調模型、不跑工具。

簡報骨架

兩種模式共用固定的六節:

## 目標          這一段要達成什麼
## 決策          決定了什麼 + 爲什麼(理由比結論重要)
## 已完成        帶產物:文件路徑、跑過的命令、測試結果
## 剩餘          還沒做的
## 關鍵上下文    路徑、符號、報錯原文、配置值
## 下一步        新會話第一條該做什麼

寫作規則對齊了 oh-my-pi 與 pi-handoff:只用對話裏出現過的事實、不臆造路徑與行號;關鍵細節不知道就寫「未知」並給出最小驗證步驟;用祈使句對下一任說話,不用第一人稱;不把「寫這份簡報」本身寫進進度或下一步。

旁問 /btw

/btw 剛纔那個 403 是哪個開關沒開?

它複用簡報用的同一個側路請求原語:快照 + 一句問題 → 一次獨立模型調用,不開啓回合、不寫事件、不佔會話記憶。側路請求發的是扁平文本(把會話壓成 ## 用戶 / ## 助手 / ## 工具結果 的對話記錄塞進一條 user 消息),因爲請求裏不聲明 tools 時,provider 會拒絕帶 tool-call 塊和圖片的原始歷史。預算按字符算:旁問 20 萬字符、簡報 40 萬字符,超了從最舊整條丟起,圖片一律變 [圖片]。留空 maxTokens 時由 ctx.llm 填該模型聲明的 defaultMaxTokens,避免「聊天能寫完、旁問被截斷」。

進度面板

/btw 和 /handoff* 的快路徑會在右下角彈出固定進度卡:標題、狀態、已跑秒數、流式正文和「停止」。它走獨立宿主路由 GET /handoff/activity?session=<id>(?cancel=1 中止),不依賴聊天流。底部輸入框是追問口,ping POST /handoff/ask 把問題交給宿主,答案流回同一張卡,不在對話裏留命令節點。追問時模型能看到本次會話最近 12 組旁問問答(原文不截斷,僅存內存,重啓即失)。

落盤結果

history: "full":

<目標工作區>/…/session-<new>/session.v4.jsonl.zstd
  header.cwd = 目標工作區
  事件 = 源會話的完整前綴 + 簡報

history: "summary":

<目標工作區>/…/session-<new>/session.v4.jsonl.zstd
  header.cwd = 目標工作區
  事件 = 標題 + 簡報(沒有別的)

適用場景與注意

適合需要在 DSH 裏跨工作區延續長任務、且希望把上下文和結論一起搬走的開發者。安裝前應檢查源碼與許可證(MIT),插件以當前 dsh 進程權限運行。

行爲上有幾點需要知道:

  • subagent 會話不能交接;沒有記錄 cwd 的會話不能交接。會話裏連一問一答都沒有時,工具會直接拒絕(這次會話還沒有可交接的對話)。
  • 新會話的 header.cwd 是目標工作區路徑,沙箱根、AGENTS.md、skills 發現都跟着走。
  • 存儲遷移先寫臨時目錄、讀回校驗,再改內存態與賬本;任一步失敗都會回滾並保留原會話。
  • 全文模式是 fork 語義:新會話 isSeeded 爲 true,歷史標記爲繼承(session/end-seed)。依賴「自身事件」的功能(例如按會話統計 token 用量)會把繼承部分算作前人歷史;摘要模式沒有這個問題,但它只知道簡報裏寫了的東西。
  • 工作區賬本與日誌是即時寫好的,側欄刷新時機由 DSH 客戶端決定,個別界面狀態可能需要切一下工作區或刷新頁面才顯示。
  • 插件依賴若干 DSH 內部接口(sessionPersistence.tracker.writers、workspaceRegistry.indexHeader/attachSession、commands.register)。DSH 升級後請先在一個臨時會話上驗證。
  • 兼容性:開發與驗證環境爲 DSH 0.2.2-rc.1(macOS 桌面版)、Node 24。需要 hosting 暴露 sessionController、workspaceRegistry、sessionPersistence 三個服務(官方 dsh-base 都有)。

結尾

dsh-handoff 的價值在於把「跨工作區繼續」這件事從手工搬運變成對話裏的一次工具調用:歷史、結論、下一步按固定骨架一起過去,源會話默認不動。倉庫:https://github.com/GarinZ/dsh-handoff,目錄頁:https://www.skillhub.cn/plugins/GarinZ/dsh-handoff。

羽毛球分组比赛记分
小程序二维码

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

小夜