Repository navigation
fix(chat): generate streamed answers only once - #6125
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
…eamed-answer-20261010 Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewer: model_agent; self_reported; model=GPT-6; provider=OpenAI
动机
没有发现阻塞问题。管家、普通项目与 Goal Chat 的用户在阅读流式回复时遇到这项开销。原来完整正文流完后,模型还要在隐藏 JSON 里再生成一遍;现在正文只生成一次,隐藏 JSON 复用正文。真实 Codex 两次请求均返回完整正文、闭合元数据,隐藏 message 为零字且没有协议警告。本 PR 不认证已安装 Bot 的回复时延,也不改变群准出标准、权限或派工。安装后的原话题时延、完整社区 golden queries 与公开群准出仍待验证。
改动思路
复用现有 prompt、parser 和 Codex 最终 item 边界,比增加第二份答案缓存或新协议版本更小且完整。本 PR 同时交付单次正文生成、最终 item 选择、负例和兼容测试及双语契约;合并后才进入安装与原话题复测。
参考既有契约 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,固定版本 cfd1bba80cc776f40a4f23294b00dbc185748aa3,判定行 Waiting is part of the conversation:收发消息、真实活动和可读答案仍通过原入口;两次真实 Codex 请求及原生事件回放验证,群准出时延另验。文档新增条款说明实现约定,没有把未达标时延写成通过。
具体改动
_turn_prompt要求完整可见 Markdown,随后仍必须附闭合 review JSON,但message留空,不再重复正文。parse_agent_response仅在闭合且可解析的 dict 中对显式空字符串复用正文,再进入原有脱敏和 typed normalization。非空旧值优先;缺失/null 不启用复用;不闭合、格式错误和更早隐藏信封不会泄漏动作或协议正文。CodexChatAgentSession.send把结构化结果已经采用的完成 item 选择复用于普通回答,排除 commentary 与不完整 deltas。类型化动作、派工与确认 owner 不变;ACP/DSH/Claude/API 继续用同一个 prompt/parser。- 三组已有测试覆盖兼容、最终消息及流式边界;中英文 RFC 同步披露默认变化。源 diff 为 133 加 / 15 删,7 文件,无新服务、状态或版本。
对主干的风险
显式空字符串现在有正文复用含义,因此必须保留 parser 与最终 item 选择的共同修复。旧非空、闭合失败、脱敏和 structured-output 路径均回归;同一事件 fixture 在 base/head 证明旧协议及不闭合行为一致,旧版 compact 答案为空及 commentary 动作提升则被修复。
合入当前主干恢复改动后,297 项相关测试通过;mypy、semantic drift smoke、diff hygiene 和风险分流 premerge 已检查。旧实现上的新 parser oracle 按预期失败。真实 gpt-6.1-sol / xhigh 连续两次请求返回完整正文、零重复 message、无协议警告。原生事件 fixture 模拟 host IO;真实模型验证只覆盖该协议,不证明 App/IM 时延和所有模型组合。按本 Goal 的 wait_for_ci=false 使用本地验证,不查询或等待 CI;GitHub 分支保护与实际合并权限单独判定。
我的整体评价
复用现有 prompt、parser 和 Codex 最终 item 边界,比增加第二份答案缓存或新协议版本更小且完整。本 PR 同时交付单次正文生成、最终 item 选择、负例和兼容测试及双语契约;合并后才进入安装与原话题复测。认可这个可独立回退的传输层增量;没有重复缓存、新生命周期或并行权限 owner。安装、原话题测试及公开群准出继续由已有社区验收任务推进,不能用 PR、测试数量或两次合成请求替代准出。作者自评是透明的 COMMENTED 记录,不冒充独立人工批准或 GitHub APPROVED;也不授予 admin bypass。
English verdict: APPROVE - exact head fdaca9b; one complete streamed answer, compact hidden metadata, final-item and fail-closed boundaries preserved. 297 focused tests, type/semantic/premerge checks, base/head replay and two real Codex requests pass; installed latency and community admission remain unqualified.
…eamed-answer-20261010 Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewer: model_agent; self_reported; model=GPT-6; provider=OpenAI
动机
没有发现阻塞问题。管家、普通项目与 Goal Chat 的用户在阅读流式回复时遇到这项开销。原来完整正文流完后,模型还要在隐藏 JSON 里再生成一遍;现在正文只生成一次,隐藏 JSON 复用正文。真实 Codex 两次请求均返回完整正文、闭合元数据,隐藏 message 为零字且没有协议警告。本 PR 不认证已安装 Bot 的回复时延,也不改变群准出标准、权限或派工。安装后的原话题时延、完整社区 golden queries 与公开群准出仍待验证。
改动思路
复用现有 prompt、parser 和 Codex 最终 item 边界,比增加第二份答案缓存或新协议版本更小且完整。本 PR 同时交付单次正文生成、最终 item 选择、负例和兼容测试及双语契约;合并后才进入安装与原话题复测。
参考既有契约 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,固定版本 5de71093cee3217c66cc32394fd841f6c831f5e2,判定行 Waiting is part of the conversation:收发消息、真实活动和可读答案仍通过原入口;两次真实 Codex 请求及原生事件回放验证,群准出时延另验。文档新增条款说明实现约定,没有把未达标时延写成通过。
具体改动
_turn_prompt要求完整可见 Markdown,随后仍必须附闭合 review JSON,但message留空,不再重复正文。parse_agent_response仅在闭合且可解析的 dict 中对显式空字符串复用正文,再进入原有脱敏和 typed normalization。非空旧值优先;缺失/null 不启用复用;不闭合、格式错误和更早隐藏信封不会泄漏动作或协议正文。CodexChatAgentSession.send把结构化结果已经采用的完成 item 选择复用于普通回答,排除 commentary 与不完整 deltas。类型化动作、派工与确认 owner 不变;ACP/DSH/Claude/API 继续用同一个 prompt/parser。- 三组已有测试覆盖兼容、最终消息及流式边界;中英文 RFC 同步披露默认变化。源 diff 为 133 加 / 15 删,7 文件,无新服务、状态或版本。
对主干的风险
显式空字符串现在有正文复用含义,因此必须保留 parser 与最终 item 选择的共同修复。旧非空、闭合失败、脱敏和 structured-output 路径均回归;同一事件 fixture 在 base/head 证明旧协议及不闭合行为一致,旧版 compact 答案为空及 commentary 动作提升则被修复。
合入当前主干恢复改动后,297 项相关测试通过;mypy、semantic drift smoke、diff hygiene 和风险分流 premerge 已检查。旧实现上的新 parser oracle 按预期失败。真实 gpt-6.1-sol / xhigh 连续两次请求返回完整正文、零重复 message、无协议警告。原生事件 fixture 模拟 host IO;真实模型验证只覆盖该协议,不证明 App/IM 时延和所有模型组合。按本 Goal 的 wait_for_ci=false 使用本地验证,不查询或等待 CI;GitHub 分支保护与实际合并权限单独判定。
我的整体评价
复用现有 prompt、parser 和 Codex 最终 item 边界,比增加第二份答案缓存或新协议版本更小且完整。本 PR 同时交付单次正文生成、最终 item 选择、负例和兼容测试及双语契约;合并后才进入安装与原话题复测。认可这个可独立回退的传输层增量;没有重复缓存、新生命周期或并行权限 owner。安装、原话题测试及公开群准出继续由已有社区验收任务推进,不能用 PR、测试数量或两次合成请求替代准出。作者自评是透明的 COMMENTED 记录,不冒充独立人工批准或 GitHub APPROVED;也不授予 admin bypass。
English verdict: APPROVE - exact head d63556b; one complete streamed answer, compact hidden metadata, final-item and fail-closed boundaries preserved. 297 focused tests, type/semantic/premerge checks, base/head replay and two real Codex requests pass; installed latency and community admission remain unqualified.
Chat currently asks the model to emit its complete Markdown answer and then generate the same answer again inside the hidden review JSON. Keep one visible answer and use an explicitly empty envelope
messageto reuse it through the existing parser. Codex selects the completed final answer item so earlier commentary cannot pollute the answer or supply action metadata.Legacy nonempty messages retain precedence. Missing/null fields do not enable reuse, malformed or unclosed envelopes still drop action metadata, and existing redaction/typed normalization remain in place. The shared transport seam serves ordinary, manager and Goal Chat; bilingual conversation docs describe the convention. The related final-item cleanup is included because compact responses need that boundary. No new authority owner or protocol version is introduced.
Validation: 278 focused tests passed, including offline intake evaluation, every-split stream redaction, legacy compatibility, incomplete-envelope negatives and commentary rejection; the new parser regression fails against the base implementation. Mypy passed. Two public synthetic requests through the real Codex adapter (
gpt-6.1-sol,xhigh) returned complete answers with closed envelopes, no protocol warnings, and zero duplicated message characters. This is protocol validation; installed Bot/topic latency and community admission are not qualified by these synthetic requests.