流式超时要绑定到流的完整生命周期
Vercel AI SDK ai@6.0.221 修复了一个隐蔽的流式超时 bug:streamText 的 timeout.stepMs 在流注册后同步阶段就被清除了计时器,流还未产生任何内容时超时已经失效。因此当一个 step 在产生第一个 token 前停滞(LLM 前置处理卡住、网络建连无响应),stepMs 永远无法触发 abort。
这个 bug 的根因是常见的「注册即清除」模式:代码在流对象创建后立即设置了 step timer 的清理回调,但此时流尚未 yield 任何内容,清理先于超时触发。修复后计时器存活到流实际 finish 或 abort,与 generateText 的行为保持一致。同版本的另一提交将超时 abort reason 改为 TimeoutError DOMException,使消费者可以通过 signal.reason.name === 'TimeoutError' 区分框架超时和用户主动取消,不再混用同一个 AbortError。
这对 Agent 平台中所有带超时的流式执行都有借鉴意义:tool streaming、SSE events、实时音频、MCP 响应——任何流在产生第一个数据前的停滞期都需要被超时覆盖,而超时的生命周期不应绑定到「注册时刻」而应绑定到「流的实际执行结束」。实践中意味着 AbortSignal.timeout() 的添加时机应该在流实际开始 yield 之后,或者在创建时就要把清理逻辑与流的终止事件(finish、error、abort)挂钩而非放在同步注册路径上。