Skip to content

修复管理工具窗口居中与会话删除残留 - #1806

Open
success-crypto wants to merge 4 commits into
BigPizzaV3:mainfrom
success-crypto:agent/center-manager-on-startup
Open

修复管理工具窗口居中与会话删除残留#1806
success-crypto wants to merge 4 commits into
BigPizzaV3:mainfrom
success-crypto:agent/center-manager-on-startup

Conversation

@success-crypto

@success-crypto success-crypto commented Aug 8, 2026

Copy link
Copy Markdown

问题与根因

本 PR 现在包含两组相互独立的管理器修复。

  1. 管理工具首次启动时没有主动设置窗口位置,窗口位置完全由系统决定,因此有时不会居中。
  2. 删除本地会话时,只要任一正文数据库删除成功就会整体返回成功,但没有继续清理其他 SQLite 数据库中的 local_thread_catalog 和 thread_timeline_ledger。结果是 threads 行和 rollout 文件已经不存在,侧栏仍显示旧标题,点击后出现 no rollout found。
  3. 旧版本还可能在 session_index.jsonl、全局状态文件和目录时间线中留下升级前的空壳引用,普通删除流程无法处理这些历史残留。

修改内容

管理器窗口

  • 创建主窗口时调用 Tauri center,使首次启动位置稳定居中。
  • 保留现有关闭、最小化、托盘和 transient 生命周期逻辑。

正常会话删除

  • 删除时遍历正文数据库和 thread-reference 数据库。
  • 备份并删除相同 thread ID 对应的 local_thread_catalog 与 thread_timeline_ledger 行。
  • 删除目录行后正确递增 local_thread_catalog_metadata.catalog_revision。
  • 不修改 local_thread_catalog_sync_state 的主机同步游标。
  • 多数据库删除出现部分失败时返回 Partial 状态和具体失败原因,不再静默报告完全成功。
  • 将所有成功数据库的备份组合为统一撤销令牌;撤销前预检全部数据库和 rollout 冲突,避免只恢复一部分或覆盖新会话。

历史已删除会话清理

  • 将旧 session_index 残留清理升级为完整的历史已删除会话清理。
  • 预览综合检查所有候选 SQLite 中的 threads、automation_runs、inbox_items、messages 等正文来源,以及 sessions 和 archived_sessions 中的真实 rollout。
  • thread_timeline_ledger 仅视为引用,不作为有效正文来源。
  • 正常数据库会话、仍有活动或归档 rollout 的会话、远程主机会话不会进入候选。
  • 候选显示 thread ID、标题、更新时间、项目或工作区,以及 catalog、timeline、session_index、global-state 等残留来源。
  • 默认不自动选择;用户勾选后还需要二次确认。
  • 预览返回快照哈希和 catalog revision;应用前重新校验,任何相关数据变化都会中止并要求重新预览。
  • 执行前要求完全退出 Codex App 或 ChatGPT,Codex++ 管理器本身可以保留。
  • session_index 使用记录级解析;全局状态使用结构化 JSON 清理和原子替换,只删除 thread 专属键、精确 ID 数组元素及精确 ID 属性绑定,不删除普通提示文本中碰巧出现的 ID。
  • SQLite 清理在事务中执行;失败会回滚当前数据库并返回逐来源完成数量、失败原因和备份路径。

备份与撤销

  • 每次清理创建独立批次备份目录。
  • manifest 保存所选 ID、候选来源、时间、原文件哈希、清理后哈希、数据库行和逐来源删除数量。
  • 保存 session_index.jsonl、.codex-global-state.json 和 .bak 原文件。
  • 管理器提供撤销最近一次残留清理入口。
  • 撤销前检查同 ID 新会话、rollout、数据库行以及清理后文件哈希;检测到冲突时拒绝覆盖。
  • 撤销目录行后再次递增 catalog revision。

用户影响

  • 正常删除会话后,侧栏目录项会同步消失,不再留下点击时报 no rollout found 的标题。
  • 升级前遗留的空壳记录可以先预览、手动选择、安全清理并撤销。
  • 正常、归档、远程和在预览后发生变化的会话受到保护。

验证

  • cargo test -p codex-plus-data:68 项通过,其中历史残留专项 9 项通过。
  • cargo test -p codex-plus-manager --lib:50 项通过。
  • npm run check:通过。
  • npm run test:56 项通过。
  • npm run vite:build:通过。
  • git diff --check:通过。

严格 Clippy 仍会被 markdown、provider_sync 和 storage 中 14 个既有警告阻断;本次新增 historical_cleanup 模块没有剩余 Clippy 报错。

@success-crypto

Copy link
Copy Markdown
Author

已按 #1619 的反馈基于 v1.2.45 重做为最小补丁,仅处理首次启动居中,不再修改窗口生命周期逻辑。当前 PR build artifacts 工作流状态为 action_required,烦请批准来自 Fork 的 CI 运行,以验证 Windows、Intel Mac 和 Apple Silicon Mac 构建。

@success-crypto
success-crypto force-pushed the agent/center-manager-on-startup branch from 8f36b01 to 0742100 Compare August 13, 2026 13:43
根因:普通删除流程只要任一正文数据库删除成功就会返回成功,但不会继续清理其他 SQLite 中的 local_thread_catalog 和 thread_timeline_ledger,导致正文及 rollout 已不存在时侧栏标题仍然保留。

修改内容:
- 普通删除遍历正文库与 thread-reference 数据库,备份并删除相同 thread ID 的目录和时间线行,正确递增 catalog revision;
- 部分数据库失败时返回部分成功及失败原因,保留可撤销备份;撤销前统一预检冲突;
- 将旧 session_index 清理升级为历史已删除会话清理,综合 threads、自动化记录、消息正文、活动及归档 rollout 判断真实来源;
- 预览显示标题、更新时间、工作区及 catalog/timeline/session_index/global-state 残留来源;默认不选择,并在执行前二次确认;
- 使用快照哈希和 catalog revision 防止预览后覆盖新数据,执行前要求完全退出 Codex App/ChatGPT;
- 结构化清理 session_index 和 global-state,仅移除 thread 专属键、精确 ID 绑定与数组元素,保留普通文本;
- 每批创建包含数据库行、原文件、哈希和删除统计的 manifest 备份,并提供冲突安全的撤销入口;
- 增加正常删除、历史空壳、归档保护、远程主机保护、并发变化、写入失败和撤销冲突测试。

验证:
- cargo test -p codex-plus-data:68 项通过;
- cargo test -p codex-plus-manager --lib:50 项通过;
- npm run check:通过;
- npm run test:56 项通过;
- npm run vite:build:通过。
@success-crypto success-crypto changed the title 修复管理工具首次启动不居中 修复管理工具窗口居中与会话删除残留 Aug 15, 2026

@BigPizzaV3 BigPizzaV3 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这组改动目前有两个会让用户难以恢复的阻塞问题:

  1. 历史清理先逐个改写三个 JSON/JSONL 文件,再逐个提交多个 SQLite 数据库。任一后续数据库失败时,前面的文件或数据库已经永久修改,函数只返回 partial_result,不会自动回滚。更关键的是,后端失败响应虽然带回 backupDir,前端却只在 isSuccessStatus(cleanup.status) 分支调用 setHistoricalCleanupBackupDir。因此真实的部分失败发生后,界面不会出现“撤销最近一次残留清理”,用户拿不到这份专门创建的恢复入口。至少应在成功或失败响应带有 backupDir 时都保留撤销入口,并补一个“第 N 个数据库失败后可从 UI 撤销已完成文件/数据库修改”的测试;更稳妥的是失败时自动按 manifest 回滚。

  2. 正常会话删除在数据库提交成功、rollout 文件删除失败时仍返回 DeleteStatus::Failed。新的 delete_local_from_paths 只把 LocalDeleted | Partial 计入 deleted_count,所以这种情况下会向上层报告“失败”,实际正文数据库及目录行已经删除,并且组合撤销 token 也不会被收集。请把这种“数据库已删、文件未删”的结果标记为 Partial,保证聚合结果和撤销 token 与真实状态一致,并补对应回归测试。

PR 同时包含窗口定位、普通删除和 1100 多行历史清理,当前没有 GitHub CI 结果。上述问题修复后还需要完整跑前端、Rust 和三平台构建检查。

失败响应保留历史清理备份入口,并允许从部分执行状态安全恢复未改动的同值文件和目录行。数据库已删除但 rollout 删除失败时返回 Partial,聚合撤销令牌与真实状态保持一致。
@success-crypto

Copy link
Copy Markdown
Author

@BigPizzaV3 已按评审中的两个阻塞问题完成修复,提交为 4dde191

  1. 历史清理失败响应只要带有 backupDir,前端也会保留“撤销最近一次残留清理”入口。撤销逻辑现在能从“第 N 个数据库失败”的部分执行状态恢复:已删除的行会恢复,未删除且与备份完全相同的行/文件会安全跳过,内容不同的同 ID 数据仍会被判定为冲突并拒绝覆盖。已增加第二个 SQLite 删除失败后通过备份完整撤销的回归测试,以及失败响应保留 UI 恢复入口的前端测试。

  2. 数据库提交成功但 rollout 删除失败时改为 DeleteStatus::Partialdelete_local_from_paths 会按真实状态计入已删除项并收集组合撤销 token。撤销时允许保留内容与备份完全一致的 rollout,内容不同仍拒绝覆盖。已通过注入确定性文件删除失败的测试覆盖聚合和撤销路径。

本地验证:

  • cargo test -p codex-plus-data:80 项通过
  • cargo test -p codex-plus-manager --lib:56 项通过
  • cargo test -p codex-plus-manager --test windows_subsystem:23 项通过
  • cargo check --workspace:通过
  • npm test:68 项通过
  • npm run check:通过
  • npm run vite:build:通过

macOS Intel / Apple Silicon 构建请由 GitHub CI 继续验证。

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.

2 participants