Repository navigation
fix(trae):上游没给完成事件(event: done)就结束时不再当成正常收尾 —— 静默截断要看得见 - #294
Open
shadyrispy wants to merge 1 commit into
Open
shadyrispy wants to merge 1 commit into
shadyrispy wants to merge 1 commit into
Conversation
「流结束了」与「上游说完成了」此前被压成一件:SoloStream::finish 在 EOF 时只补 [DONE]、aggregate 的 finish_reason 直接兜 stop(照抄参考实现,向量的两条 「没给 done」形状钉着)。于是上游把连接撑断时,那份前缀在客户端看起来是一次 完全正常的完成 —— 上游 issue aimod-cc#286:trae 的 deepseek-v4.1-flash-solo 推理失控, 报告人 13/15 次只收到前缀,网关侧 status=200 / 错误列为空 / 一次都不重试, 连自动续写都接不住(它要的 finish_reason 被兜成了 stop)。 判据是现成的:产出过内容(正文/思考/工具调用任一非空)且上游没给过完成事件。 - 流式:在 [DONE] 之前补一帧错误(形状与流内错误一致),错误进请求日志; - 非流式:直接 502,不再返回「200 + 前缀」那份假成功; - 「一句不吐就结束」不算截断(归既有空回答兜底链),event: error 之后结束也不算 (错误已经如实下发过)。 - 兜底开关 AGENT2API_TRAE_NO_REQUIRE_TERMINAL=1 关掉这条判据(读一次定死)。 转换层只如实报告事实(SoloStream 记 saw_done/saw_output,aggregate 返回 Aggregated),回包形状一个字不改 —— 那两条对拍向量因此一条都没动。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
这条修什么
上游 issue #286:trae 的
deepseek-v4.1-flash-solo推理失控(报告人实测同一简单任务的推理量 13,619 字符,同家其它模型低 100–900 倍),上游把连接撑断时没发结束帧event: done,而网关把「流结束了」当成了「上游说完成了」:SoloStream::finish()在 EOF 只补一个[DONE]—— 没有错误帧,也没有任何带finish_reason的 chunk;aggregate()的finish_reason初值就是"stop",直接写进 200。于是客户端拿到的是期望输出的严格前缀(报告人 13/15 次,非流式 12/15),而网关侧
status=200、错误列为空、一次都不重试。最坏的一点是它不像失败:自动续写(#233)也接不住 —— 判据要的finish_reason被兜成了stop,第 1 条就落空。根因不是「读错误被吞」:真报错时两条路都留痕(流式记
note_error并下传Err,非流式给 502)。报告人观察到的是干净 EOF —— 上游在 HTTP 层把响应体正常结束了,只是没给event: done。缺的是「上游到底收没收场」这个判别,而它一直就在手上。改了什么
SoloStream记saw_done/saw_output并开只读访问器;aggregate返回Aggregated { body, saw_done, saw_output }(body 逐字不变)。参考实现的向量把「没给 done 也结束」当正常形状(上游没给 done(EOF 兜底 [DONE])与usage 之后没有 done两条),因此那两条向量与对拍测试一条都没动。missing_terminal(saw_done, saw_output, require):产出过内容(正文 / 思考 / 工具调用任一非空)且上游没给过完成事件。两个例外刻意不判:一句不吐就结束(归既有的空回答兜底链)、event: error之后结束(saw_done同样为真,错误已经如实下发过)。[DONE]之前补一帧data: {"error": {…, "type": "upstream_error"}}(形状与流内错误一致),并把该轮写进请求日志的错误列;AGENT2API_TRAE_NO_REQUIRE_TERMINAL=1关掉这条判据(读一次定死,与ZCODE_REQUIRE_CAPTCHA同一取向)。上面那两条向量说明这条判据是有意偏离参考实现,万一在没见过的上游形状上误伤,兜底不该依赖发版。测试
cargo test -p agent2api-server:591 passed / 0 failed / 6 ignored;基点 betaa55e1eb同命令实跑 585 passed / 6 ignored ⇒ 净增 6 条。新增用例:无 done 有内容(流式要补错误帧且错误进遥测、非流式要 502 而不是 200)、有 done 的正对照(字节不多一个、无错误留痕)、「一句不吐就结束」仍容忍、判据表与开关解析(不碰进程环境变量)、聚合层如实回报两个标志位(body 形状不变)。
反转验证:把开关打上重跑同一批 trae 用例 ⇒ 恰好那两条行为用例转红(
a_stream_that_ends_without_done_is_flagged_in_band、an_aggregate_that_ends_without_done_fails_instead_of_a_prefix),其余 137 条仍绿。已知边界
request_raw不再写入,只能靠 debugMode 采集或加计数器,本 PR 未加计数器。finish_reason=stop」:按流式路径只会下发[DONE]、不带finish_reason,只有非流式显式写stop,这一处描述未向其确认。saw_error()为真 ⇒ 不触发续写(刻意的:先让客户端知道这轮不完整,再谈续写)。