docs(cleanup): remove 'current' as special provider; align UI/messages and migration naming to 'default' and one-time import rule

- App: update auto-import message to '默认供应商'
- README: clarify default import only when providers are empty
- Plan doc: replace 'current entry' wording with current pointer (manager.current)
- Migration: name live-imported item 'default' instead of 'current'
This commit is contained in:
Jason
2025-09-05 15:16:03 +08:00
parent a1dfdf4e68
commit ab6be1d510
4 changed files with 13 additions and 13 deletions

View File

@@ -69,7 +69,7 @@
- 供应商副本:`auth-<name>.json``config-<name>.toml`
- API Key 字段:`auth.json` 中使用 `OPENAI_API_KEY`
- 切换策略:将选中供应商的副本覆盖到主配置(`auth.json``config.toml`)。若供应商没有 `config-*.toml`,会创建空的 `config.toml`
- 导入默认:`~/.codex/auth.json` 存在,会将当前主配置导入为 `current` 供应商`config.toml` 不存在时按空处理。
- 导入默认:仅当该应用无任何供应商时,从现有主配置创建一条默认项并设为当前`config.toml` 不存在时按空处理。
- 官方登录可切换到预设“Codex 官方登录”,重启终端后可选择使用 ChatGPT 账号完成登录。
### Claude Code 说明
@@ -79,7 +79,7 @@
- 供应商副本:`settings-<name>.json`
- API Key 字段:`env.ANTHROPIC_AUTH_TOKEN`
- 切换策略:将选中供应商的副本覆盖到主配置(`settings.json`/`claude.json`)。如当前有配置且存在“当前供应商”,会先将主配置备份回该供应商的副本文件。
- 导入默认:`~/.claude/settings.json``~/.claude/claude.json` 存在,会将当前主配置导入为 `current` 供应商副本
- 导入默认:仅当该应用无任何供应商时,从现有主配置创建一条默认项并设为当前
- 官方登录可切换到预设“Claude 官方登录”,重启终端后可使用 `/login` 完成登录。
### 迁移与备份

View File

@@ -14,13 +14,13 @@
- 当前:
- 全局配置:`~/.cc-switch/config.json`v2`MultiAppConfig`,含多个 `ProviderManager`)。
- 切换依赖“供应商副本文件”Claude`~/.claude/settings-<name>.json`Codex`~/.codex/auth-<name>.json``config-<name>.toml`)→ 恢复到主配置。
- 启动:若检测到现有主配置自动导入为 `current` 供应商
- 启动:若对应 App 的供应商列表为空,可从现有主配置自动创建一条“默认项”并设为当前
- 问题:存在“副本 ↔ 总配置”双来源,可能不一致;明文落盘有泄露风险。
## 3. 总体方案
- 以加密文件 `~/.cc-switch/config.enc.json` 替代明文存储;进程启动时解密一次加载到内存,后续以内存为准;保存时加密写盘。
- 切换时:直接从内存 `Provider.settings_config` 写入目标应用主配置;切换前回填当前 live 配置到 `current` 供应商,保留外部修改。
- 切换时:直接从内存 `Provider.settings_config` 写入目标应用主配置;切换前回填当前 live 配置到当前选中供应商(由 `manager.current` 指向),保留外部修改。
- 明文兼容:若无加密文件,读取旧 `config.json`(含 v1→v2 迁移),首次保存写加密文件,并备份旧明文。
- 旧文件清理:提供“可回滚归档”而非删除。扫描 `~/.cc-switch/config.json`v1/v2与 Claude/Codex 的历史副本文件,用户确认后移动到 `~/.cc-switch/archive/<ts>/`,生成 `manifest.json` 以便恢复;默认不做静默清理。
@@ -66,10 +66,10 @@
- `MultiAppConfig::save()`:统一调用 `write_encrypted_config()`;若检测到旧 `config.json`,首次保存时备份为 `config.v1.backup.<ts>.json`(或保留为只读,视实现选择)。
- 调整 `src-tauri/src/commands.rs::switch_provider`
- Claude
1. 回填:若 `~/.claude/settings.json` 存在且 `current` 非空 → 读取 JSON写回 `manager.providers[current].settings_config`。
1. 回填:若 `~/.claude/settings.json` 存在且存在当前指针 → 读取 JSON写回 `manager.providers[manager.current].settings_config`。
2. 切换:从目标 `provider.settings_config` 直接写 `~/.claude/settings.json`(确保父目录存在)。
- Codex
1. 回填:读取 `~/.codex/auth.json`JSON与 `~/.codex/config.toml`(字符串;非空做 TOML 校验)→ 合成为 `{auth, config}` → 写回 `manager.providers[current].settings_config`。
1. 回填:读取 `~/.codex/auth.json`JSON与 `~/.codex/config.toml`(字符串;非空做 TOML 校验)→ 合成为 `{auth, config}` → 写回 `manager.providers[manager.current].settings_config`。
2. 切换:从目标 `provider.settings_config` 中取 `auth`(必需)与 `config`(可空)写入对应主配置(非空 `config` 校验 TOML
- 更新 `manager.current = id``state.save()` → 触发加密保存。
- 保留/清理:
@@ -80,7 +80,7 @@
- 启动:`AppState::new()` → `MultiAppConfig::load()`(优先加密)→ 进程内持有解密后的配置。
- 添加/编辑/删除:更新内存中的 `ProviderManager` → `state.save()`(加密写盘)。
- 切换:回填 live → 以目标供应商内存配置写入主配置 → 更新 `current` → `state.save()`。
- 切换:回填 live → 以目标供应商内存配置写入主配置 → 更新当前指针(`manager.current`→ `state.save()`。
- 迁移后提醒:若首次从旧明文迁移成功,弹出“发现旧配置,可归档”提示;用户可进入“存储与清理”页面查看并执行归档。
## 8. 迁移策略

View File

@@ -164,7 +164,7 @@ pub fn migrate_copies_into_config(config: &mut MultiAppConfig) -> Result<bool, S
let settings_path = crate::config::get_claude_settings_path();
if settings_path.exists() {
match crate::config::read_json_file::<Value>(&settings_path) {
Ok(val) => Some(("current".to_string(), val)),
Ok(val) => Some(("default".to_string(), val)),
Err(e) => {
log::warn!("读取 Claude live 配置失败: {}", e);
None
@@ -269,7 +269,7 @@ pub fn migrate_copies_into_config(config: &mut MultiAppConfig) -> Result<bool, S
} else {
String::new()
};
Some(("current".to_string(), serde_json::json!({"auth": auth, "config": cfg})))
Some(("default".to_string(), serde_json::json!({"auth": auth, "config": cfg})))
}
Err(e) => {
log::warn!("读取 Codex live auth.json 失败: {}", e);
@@ -350,7 +350,7 @@ pub fn migrate_copies_into_config(config: &mut MultiAppConfig) -> Result<bool, S
}
}
// 若 current 为空,将 live 导入项设为 current
// 若当前为空,将 live 导入项设为当前
{
let manager = config.get_manager_mut(&AppType::Claude).unwrap();
if manager.current.is_empty() {

View File

@@ -80,7 +80,7 @@ function App() {
setProviders(loadedProviders);
setCurrentProviderId(currentId);
// 如果供应商列表为空,尝试自动导入现有配置为"current"供应商
// 如果供应商列表为空,尝试自动从 live 导入一条默认供应商
if (Object.keys(loadedProviders).length === 0) {
await handleAutoImportDefault();
}
@@ -154,14 +154,14 @@ function App() {
}
};
// 自动导入现有配置为"current"供应商
// 自动从 live 导入一条默认供应商(仅首次初始化时)
const handleAutoImportDefault = async () => {
try {
const result = await window.api.importCurrentConfigAsDefault(activeApp);
if (result.success) {
await loadProviders();
showNotification("已自动导入现有配置为 current 供应商", "success", 3000);
showNotification("已从现有配置创建默认供应商", "success", 3000);
}
// 如果导入失败(比如没有现有配置),静默处理,不显示错误
} catch (error) {