前言¶
DSH 的理念是「一切皆插件」,IM 接入通常靠 @xmanrui/dsh-im 或 dsh-onebot-qq 這類插件完成。拿它接微信公衆號、QQ 羣或個人號時,一個常見問題是:模型回覆一大段貼過去,看起來像機器人;想讓它像真人一樣主動開口,也沒有現成能力。這兩個插件本身都不提供分段發送和自動發送。
dsh-im-companion(npm 包 @jiang_li/dsh-im-companion)就是補這兩塊空白的插件,由 jiang_li(GitHub 賬號 zingreqe)維護,MIT 協議。它針對已抓取資料中 @xmanrui/dsh-im 和 dsh-onebot-qq 缺失的能力,加了三樣東西:分段發送、自動發送、話題庫。下面按功能、安裝、用法、限制的順序介紹。
定位¶
一句話:在不改系統提示詞、不繞開原有鏈路的前提下,讓用上述兩個插件的 DSH 機器人回覆更像真人,並能按你定的時間窗主動說話,參數可逐機器人配置。
它不是通用 IM 通道,而是掛在已有 IM 插件上的擴展。兩個插件都沒裝時,插件仍能加載,面板裏只有空列表。
核心功能¶
1、分段發送¶
讓大模型自己分段,規則很簡單:模型輸出裏的空行就是氣泡邊界,插件按段落逐條發出。
實現上有個關鍵點:前幾段由本插件發送,最後一段仍走 dsh-im 原來的出站鏈路,避免同一段內容被髮兩次。插件不額外注入提示詞,因此不會覆蓋或繞開系統提示詞、記憶插件之類的上下文注入。
2、自動發送¶
按每個機器人的發送時間窗、間隔、隨機性、每日上限,定時在真實會話裏跑一輪 Agent:觸發消息作爲 im-proactive 來源的消息放進會話,會話自己的系統提示詞、記憶和其他插件注入全部生效,生成結果按段落髮回 IM。
默認選取該機器人最新未歸檔的會話,也可以在面板手動指定某條會話固定使用。
隨機性參數的映射方式:0 時實際間隔在 [0, 2×間隔] 內均勻隨機,10 時嚴格固定間隔,中間線性過渡。可以跨夜排時間窗。
3、話題庫¶
插件註冊了一個 topic_library 工具,模型可以把聊天裏出現的話題、興趣、偏好按「一級分類 / 二級分類 / 描述」收進庫裏。可配置入庫敏感度(0–10,爲 0 時工具不出現在模型上下文裏)、遺忘天數(0 爲不自動遺忘)、固定話題,也可以在面板手動增刪改。
主動發消息時可以把已有話題注入提示詞,讓主動消息不那麼生硬。
對兩個 IM 插件的適配細節¶
@xmanrui/dsh-im¶
這是個聚合機器人服務插件,支持微信、QQ、飛書、企業微信等連接,優點是不容易被風控,缺點是機器人賬號用不了真實賬號的功能。本插件對它的擴展方式是在 Host 側包裝 typertGateway.invoke:只處理 dsh-im 的 owner peer(interactions: 'none')發起的 session.page 請求,在含 turn/end 的響應裏注入合成 assistant/message 事件,把已發過的前綴段從 dsh-im 的最終答案裏抹掉,只留末段。Web UI 的會話傳輸不受影響。
dsh-onebot-qq¶
這個插件通過 napcat 連接真實 QQ 號,能提供真實賬號的聊天能力,但沒有自動發送。兩者的分段規則被本插件統一。由於 dsh-onebot-qq 不向宿主暴露服務,插件用了兩個縫:
1、包裝它的 OutboundPipeline.prototype.sendToChat,出站文本按空行拆成多條氣泡,仍走它自己的 Markdown 清理、轉發塊、t2i、隊列與重連補發。
2、冷會話(重啓後還沒收到過消息)bridge 不會投遞,插件在 6 秒後接管,先走捕獲到的 bridge 實例的出站閘門分段發送,bridge 還沒出現時退回 qq_send_segments 工具(每段 500 字以內、每批 9 段)。
面板裏每個 QQ 私聊和羣聊是獨立卡片(onebot:private:<QQ> / onebot:group:<羣>),可以同時給多個私聊開自動發送,各自的時間窗、間隔、隨機性、每日上限、回覆後靜默和話題提示互不影響。舊的單個「QQ(dsh-onebot-qq)」配置會自動遷移到它綁定的那條聊天上。
使用該插件控制的真實 QQ 號容易被風控和封號,不建議用主號連接。另外需要機器人之前至少和用戶聊過一次,纔會存在綁定會話;冷會話會在 30 秒內被索引出來。
安裝與啓用¶
在 profile 爲 web 的 DSH 進程裏執行:
dsh plugin --profile web add @jiang_li/dsh-im-companion
裝完重啓或重載 DSH。插件要求 Node.js >= 22,當前版本 1.4.2。本地開發時,可以把 plugin_manager install_bundle 指向源碼目錄,profile 裏是軟鏈接,改完即生效。
注意 plugin_manager install_bundle 對已安裝的包會返回 already-installed,升級版本號不會覆蓋安裝,需先 remove_bundle 再裝。
面板使用¶
裝好後刷新 DSH Web 頁面,側邊欄出現「主動消息」,面板兩個頁籤。
發送設置頁籤把每個機器人排成宮格里的一格:
- 分段發送:總開關、段間延遲範圍、模擬打字速度(字數上限僅保留給舊的分段函數,IM 分組以模型段落爲準)。
- 自動發送:總開關,每機器人一張卡片,含發送會話(留空爲「自動:最新未歸檔會話」)、時間窗(可跨夜)、間隔分鐘、隨機性 0–10、每日上限、回覆後靜默時長、時區、話題提示。
- 消息提示詞:一段自定義模板,作爲用戶消息追加進目標會話,不替換系統提示詞。
- 「立即發一條」用當前草稿立即試發,不需要先保存,也不會動表單裏的其他改動。
話題庫頁籤只在切過去時加載和顯示話題數據,包含入庫敏感度 0–10、遺忘天數、話題列表與手動編輯。
消息提示詞與佔位符¶
模板會作爲一條 im-proactive 用戶消息追加進目標會話。面板上有佔位符按鈕,點一下插到光標處,「恢復默認」可回到內置模板。支持的佔位符:
| 佔位符 | 內容 |
|---|---|
{{time}} |
發送時刻(本地時間,如 2026-11-02 18:27) |
{{weekday}} / {{date}} |
星期幾 / 日期 |
{{topic}} |
該機器人卡片裏的「話題提示」 |
{{topics}} |
話題庫裏的分類與摘要(最多 40 條,固定項標 ★) |
{{topicHints}} |
最近關注的話題提示 |
{{lastTexts}} |
最近主動發過的內容,避免重複 |
未填值的佔位符留空,多餘空行自動合併。
存儲與改動重載¶
設置、話題庫與運行狀態寫入 ~/.dsh/dsh-im-companion.json,原子寫入。自動發送總開關、每個機器人的開關和發送會話改動會立即保存,其餘字段在點「保存」時落盤。
改動後的重載方式:
1、改了 Host 側(index.js、src/*.mjs):plugin_manager set_bundle 禁用再啓用即可重新 import,不必重啓整個 DSH;不放心就重啓。
2、改了客戶端半(client.js):dsh-client-modules 只在包來源變化時重讀文件,沒有 pnpm run dev:web 看護時刷新頁面拿到的仍是舊 bundle,需要先用 set_bundle 把插件設爲 enabled:false 再設回 true,隨後刷新頁面。
已知限制¶
1、分段只對能解析出投遞目標的 IM 會話生效,解析不到時本輪按原樣整段發送。
2、QQ 的分段依賴包裝 lib/outbound.js,包升級後若改了類名或方法名,包裝會失敗並自動退回整段發送,不影響 bridge 本身。
3、自動發送要求該機器人至少有一個已綁定會話,一個都沒有時只會在面板運行記錄裏提示,不會憑空新建會話。
4、主動發送依賴渠道的主動投遞能力與 contextToken 新鮮度,掉線或令牌失效會記在運行記錄裏。
適用場景與注意¶
適合已經在用 @xmanrui/dsh-im(微信公衆號、飛書、企業微信等聚合渠道)或 dsh-onebot-qq(napcat 真實 QQ 號)的 DSH 開發者,想改善機器人回覆觀感、加上主動問候的場景。不想寫額外提示詞、想保留原鏈路的分段行爲,也符合這插件的實現方式。
安裝前建議在 GitHub 倉庫 檢查源碼與 MIT 許可證,確認它包裝的 Host 側 API(typertGateway.invoke、OutboundPipeline.prototype.sendToChat、ChatBridge.prototype.onSessionEvent 等)與你當前的 @xmanrui/dsh-im、dsh-onebot-qq 版本一致。插件以當前 dsh 進程權限運行,自動發送會在設定時間真實對外發消息,時間窗和每日上限要先設好。QQ 真實號場景注意風控,不要用主號。
小結¶
它做的事情很具體:在已有 IM 插件之上加分段發送、自動發送和話題庫,改動集中在包裝出站鏈路和觸發真實 Agent 輪次,不改系統提示詞,參數逐機器人可配。目錄頁在 https://www.skillhub.cn/plugins/zingreqe/dsh-im-companion,源碼在 https://github.com/zingreqe/dsh-im-companion。