dsh-llm-network-retry:斷網時不讓一輪對話死掉

前言

跑智能體任務時最常見的一種失敗是:一輪對話跑到一半網絡斷了——合蓋、切 VPN、弱網握手超時。DSH 自帶的 @deepseek-ai/dsh-llm-retry 確實會重試,但預算來自 provider 的 retryPolicy,默認 normal 只有最多 5 次,約 10 秒就放棄。結果是輪次結束,必須手動點「繼續」。

elfgzp/dsh-llm-network-retry 專門爲這個場景做插件:連接類失敗無限重試,直到網絡恢復;其它錯誤仍然有界,讓真正的 400、鑑權、上下文超長立刻失敗。

下面介紹它的定位、安裝、配置與邊界。事實來自插件 GitHub README 與 package.json。

這是什麼

一句話定位:掛到 agent loop 的重試瀑布上,給「網斷了」這一類失敗加一條無上限重試鏈。

  • 插件名:dsh-llm-network-retry
  • 維護者:elfgzp
  • 分類:模型推理
  • 版本:1.2.0
  • 許可證:MIT
  • 星標:0

它實現的是 Codex CLI 裏的 unbounded_connection_retries 規則:只有 ConnectionFailed 這類「網斷了」的錯誤無上限重試,從 5 s 起翻倍到 60 s;其餘照舊有界。裝好即生效,不需要配置。

核心功能

重試預算分開,不把 token 燒在死路上

它和自帶 llm-retry 的區別不在「能不能重試」,而在預算從哪來:

自帶 llm-retry 本插件
默認預算 provider retryPolicy,默認最多 5 次 連接類失敗無上限;其它 5 次
默認退避 500 ms → 10 s 連接類 5 s → 60 s;其它 500 ms → 10 s
約多久放棄 ~10 秒 連接類永不放棄;其它 ~10 秒
斷網 10 秒 輪次結束,需手動「繼續」 自動接上

換句話說,插件的改變是「值不值得等」的判斷:死鏈不值得等,活鏈應該一直等到恢復。

不重複建鏈

插件 prepend 在自帶執行器之前,連接類失敗由它一家接管成一條無限鏈,而不是「自帶 5 次 + 本插件再來一條」。已經聲明 mode: always 的 provider 則完全讓給它,不疊加。這樣避免兩個執行器各建重試鏈、互相搶預算。

每條重試都是真實計費請求

無上限模式會一直重試到成功或你取消爲止。這是它的設計目的,但需要知悉:等待期間每次重試都是一次真實請求。

崩潰中斷的那一輪,另走一條鏈路

進程被殺、崩潰或關閉超時後,agent-loop 會在下次啓動時發現日誌末尾有一輪沒閉合,補一條合成 turn/end{interrupted} 關掉。這種失敗和斷網無關,請求級重試插不進去。

插件補了三件事:

  1. 輸入框下方給提示條,寫明「上次運行被中斷(第 3 輪)」,列出結果未知的工具調用(bash、write),讓你先覈對真實狀態再繼續。
  2. 啓動時掃描全部會話,把上次以崩潰收尾的會話在側邊欄點一個小黃點,懸停顯示「第 N 輪被中斷,這些工具調用結果未知:…」。
  3. 打開這種會話時自動繼續末尾那一輪,不需要點按鈕。

觸發條件是「日誌末尾那一輪是 interrupted」,不看啓動來源。這樣能同時做到三件事:崩潰會話會續跑,三個月前的正常會話不動,崩潰可復現時不循環(下次重啓不再自動續,改爲留給人工判斷)。

兩條實現細節值得留意:掃描是隻讀的(open(id, 'read'),不取寫權),有限併發默認 4,單會話讀失敗只跳過、不影響其它,且可取消;繼續消息用 agent.followup() 而不是 sessionController.prompt(),因爲後者會把消息源寫成 user-rpc,日誌裏看不出這條來自插件。

判定表

哪類錯誤重試、哪類不重試,按下表:

失敗 code 行爲
TRANSPORT / TIMEOUT / NETWORK 無上限,5 s → 60 s
SERVER / RATE_LIMIT / EMPTY_RESPONSE 有界,默認 5 次,500 ms → 10 s
AUTH / QUOTA / CONTEXT_WINDOW_EXCEEDED / INVALID_REQUEST 不重試,立即交給下游
本輪已取消 不重試,且不驚動下游
未列出的 code 交給下游(preset: always 時改爲重試)

服務端返回的 Retry-After 會被尊重——只要不超過本策略上限;超過上限就用本地退避,策略不會就此終止。

安裝與啓用

需要 DeepSeek Harness 0.2.x。

Web 界面:側邊欄 → 插件 → 添加插件 → 安裝第三方插件,粘貼倉庫地址:

https://github.com/elfgzp/dsh-llm-network-retry

確認後在「已安裝插件」裏打開網絡重試。

讓 agent 裝:在開啓了插件管理工具的會話裏說

從 https://github.com/elfgzp/dsh-llm-network-retry 安裝這個插件並啓用

命令行:

dsh plugin --profile <profile> add "github:elfgzp/dsh-llm-network-retry#main"

裝完直接對話即可,斷網時聊天裏會出現重試行自己倒數。改了 config 或更新了插件代碼,把插件 toggle 一次(關掉再打開)就會重載;唯獨新增瀏覽器半邊需要重啓一次 Harness。

配置

默認值就是 Codex 的形狀,config 留空即可:

- insert:
    - id: llm-network-retry
      name: dsh-llm-network-retry
      config:
        preset: codex
        maxRetries: 5
        unboundedConnectionRetries: true
        maxUnboundedWaitMs: 0
        providers: []
        models: []
        honorRetryAfter: true
        respectProviderPolicy: true
        requestBackoff:
          initialDelayMs: 500
          maxDelayMs: 10000
          jitterRatio: 0.1
          multiplier: 2
        connectionBackoff:
          initialDelayMs: 5000
          maxDelayMs: 60000
          jitterRatio: 0.1
          multiplier: 2

三種 preset:

  • codex(默認):連接類無上限,其它有界。日常用這個。
  • always:只要不是致命錯誤就無上限重試。適合「寧可等一小時也別斷」的長任務。
  • normal:任何情況都不無上限,等價於自帶 llm-retry 的默認行爲,只是預算由本插件管。

寫錯字段名會在激活時直接報錯,不會悄悄不生效。

典型用法

安裝後無需額外配置,直接對話即生效。斷網時聊天裏會渲染原生的重試行,樣式大致是:

↻ 正在重試… 3/∞ · 12 秒後   連接被重置

崩潰中斷的會話打開後會看到提示條,選擇「繼續上次任務」即可讓模型按順序做:先覈實真實狀態(文件、Git、遠端、服務)→ 只直接重試只讀或冪等操作 → 有副作用的先確認是否已生效 → 狀態不清楚先問你。這正是插件刻意的設計:進程死亡時可能有 git push、npm publish、部署在飛,不能盲目重放。

適用場景與注意

適合經常跑長任務、且會受網絡切換影響的 DSH 用戶,尤其是希望斷網窗口(合蓋、VPN、弱網)不打斷一輪對話的場景。

需要注意幾點:

  • 插件以當前 dsh 進程權限運行。安裝第三方插件前,應先檢查源碼與許可證(MIT)。
  • 只覆蓋模型請求失敗的這一層。工具調用、shell 命令失敗各有自己的超時與重試語義,插件不碰。
  • 直接調用 ctx.llm.stream() 的代碼不走 agent loop,因此不享受這裏的重試(自帶執行器也是同樣邊界)。
  • 崩潰恢復只處理日誌末尾那一輪,更早的中斷輪次已被後續輪次覆蓋,頁面不會追問。
  • 社區目錄是獨立站點,與 DeepSeek / 幻方無官方從屬關係,這不是官方應用商店。

結尾

這個插件的價值很收斂:把「網絡斷了」這類本可以自愈的失敗,從需要手動繼續,變成自動接上;同時不改變真正該快速失敗的錯誤的行爲。默認配置即 Codex 的形狀,需要時再調 preset 和退避。

目錄頁:https://www.skillhub.cn/plugins/elfgzp/dsh-llm-network-retry

GitHub:https://github.com/elfgzp/dsh-llm-network-retry

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

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

小夜