feat(codex): add opt-in migration and ledger-based restore for unified session history

- Enable dialog gains a checkbox (default off) to migrate existing
  official sessions from the built-in "openai" bucket into the shared
  "custom" bucket, with per-generation backups; failed migrations retry
  at startup
- Disable dialog offers a precise restore driven by the backup ledger:
  only sessions recorded as "openai" in backups are flipped back, and
  sessions created while the toggle was on are never touched
- Completion marker and backup generations are bound to the canonical
  Codex config dir; migrate/restore serialize on an op lock and the
  marker is written conditionally inside the settings write lock
- save_settings rolls back the toggle and fails the save when the live
  rewrite fails; migration additionally requires the live config to
  actually route to the shared bucket (skips with live_not_unified so
  refused injection or proxy takeover can't split history)
- Restore refuses to run while the toggle is (re-)enabled and reports
  nothing_to_restore instead of a zero-count success; local migration
  markers are now backend-owned in merge_settings_for_save so stale
  frontend payloads can't resurrect them
- Settings autosave reverts optimistic form state on failure so a
  failed toggle change can't be replayed by an unrelated save
- ConfirmDialog supports an optional checkbox; all four locales updated
This commit is contained in:
Jason
2026-06-12 23:35:01 +08:00
parent 948d762792
commit eab6bfd20c
15 changed files with 1369 additions and 43 deletions
+17
View File
@@ -19,6 +19,13 @@ export interface WebDavTestResult {
message?: string;
}
export interface CodexUnifyHistoryRestoreResult {
restoredJsonlFiles: number;
restoredStateRows: number;
/** 还原被跳过的原因(如当前目录没有账本);存在时不应报成功 */
skippedReason?: string;
}
export interface WebDavSyncResult {
status: string;
}
@@ -32,6 +39,16 @@ export const settingsApi = {
return await invoke("save_settings", { settings });
},
/** 是否存在统一 Codex 会话历史的迁移备份(关闭弹窗据此显示"恢复备份"勾选) */
async hasCodexUnifyHistoryBackup(): Promise<boolean> {
return await invoke("has_codex_unify_history_backup");
},
/** 按迁移备份账本把当时迁入共享桶的官方会话还原回 openai 桶(幂等) */
async restoreCodexUnifiedHistory(): Promise<CodexUnifyHistoryRestoreResult> {
return await invoke("restore_codex_unified_history");
},
async restart(): Promise<boolean> {
return await invoke("restart_app");
},