SuperAI Agent v0.2.34
SuperAI Agent v0.2.34
修复:使用 OpenAI 兼容网关(经本地代理)时,同一句话反复输出、永不结束;以及流式回复要等 30 秒才出现。
现象
在企业网关上让模型写计划文件,界面里「Let me write the plan.」出现十几次,接着「Now I have all the requirements. Let me write the plan file.」出现二十多次,没有任何工具卡片,直到手动停止。
根因(用真实代理 + 真实命令行对一个可控的假网关复现)
- 代理没有把命令行的输出预算(
max_tokens)转发给上游,上游因此按自己的默认上限(通常只有几千 token)截断回答。写一整个文件的 Write 工具调用一旦超过这个上限,就会在 JSON 中间被切断(finish_reason: length)。 - 代理把被切断的工具调用当作完整调用转发。命令行照常执行,Write 因参数不完整而报错,模型于是重新生成同样的回答,再次在同一位置被切断——没有任何上限。复现时 150 秒内出现 70 条相同消息、35 次请求。纯文本被切断时走的是命令行自带的有界恢复(最多 3 次),所以是 4 条重复加一条误导性的「超过 32000 输出 token」错误。
- 另一个独立缺陷:代理对流式回复设了 30 秒的整体超时。超过 30 秒的流被强行中断,命令行丢弃已收到的部分文本并改用非流式重发——用户看到的是 30 秒毫无反应,然后很久之后才出现完整回答。
修复
- 转发
max_tokens(Responses API 为max_output_tokens)。若某个服务商拒绝这个值(HTTP 400 并点名该字段),代理自动去掉该字段重试一次并记住,此后对该服务商不再发送——即被硬性限制的服务商行为与之前完全一致,只多一次请求。 - 绝不转发被截断的工具调用:流式转换改为在工具块结束时整体发出;若上游以
length结束(或流没有任何结束原因就断了)而参数不是完整 JSON,则丢弃该调用。命令行随即看到「文本 + max_tokens」,走它自带的有界恢复并明确报错,而不是执行垃圾输入并无限循环。非流式(回退)路径采用同一规则。 - 流式超时只约束响应头(60 秒),正文允许运行数分钟;命令行自有的空闲看门狗负责卡住的流。非流式保留 300 秒总超时。
- 顺带修正:文本块之后紧接工具调用时,同一个块索引会收到两次
content_block_stop;现在每个块恰好一次。
验证
- 复现基准(假网关 + 真实代理 + 真实无头命令行):对照组 1 条;文本截断 4 条后报错;工具调用截断修复前无限循环,修复后终止;慢流修复前触发回退,修复后正常完成。
- 新增 19 项测试:
max_tokens转发与拒绝回退策略(代理端到端)、流式/非流式截断工具调用的丢弃与保留规则、每块恰好一次 stop、响应头超时与正文超时分离。两条「max_tokens应为 undefined」的旧断言正是这个 bug 的写照,已改正。