fix(web): keep thinking off the spoken consult and rectification answer

Enumerate evidence kinds so education cannot be proposed as a kind, and stream Chinese thinking on a separate channel that collapses when the reply arrives.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-21 21:30:55 +08:00
parent 56577504d8
commit 4e247c112e
27 changed files with 465 additions and 73 deletions
+36 -4
View File
@@ -4582,8 +4582,8 @@
- 根因:两层。其一,`finish_reason=length` 与超时中断后的半截正文仍走 `run.completed``complete_consultation_response`,公开回执故意不含 `modelFinishReason`,界面无法区分正常结束与夹断。其二,咨询 `agent.stream` 未设可见输出预算,也未关闭 Flash 默认 thinking;隐藏推理与可见正文共用 `max_tokens`,更容易在标题中途 `length` 停住。`AGENT_TIMEOUT_MS = 110_000` 与路由 `maxDuration = 120` 仍可能在组答阶段掐流,旧逻辑同样把已发出的半截当成功。
- 修复:可见正文在 `length` 结束,或超时/中止时已有输出,改为 `run.failed` / `answer_truncated`,保留已流出文本,账务走 `cancel`。咨询流设置 `maxOutputTokens = 8192`,并对当前供应商与 `openai` 兼容键关闭 thinking。客户端保存半截助手消息并提示未完成、不会扣点,不再要求 `run.completed` 才落盘。
- 验证:`frontend/tests/consultation-agentic-runtime.test.ts` 覆盖 `length` 与超时半截不得 `run.completed`、不得调用 `onComplete``consultation-workflow-contract.test.ts` 锁定输出预算与 thinking disabled`consultation-recovery.test.ts``chat-stream-layout.test.ts` 锁定半截落盘与提示;`agent-observability.test.ts``answer_truncated` 纳入已知错误码。
- 防复发:有可见正文不等于咨询完成。`finish_reason=length`、超时半截不得再映射为 `run.completed`。咨询生成必须显式保留可见 token 预算;不得依赖 Flash 默认 thinking 与提供方默认 `max_tokens`。公开回执仍不得带 `modelFinishReason`,失败码必须能单独说明夹断。
- 相关记录:BUG-280、BUG-277、BUG-340
- 防复发:有可见正文不等于咨询完成。`finish_reason=length`、超时半截不得再映射为 `run.completed`。咨询生成必须显式保留 8192 可见 token 预算。若打开 provider thinking,必须走独立 `thinking.delta`,不得把推理写进 `answer.delta`。公开回执仍不得带 `modelFinishReason`,失败码必须能单独说明夹断。
- 相关记录:BUG-280、BUG-277、BUG-340、BUG-346
- 复发自:无
- 修复版本:待提交
@@ -5126,8 +5126,8 @@
- 根因:BUG-305 只修了咨询路径。纠正 `agent.stream` 没有 `maxOutputTokens`、没有关闭 thinking,并把任意 `finish` 当成成功。进度事件 `tool.activity started` 被客户端丢掉,所以长计算期间用户只能干等。
- 修复:咨询与纠正共用 `agentGenerationSettings`8192 可见 tokenthinking disabled)。纠正在 `finish_reason=length` 时走 `answer_truncated`、不扣点、不把半截写入成功 Turn;客户端保留已流出正文并提示未完成。等待态改为公开工具进度(正在比较候选时间等)和 8 秒后的已用时,不展示模型思维链。
- 验证:`frontend/tests/rectification-v9-stream.test.ts` 的 length 夹断不得 `run.completed``frontend/tests/rectification-v9-agent.test.ts` 锁定纠正流的输出预算与 thinking disabled`frontend/tests/agent-activity-progress.test.ts``frontend/tests/rectification-agentic-entry.test.ts``frontend/tests/consultation-workflow-contract.test.ts`
- 防复发:纠正与咨询必须走同一套 generation settings。不得为了等待体验打开 provider thinking。`tool.activity started` 必须驱动 Orb 文案。`finish_reason=length` 不得映射为 `run.completed`
- 相关记录:BUG-305、BUG-282、BUG-329
- 防复发:纠正与咨询必须走同一套 generation settings 与 8192 可见预算。不得为了等待体验打开 provider thinking。若打开 thinking,必须走独立 `thinking.delta`,不得把推理写进 `answer.delta``tool.activity started` 必须驱动 Orb 文案。`finish_reason=length` 不得映射为 `run.completed`
- 相关记录:BUG-305、BUG-282、BUG-329、BUG-345
- 复发自:BUG-305(咨询已修,纠正仍用默认 thinking 与任意 finish
- 修复版本:`6a44c778`
@@ -5211,3 +5211,35 @@
- 复发自:BUG-341(第三条咨询路径扩大了 mode 联合类型,未改类型谓词)
- 修复版本:eeee0e49
## BUG-345 | 生时纠正把工具重试自述当成回答,且 kind 在 schema 里是自由字符串
- 状态:resolved
- 首次发现:2026-08-21
- 最近更新:2026-08-21
- 影响面:`POST /api/rectification/agent``runV9AgentTurn`、证据工具 `proposedKind`/`domain` schema、生时纠正对话
- 用户现象:用户补了一条升学经历后,结算气泡里是英文工具重试自述(大意:proposedKind 被拒、education 不是合法 kind、改用 education_start),没有中文跟进问句。棋盘已推进,说明计分跑过,失败的是用户可见正文。
- 触发条件:用户给出升学类经历,模型把 `missing_evidence_categories` 里的领域名 `education` 当成 `proposedKind` 调用证据工具。
- 根因:与 BUG-278 / BUG-277 同类。`proposedKind``domain` 在 Zod schema 里是自由字符串,白名单只在 `execute``isEvidenceKind()` 里;模型在 JSON schema 里看不到 `education_start`。被拒后把重试过程写进 `text-delta`。纠正 runner 立刻把每个 `text-delta` 发成 `answer.delta`,没有咨询路径那种契约门。BUG-340 关闭 provider thinking 后,过程自述更容易落到正文通道。
- 修复:证据 kind/domain 改为枚举,模型在调用前能看到 `education_start`。工具失败未恢复成功前的正文、以及纯英文过程自述,不得进入 `answer.delta`。中文思维链走独立的 `thinking.delta`(来自 `reasoning-delta` 或契约未绿的中文片段);英文过程自述丢弃。纠正打开 provider thinking。界面灰色「思考过程」,有正文后默认折叠。
- 验证:`frontend/tests/rectification-v10-tool-contract.test.ts` 拒绝 `proposedKind: "education"``frontend/tests/rectification-v9-stream.test.ts` 英文重试自述不得出现在公共流,用户只拿到中文回答;思维链映射与折叠 UI 的源码合同。
- 防复发:模型必须遵守的词汇写在 schema 枚举里,不要只写在 execute。`answer.delta` 不得承载工具重试自述。思维链必须是独立事件类型。`thinking.delta` 不得写入 run_phase 表。
- 相关记录:BUG-277、BUG-278、BUG-340、BUG-346
- 复发自:BUG-277(纠正未做契约门)、BUG-278kind 未枚举)、BUG-340(关 thinking 后自述改走正文)
- 修复版本:待提交
## BUG-346 | 普通咨询未打开思维链通道,灰色折叠 UI 只在生时纠正生效
- 状态:resolved
- 首次发现:2026-08-21
- 最近更新:2026-08-21
- 影响面:`POST /api/consult``streamAgentResponse`、咨询页 `ChatMessageRow`
- 用户现象:生时纠正已有灰色「思考过程」、正文出来后折叠;普通咨询仍无思维链。
- 触发条件:网页个人咨询 / 无分钟百科 / 声明窗口咨询。
- 根因:BUG-305 / BUG-340 为保住可见 token 预算,把咨询 `consultationGenerationSettings` 固定为 thinking disabled,并丢弃 `reasoning-*`。BUG-345 只给纠正打开独立 `thinking.delta` 与折叠 UI。
- 修复:咨询同样启用 provider thinking8192 可见预算不变。`reasoning-delta` 经中文清洗后发 `thinking.delta`;契约未绿的 `text-delta` 仍按 BUG-277 丢弃,不升格为思维链。咨询页把 `thinkingText` 接到共用 `ChatMessageRow`,有正文后默认折叠。会话落盘不保存思维链。
- 验证:`frontend/tests/consultation-agentic-runtime.test.ts` 中文 reasoning 进 thinking 通道、英文过程自述不进正文;`consultation-workflow-contract.test.ts` 锁定 `thinking: "enabled"``chat-stream-layout.test.ts` 锁定咨询页与折叠 UI。
- 防复发:咨询与纠正的思维链必须是 `thinking.delta`,不得混进 `answer.delta`。BUG-277 的契约前正文仍须丢弃。打开 thinking 不得降低 8192 可见预算,`finish_reason=length` 仍不得当完成。
- 相关记录:BUG-277、BUG-305、BUG-340、BUG-345
- 复发自:BUG-305(咨询关 thinking 保预算)、BUG-345(只修了纠正)
- 修复版本:待提交