修复DirectProject对话历史分页卡页

聊天历史按有效消息分页并返回原生游标,保留默认原始切片接口
工具和推理记录不占聊天页名额,逐行过滤避免传回大段工具输出
隔离重新加载和项目切换的迟到响应,补齐单飞、重试与消息去重
补充原生和真实App回归测试,增加人工只读日志重放入口
更新B05状态、规范与PR验收记录,不提交用户原始日志
This commit is contained in:
2026-09-16 18:46:47 +08:00
parent 825ea76b7b
commit 1b010fb1f8
14 changed files with 685 additions and 36 deletions
@@ -32,6 +32,9 @@
## 2026-09-16 DirectProject 回合展示唯一归属
- 聊天历史使用 `read_direct_project_history_slice``messagesOnly: true` 模式,按有正文的 user/assistant 消息分页,默认 20 条;工具/推理原始记录不占聊天页名额、不进入聊天分页响应,也不从磁盘删除。接口省略该选项时维持原始 item 切片语义。响应给出明确的 `oldestItemId` 游标;消息投影不能重新发明分页位置。
- 消息模式读取逐行过滤原始记录,不在内存中积累整份工具输出;正文、原始 ID 和信封时间原样保留。旧的无 ID 消息不能凭空生成身份,必要时向前扩展到已有消息 ID 边界;没有更早消息时结束分页。
- 首屏和加载更早消息共用分页解析;重复点击只发一个请求,重叠消息按原始 ID 去重并保留当前显示版本。切项目、同项目重新加载及 A→B→A 的迟到响应不得覆盖当前消息、游标或加载状态;失败保留已有消息与分页位置并允许重试。
- 交付合同:实时消息、历史回读、工具详情与最终回复先归一为按 `clientTurnId` 唯一的回合,再渲染一次。用户消息始终保留;同一回合的正文、工具和耗时不能从消息、实时尾部、未归属尾部等多个出口重复展示。
- 归属来自 `direct-codex:{clientTurnId}:{role}`、文本流中保留的原始 item ID,以及项目历史内明确用户记录之后的 assistant 记录。先在已加载的完整消息集合中关联,再做可见分页;持久历史继续通过 canonical item 切片懒加载,`hasMore` 为真时,未加载回合的工具流不得漂到当前页尾部。禁止将第 N 个有工具回合配给第 N 条用户消息,禁止按文本长度、标点或时间窗猜测归属。缺身份的旧记录保留,不猜造其与其它回合的关联。
- 有回合流时正文与工具位置仅来自 item 边界与 `seq`,工具详情按该回合的 `callId` 关联;没有流时同一个回合容器显示历史消息与工具。整轮累计文本仅在活动回合尚无流和持久 assistant 时作兜底,不另建实时消息出口。