mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-01 12:22:09 +08:00
feat: unify Codex third-party providers into stable "custom" history bucket
Codex filters resume history by `model_provider`, so switching between provider-specific ids like `rightcode` and `aihubmix` made past sessions appear to vanish. Collapse all third-party providers into a single stable bucket so cross-switch history stays visible. - Normalize live `model_provider` to "custom" on every Codex write (reserved built-in ids like openai/ollama are preserved). - Add device-level one-shot migration that rewrites historical JSONL session files and the `state_5.sqlite` threads table from legacy provider ids into the "custom" bucket. Backs up originals under `~/.cc-switch/backups/codex-history-provider-migration-v1/` and uses the SQLite Backup API for the state DB. - Record completion in `settings.json` under `localMigrations` so the migration is strictly idempotent across launches. - Update Codex provider preset templates to emit `model_provider = "custom"` out of the box.
This commit is contained in:
@@ -21,6 +21,20 @@ fn merge_settings_for_save(
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if incoming.local_migrations.is_none() {
|
||||
incoming.local_migrations = existing.local_migrations.clone();
|
||||
} else if let (Some(incoming_migrations), Some(existing_migrations)) =
|
||||
(&mut incoming.local_migrations, &existing.local_migrations)
|
||||
{
|
||||
if incoming_migrations
|
||||
.codex_third_party_history_provider_bucket_v1
|
||||
.is_none()
|
||||
{
|
||||
incoming_migrations.codex_third_party_history_provider_bucket_v1 = existing_migrations
|
||||
.codex_third_party_history_provider_bucket_v1
|
||||
.clone();
|
||||
}
|
||||
}
|
||||
incoming
|
||||
}
|
||||
|
||||
@@ -83,7 +97,10 @@ pub async fn set_auto_launch(enabled: bool) -> Result<bool, String> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::merge_settings_for_save;
|
||||
use crate::settings::{AppSettings, WebDavSyncSettings};
|
||||
use crate::settings::{
|
||||
AppSettings, CodexThirdPartyHistoryProviderBucketMigration, LocalMigrations,
|
||||
WebDavSyncSettings,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn save_settings_should_preserve_existing_webdav_when_payload_omits_it() {
|
||||
@@ -204,6 +221,40 @@ mod tests {
|
||||
Some("")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn save_settings_should_preserve_local_migrations_when_payload_omits_it() {
|
||||
let existing = AppSettings {
|
||||
local_migrations: Some(LocalMigrations {
|
||||
codex_third_party_history_provider_bucket_v1: Some(
|
||||
CodexThirdPartyHistoryProviderBucketMigration {
|
||||
completed_at: "2026-05-20T00:00:00Z".to_string(),
|
||||
target_provider_id: "custom".to_string(),
|
||||
source_provider_ids: vec!["rightcode".to_string()],
|
||||
migrated_jsonl_files: 2,
|
||||
migrated_state_rows: 3,
|
||||
},
|
||||
),
|
||||
}),
|
||||
..AppSettings::default()
|
||||
};
|
||||
|
||||
let incoming = AppSettings::default();
|
||||
let merged = merge_settings_for_save(incoming, &existing);
|
||||
|
||||
let migration = merged
|
||||
.local_migrations
|
||||
.as_ref()
|
||||
.and_then(|migrations| {
|
||||
migrations
|
||||
.codex_third_party_history_provider_bucket_v1
|
||||
.as_ref()
|
||||
})
|
||||
.expect("local migration marker should be preserved");
|
||||
assert_eq!(migration.target_provider_id, "custom");
|
||||
assert_eq!(migration.migrated_jsonl_files, 2);
|
||||
assert_eq!(migration.migrated_state_rows, 3);
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取开机自启状态
|
||||
|
||||
Reference in New Issue
Block a user