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:
@@ -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` 完成登录。
|
||||
|
||||
### 迁移与备份
|
||||
|
||||
@@ -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. 迁移策略
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user