Skip to content

feat(history): 扩展会话索引修复,补齐不完整轮次与用时 - #2649

Open
Yuimi-chaya wants to merge 10 commits into
BigPizzaV3:mainfrom
Yuimi-chaya:codex/thread-history-hydration-20261021
Open

Yuimi-chaya wants to merge 10 commits into
BigPizzaV3:mainfrom
Yuimi-chaya:codex/thread-history-hydration-20261021

Conversation

@Yuimi-chaya

@Yuimi-chaya Yuimi-chaya commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

问题与现有修复的关系

历史搜索能找到消息,但对话时间线可能跳过轮次,或只显示中间工作过程,缺少最终答复、文件改动及用时。一种已确认的情况是:源记录和历史索引完整,后端能够返回内容,但前端已经登记的轮次没有加载完整。

#2262 已提供基于 rollout 的消息索引修复。本 PR 在同一流程中补充前端恢复阶段,不创建第二套入口或自动 loader。持久化索引仍由原有修复负责,前端阶段不改写 rollout 或 SQLite。

入口与触发

  • 沿用「会话管理 → 修复会话索引」按钮、原有自动检查开关及报告界面,不新增开关、按钮、bridge route 或常驻扫描。
  • 沿用启动及注入完成后的首次索引检查、每次检查完成后间隔 30 分钟复查,以及激活已有实例的流程。手动按钮不依赖自动检查开关。
  • 原有索引检查成功且未中止后才请求前端补载,数据库没有新增修复项时也可执行。读取或刷新报告不触发补载。
  • 不保留延迟请求、定时重试或排队任务。当前页面不适合修复时跳过,不把请求重放到之后打开的其他会话。

不完整轮次的恢复

  • 处理当前本机会话中已登记的终态轮次,包括连续多个非空但分页未完成的轮次,不再要求空数组或前后有内容的锚点。
  • 修正“恢复用户输入就算完成”的提前停止条件。已有输入或工作过程不代表消息完整;只有原生 hasLoadedOldest 才确认消息分页完成。
  • 移除每轮四页的截断。串行调用原生 loadTurnItems(..., false, ...),在共享预算内继续读取;之前已补回部分内容的轮次,在后续修复中仍可继续处理。
  • 先补齐选定轮次的消息,再查询缺失的时间信息,避免慢元数据扫描反复耗尽预算,使正文和文件改动始终得不到补载。
  • 最终答复及文件改动来自原生 agentMessage、fileChange 等消息,保留原生显示和文件改动派生逻辑,不自行生成报告或文件清单。
  • 原生消息分页不会回填轮次用时。对缺失的用时及开始、完成时间,以 thread/turns/list 的 itemsView: "notLoaded" 模式读取元数据,不请求消息正文。只对原生 ID 与终态匹配的现存轮次,经原生状态接口填入缺值;保留已有值,包括 0。
  • 元数据修复不改轮次状态、消息、用户输入、分页游标或 canonical islands,也不整体重新 hydrate 会话。源记录没有对应时间值时不推算或伪造。

并发与安全边界

  • 只选择可确认归属的 Codex 主窗口及本机会话;原生 raw manager 必须已有对应 AppScope family 绑定,发现过程不创建管理器,不执行读取到的源码。
  • 每次读取前后及元数据更新回调内,核验管理器身份、存活状态、当前会话、历史 generation 和原生忙碌状态。元数据更新还要求当前窗口为 owner;任何未确认提交都让步,包括已终止但尚未核销的收据。
  • 切换会话、隐藏窗口、重新注入、历史代际变化或管理器退出时停止后续操作。同步订阅在更新后触发退出或生成时,也不再广播迟到快照。
  • 每次修复最多处理 32 个轮次,消息和元数据共享 128 次分页调用预算;其中元数据查找最多 64 页,每页 32 个轮次。超过 12 秒不再发起新读取,保留原生驱逐及重连边界。
  • 预算耗尽、读取失败或元数据无法核实,结果为部分完成,不宣称轮次已完整。消息读取失败或无进展时结束请求;元数据不兼容不会撤回已经完成的消息补载。
  • 共享 in-flight 门控和有界请求去重,重注入不产生并行读取链。通知等待最多 20 秒,超时不重发,也不反转已完成的数据库修复。
  • 不启动轮次或模型请求,不修改供应商配置,不把前端分页计数混入数据库消息恢复数量;诊断只记录状态及计数,不记录聊天正文。

上游兼容

已合并上游 v1.11.1 的 main。两处冲突均为已等价合入修复的注释差异,保留上游实现和注释;未回退上游更新。

保留独立的默认状态路径测试隔离锁及供应商同步测试断言。前端界面、翻译、原有索引扫描和修复职责不另起实现。

验证

  • 新增的三个关键回归先在旧代码上失败:用户输入导致提前停机、连续非空轮次被漏选、再次修复跳过已部分加载的轮次。
  • 完整前端:784 passed / 0 failed / 1 项既有 skip,其中包含 39 项历史补载行为测试。
  • TypeScript、Rust 文件格式、renderer 与 native browser inspector 组装一致性、manifest 行数及 git diff --check 通过。
  • 完整 Rust workspace:98 组,2750 passed / 0 failed / 23 项既有 ignored / 0 filtered;锁定依赖、离线 Release、编译并发为 2,测试使用默认并行。
  • 最终生成注入资源重新编译后的补载核心专项:4 passed / 0 failed,覆盖通知、报告预算、元数据计数及旧版报告兼容。

限制

这是对已登记轮次加载不完整及缺失时间信息的有界恢复,不表示已查明最初留下异常前端状态的原因。未登记的历史、损坏的索引、丢失的源文件和缺失的原生消息投影,不由前端阶段猜测补建。

本次修复已覆盖静态原生契约及自动化回归;更新后的实际应用验收仍待进行,不把之前的人工补载成功当作本次修复的验收。仅适配可确认归属的主窗口本机会话,远端主机、活动悬浮层和快捷聊天不在范围内。

使用与边界见 docs/session-index-repair.md 和 docs/history-turn-recovery.md。

@130040167

130040167 commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

看起来和会话管理的 修复会话索引 功能差不多?可以直接完善那个。#2262

@Yuimi-chaya
Yuimi-chaya force-pushed the codex/thread-history-hydration-20261021 branch from 10b8912 to 6172235 Compare October 21, 2026 10:21
@BigPizzaV3

Copy link
Copy Markdown
Owner

当前 head 的 Windows/macOS CI 均已通过。复核发现本 PR 与已关闭的 #2262 在“历史空轮次/缺失消息补载”职责上存在明显重叠;合并前请明确由哪个入口负责补载,避免两套自动 loader 并行。当前暂不列入可直接合并清单。

@Yuimi-chaya

Copy link
Copy Markdown
Contributor Author

感谢提醒,我核对了 #2262 和当前 main。两者确实都面向历史消息缺失,但修复层次不同:#2262 从 rollout 修复原生数据库中的消息索引;#2649 处理消息及索引已经存在、后端能够返回,但前端轮次内容尚未加载而不显示的情况。

这次 10 月的实际案例中,数据库和后端读取均正常,调用原生轮次补载后内容恢复,因此仅重复索引修复不能覆盖这个场景。当前旧功能调用的是 Rust 索引修复,并不调用前端的 loadTurnItems。

我认同避免重复入口和自动调度。如果希望统一到现有会话修复功能下,我可以据此调整入口和职责划分,保留数据库索引修复与前端补载两个阶段。想先确认,这是否是期望的整合方向?

@Yuimi-chaya

Copy link
Copy Markdown
Contributor Author

@130040167 可以在现有会话修复入口下完善,我认同尽量复用入口。只是这次需要补充的是前端加载状态的恢复,单独扩展 Rust 侧的索引扫描还不够。

10 月 16 日排查的实际情况是:缺失消息已经同时存在于 rollout 和原生历史数据库中,后端历史接口也能返回;但已打开会话里的三个前端轮次,其 items 和用户输入数组都是空的,分页又没有加载完,因此没有显示出来。调用原生 loadTurnItems 后内容就恢复了,过程中没有补写数据库。

所以不是认为 #2262 没生效,而是它处理的“索引缺项”和这次的“索引已有、前端未加载”需要分别处理。如果统一到现有入口,可以保留索引检查,再增加针对当前已打开会话的前端补载阶段,由明确的触发入口负责,避免重复自动调度;不需要为这个场景重新插入消息或改写索引。

我可以按这个方向配合整合,具体入口和触发方式等维护者确认后再调整。至于前端最初为什么留下这些空轮次,目前还没有复现,这个 PR 是补载兜底,不是宣称已经修复了那个初始原因。

@130040167

Copy link
Copy Markdown
Contributor

嗯,整合在一起吧。

@Yuimi-chaya Yuimi-chaya changed the title feat(history): 补载被静默跳过的历史空轮次(默认关闭) feat(history): 扩展会话索引修复,补载前端历史空轮次 Oct 21, 2026
@Yuimi-chaya Yuimi-chaya changed the title feat(history): 扩展会话索引修复,补载前端历史空轮次 feat(history): 扩展会话索引修复,补齐不完整轮次与用时 Oct 22, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants