@ruqinhu/dsh-weixin-link:把 DSH 回合結果自動投遞到微信 iLink

前言

在 DeepSeek Harness(DSH)裏跑定時任務或遠程觸發會話時,模型往往只在終端或 Web UI 裏給出答案,不會主動把同一段文字發到手機。若依賴模型自己調用發送工具,常見結果是:會話裏已有回覆卻未外發、誤發元評論,或把錯誤棧當成「報告」推出去。微信 iLink 側還有硬性約束:每次發送必須攜帶來自入站消息的 context_token,插件不能憑空造 token,長時間無人發消息時,待發內容只能暫存而不能改走別的通道。

下面介紹社區插件 @ruqinhu/dsh-weixin-link(維護者 ruqinhu,分類:客戶端)。它在 DSH 與微信 iLink API 之間做通道:收消息、在合適回合結束時自動投遞結果,並記錄投遞迴執與決策軌跡。

這是什麼

@ruqinhu/dsh-weixin-link 是面向 DeepSeek Harness 的 Weixin(iLink)通道插件。簡介原文爲:bidirectional send/receive with delivery receipts——即雙向收發,並對每次發送嘗試留痕。

插件通過 Cordis patch 訂閱 session/event,在 turn/end 時決定是否把本回合文本發到微信,而不是把「記得調用發送工具」交給模型。憑證經 DSH 的 credential store(ctx.credentials.resolve())讀取,不直接讀 process.env,以免覆蓋 $DSH_HOME/.credentials.yaml 與項目 .env 的分層規則。

核心功能

約束 後果
每次發送必須帶 context_token token 只能來自入站消息
不能 mint token 長時間無入站時,例如 07:00 定時報告會暫存,直到機主再發消息
不做 fallback 通道 失敗不轉路由;暫存文本在條件允許時重放
單條文本上限 2,200 字 在代碼裏截斷,不交給模型自行控制

哪些回合會被自動投遞

插件按 source.kind 過濾。只有部分來源會外發:

source.kind 來源 是否投遞
schedule cron 任務 是
weixin-link 機主從微信發來消息觸發的回合 是
user 終端 / Web UI 輸入 否(答案已在屏幕上)
runtime-context / skill-catalog / time-context 等 注入上下文 否
compact-checkpoint / provider / fallback 等 壓縮、標題等內部流程 否

README 說明:只有第一條用戶消息標定來源;後續回合會注入上下文,若用「最後一條消息」判斷,會把所有回合都當成上下文而不投遞。

機制要點

  • 誰負責發:通道在 turn/end 自動發送;備選方案是讓模型調用 weixin_push,實測會出現已回答但未外發、亂推說明文字等問題。模型若不想說話,可使用 [SILENT]。
  • 去重:10 分鐘內相同正文視爲已投遞;窗口外重複仍會發出。手動 weixin_push 會壓制同內容的自動投遞。
  • 空回合:發送 本次無產出(timestamp),避免「跑了但失敗」與「沒跑」無法區分。
  • 失敗回合:可發送 ⚠️ 回合未完成(reason,timestamp):本次沒有可投遞的內容。;每個 session 每小時最多一條失敗通知(內存計數,進程重啓可能多一條)。
  • 入站與重放:獨立定時器重放 outbox,單線程 serial;長輪詢 bootstrap 不阻塞重放,避免 30/60/120 秒退避疊加成數分鐘 deaf。
  • 存活檢測:每輪更新 state/heartbeat.json,默認每 60 秒檢查;若連續 3 個 budget(≥ 90 秒)沒有任何發送嘗試,則重啓 poll 循環。

工具與本地文件

工具 用途
weixin_push 立即發送;無法投遞時自動暫存(park)
weixin_status 登錄狀態、token 年齡、最近投遞、outbox 深度、poll 是否存活
路徑(默認 dataDir 爲 ~/.dsh/weixin-link) 內容
receipts/YYYY-MM-DD.jsonl 每次發送嘗試一行,按東八區日期分文件
delivery-trace.log 每個 turn 的投遞決策,含 skip 及原因
outbox/ 等待 token 的暫存消息
state/heartbeat.json 最近嘗試/成功、失敗次數、入站計數、重啓次數

delivery-trace.log 示例形態(README 摘錄):

send session=... turn=12 kind=turn len=63
ok   session=... turn=12 msgid=7521135910923441000
skip session=... turn=13 reason=source-not-deliverable

兼容性與體量

項 值
DSH(peer) 0.2.1-rc.5
插件版本(package.json) 0.4.2
Runtime Node 22+,無 native 模塊
依賴服務 tools、credentials、sessionController;agents 可選
載荷 僅文本,≤ 2,200 字符
許可證 MIT
單元測試 README 稱 248 條、21 個文件,tsc --noEmit 通過

安裝與配置

安裝

官方安裝命令如下:

dsh plugin add @ruqinhu/dsh-weixin-link

安裝前請自行查看 GitHub 倉庫 源碼與 MIT 許可證。插件以當前 DSH 進程權限運行,憑證與 dataDir 會落在本機,部署前確認 token 與數據目錄權限可接受。

憑證

在 credential store 中配置 bot token 與 account id。默認 credential 名稱:

  • WEIXIN_BOT_TOKEN(配置項 tokenEnv)
  • WEIXIN_BOT_ACCOUNT_ID(配置項 accountIdEnv)

主要配置項

Key 默認值 含義
baseUrl https://ilinkai.weixin.qq.com iLink 端點
dataDir ~/.dsh/weixin-link token、outbox、receipts、trace
poll true 是否運行入站長輪詢
pollTimeoutMs 40000 客戶端超時,須大於服務端 35 s hold
defaultUserId "" 收件人;空則用最 recent 入站發送者
echoOwnMessages false 是否把機器人自己的消息當入站
sessionId "" 入站路由到的 session,冷啓動可恢復
replayIntervalMs 300000 outbox 重試間隔
dedupeWindowMs 600000 相同正文去重窗口
notifyTurnFailures true 回合未完成時是否通知
watchdogIntervalMs 60000 存活檢查間隔;0 關閉

典型用法

  1. 安裝插件並在 DSH credential store 中寫入 WEIXIN_BOT_TOKEN 與 WEIXIN_BOT_ACCOUNT_ID。
  2. 保持 poll: true,從微信向機器人發一條消息,爲後續發送換取 context_token。
  3. 配置 cron(source.kind 爲 schedule)或繼續通過微信觸發會話;回合結束後查看手機是否收到自動投遞,必要時讀 delivery-trace.log 與 receipts/。
  4. 需要主動推送或排查隊列時,在會話中調用 weixin_status 查看 token 年齡與 outbox 深度;無法立即發送時用 weixin_push(會 park 到 outbox)。

README 記錄的實測:入站 10:00:04 → 回合完成 10:00:24 → 同秒 ok msgid=...;14 小時運行 watchdog restarts: 0。配額耗盡(429 AccountQuotaExceeded)時,舊構建連續 skip not-completed,新構建在約四分鐘沉默後發出一條說明回合未完成的短消息。

適用場景與注意

適合:希望 DSH 定時報告、微信觸發的會話結果自動回到同一微信對話;需要 JSONL 回執與 trace 審計發送嘗試的場景。

限制(README 開放問題摘要):

  • Token 無法由插件刷新;約 12 小時無入站會 park 發送。
  • 單 poll 循環、單收件人;多賬號需額外路由層。
  • Outbox 重放串行;富媒體 / 卡片未支持,僅文本。
  • 調試器暫停或長 GC 可能被 watchdog 判爲 stall 並重啓(無害但會記入 heartbeat)。

DSH 生態強調「一切皆插件」;SkillHub 目錄頁 爲社區站點,與 DeepSeek / 幻方無官方從屬關係。

結尾

@ruqinhu/dsh-weixin-link 把微信 iLink 的 token 約束、回合來源過濾和 turn/end 自動投遞合在一起,減少「模型忘了發微信」類問題,並用 outbox、trace 與 receipts 把失敗與 skip 原因留在磁盤上。進一步細節見 GitHub README(含中文 README.zh-CN.md)與目錄頁 skillhub.cn/plugins/ruqinhu/dsh-weixin-link。

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

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

小夜