Skip to content

网络代理下后台子Agent模型重试毫无作用 #3721

Description

@sodiumDB

你运行的 Kimi Code 版本是?

0.42.0

你使用的是哪个开放平台/订阅?

kimi

你使用的是哪个模型?

主Agent K3,子Agent为私有部署Qwen3.8-27B

你的电脑平台是?

linux ubuntu 24.04

你遇到了什么问题?

后台子Agent模型偶尔会断连,但没有任何重试请求被发送出去,而且新开启的子Agent是可用的,但不保证不会出现这个问题。
此问题我通过AI对kimi code进行研究,AI有一些结论(见下文,附复现脚本)
注:此子Agent使用的模型URL为http,https下不会触发此问题. 此问题在打开VPN时走的本机http代理会有概率触发。

复现步骤?

隔离探针——完全按 packages/agent-core-v2/src/_base/utils/proxy.ts:218-226 的方式装配 undici
包,然后调用全局 fetch;故障代理接受 TCP 连接后直接销毁 socket,始终不回应 CONNECT

7.27.1(实际打包) 8.10.2(已修)
结果 永不 settle ~40 ms 内失败,UND_ERR_PRX_CONN
CONNECT 次数 149 次 / 3.8 秒(≈39 次/秒) 1 次

同一故障注入到真实二进制前面(kimi -p "..."HTTPS_PROXY 指向故障代理):

退出码 124(被 timeout 强杀;全程未返回),48 秒
代理计数: {"connects":6270,"tunneled":0,"dropped":6269,"elapsedMs":48573}
#6266 api.deepseek.com:443 · #6267 code.kimi.com:443 · #6268 telemetry-logs.kimi.com:443 …

整个 45 秒内没有任何输出、也没有任何报错。≈129 次/秒约为隔离探针的 3 倍,因为每个出口都在转
自己的循环。未消耗任何模型额度——没有一条隧道建立成功。

为什么重试走不出来

传输错误被归类为可重试,于是整个预算都消耗在同一个卡死的池上——
llm-adapter/contract/errors.ts:240-251NETWORK_REAPIConnectionError)与 :221-224
human/llm/requester/retry.ts:39-57,预算在 :3DEFAULT_MAX_RETRY_ATTEMPTS = 10)。

每一次尝试确实会新建一个 SDK client(.../bases/openai/requester.ts:52-59)——但它带着
maxRetries: 0没有传 fetch 选项,因此仍然走 globalThis.fetch 和进程级全局
dispatcher。新建 client 不会清掉已经卡死的池;这就是「看起来在重连、实际什么都没做」的原因。

而且没有任何地方会重建它:只在 apps/kimi-code/src/main.ts:187 安装一次,而在
packages/*/src + apps/*/src 全量检索中,唯一的 dispatcher.close() 属于 web 抓取工具自己
app/web/providers/local-fetch-url.ts:70)。

期望的行为是什么?

子Agent能正常发送模型重连请求,不再因为重连失败导致任务中断且子Agent对话无法继续。

补充信息

我并非主张以下内容

复现证明的是*「请求永不 settle + 狂打代理」。它本身并不能证明「永久卡死直到重启」*——
在我的测试里,代理一恢复,那个挂住的请求就成功了。并且原始的「零新 socket」/ 每次约 1.4 s 失败
与我实测到的行为(每秒约 39 个新 socket)并不一致,因此可能还存在第二个机制。可以确凿断言的是:
(a) 实际打包的 undici 存在一个已确认的缺陷,而当前版本没有它的修复;(b) 代码里没有任何
dispatcher 恢复路径,所以任何卡死状态在构造上就是永久的。

**

建议方向**

  1. 接入 #5441 —— 把 ^7.27.1 升到 ≥ 8.6.0,或把那段七行分支内联进来。这条路无法靠「去掉
    npm 依赖、改用 Node 自带环境代理」绕过:Node v24.17.0 自带的 undici 行为完全一样
    (只用 fetch 的最小对照测试,6 秒内 215 次 CONNECT)。
  2. 重建全局 dispatcher —— 在连续 N 次 provider.connection_error 之后重建它;这一步才是把
    「永久性」变成可恢复瞬时故障的关键,且与触发原因无关。
  3. error.cause 暴露出来 —— 在 convertOpenAIError() 的连接错误分支
    .../bases/openai/format.ts:339,353):现在它塌缩成 SDK 的字面量 "Connection error."
    这正是这一类报告很难从日志入手定位的原因。

自包含复现(Node ≥ 22 + curl,无需 npm)见附件 kimi-undici-connext-repro.zip./run.sh
对比 7.27.1 与 8.10.2,./e2e-kimi.sh 把同一故障注入到真实二进制前面。

kimi-undici-connext-repro.zip

Contribution

  • 我愿意自己提交修复此 bug 的 PR(请先等待维护者在本 issue 中批准)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions