首页
/ CC Switch v3.8.0 持久化架构升级解析:从单一 config.json 到 SQLite + JSON 双层存储

CC Switch v3.8.0 持久化架构升级解析:从单一 config.json 到 SQLite + JSON 双层存储

2026-09-06 22:15:08作者:瞿蔚英Wynne

CC Switch v3.8.0(2025-11-28 发布)是一次以「数据持久化层重构」为主线的重大架构升级版本:它把全部可同步数据从单一 config.json 迁移到 SQLite,将设备级状态留在 JSON,为后续云同步与本地代理功能打下地基。本文基于仓库内 v3.8.0 中文发布说明 展开,并结合 数据库模块迁移引擎备份实现 等源码,完整梳理这一版本的双层架构设计、自动迁移机制、关键 Bug 的根因与修复,以及日语支持、递归扫描 Skills、开机自启等全部功能细节,帮助开发者在升级部署时准确理解数据去向与潜在风险点。


版本概览

项目 内容
发布日期 2025-11-28
提交数量 自 v3.7.1 起 51 个提交
代码变更 207 个文件,+17,297 / -6,870 行(净增 +10,427 行)
核心主题 持久化架构升级,为云同步奠定基础

按提交类型分布:fix 25 个、refactor 11 个、feat 9 个、test 1 个、其他 5 个;改动区域上前端源码 112 个文件、Rust 后端 63 个文件、测试文件 20 个文件、国际化文件 3 个文件。这是一个典型的「先修稳定性、再动存储层」的重构版本。


持久化架构升级:SQLite + JSON 双层设计

架构变更全景

v3.7.x 时代,CC Switch 的全部数据(供应商、MCP、提示词、设置等)都存放在一个 config.json 文件中。v3.8.0 将其拆分为两层:

v3.7.x (旧)                      v3.8.0 (新)
┌─────────────────┐              ┌─────────────────────────────────┐
│  config.json    │              │  SQLite (可同步数据)             │
│  ┌───────────┐  │              │  ├─ providers     供应商配置     │
│  │ providers │  │              │  ├─ mcp_servers   MCP 服务器     │
│  │ mcp       │  │     ──>      │  ├─ prompts       提示词         │
│  │ prompts   │  │              │  ├─ skills        技能           │
│  │ settings  │  │              │  └─ settings      通用设置       │
│  └───────────┘  │              ├─────────────────────────────────┤
└─────────────────┘              │  JSON (设备级数据)               │
                                 │  └─ settings.json 本地设置       │
                                 │     ├─ 窗口位置                  │
                                 │     ├─ 路径覆盖                  │
                                 │     └─ 当前选中供应商 ID          │
                                 └─────────────────────────────────┘

双层结构的划分逻辑是:

层级 存储方式 数据类型 同步策略
云同步层 SQLite 供应商、MCP、Prompts、Skills 未来可同步
设备层 JSON 窗口状态、本地路径、当前选择 保持本地

判断标准很清晰:跨设备应当一致的数据进 SQLite,与具体机器/窗口绑定的数据留在 JSON——窗口位置、本机路径覆盖这类信息同步到另一台设备没有意义,反而会造成困惑。

源码印证:database/ 模块结构

发布说明描述的模块化结构在仓库中可以直接对应到 src-tauri/src/database 目录:

database/
├── mod.rs              核心 Database 结构体和初始化
├── schema.rs           表结构定义、Schema 版本迁移
├── backup.rs           SQL 导入导出、二进制快照备份
├── migration.rs        JSON → SQLite 数据迁移引擎
└── dao/                数据访问对象层
    ├── providers.rs    供应商 CRUD
    ├── mcp.rs          MCP 服务器 CRUD
    ├── prompts.rs      提示词 CRUD
    ├── skills.rs       Skills CRUD
    └── settings.rs     键值对设置存储

(仓库当前版本的 dao 目录 还随后续版本扩展了 profiles.rsfailover.rsproxy.rs 等 DAO,印证了这一模块化设计确实可持续扩展。)

几个关键实现细节:

  • 数据库文件位置:从 mod.rsDatabase::init() 可以看到,SQLite 文件落在 ~/.cc-switch/cc-switch.db(通过 get_app_config_dir() 拼接),而非各客户端(Claude/Codex 等)的目录中。
  • 连接封装rusqlite::Connection 本身不是 Sync 的,源码用 Mutex<Connection> 包装(见 Database { conn: Mutex<Connection> }),以支持在 Tauri State 多线程环境下共享;配套的 lock_conn! 宏统一处理加锁错误,避免 unwrap panic。
  • PRAGMA 配置:初始化时显式开启 PRAGMA foreign_keys = ON(这是本次「自定义端点丢失」Bug 的根源,后文详述);新建数据库还会设置 PRAGMA auto_vacuum = INCREMENTAL,配合启动时的 incremental_vacuum 回收磁盘空间。
  • Schema 版本管理:模块顶部定义了 SCHEMA_VERSION 常量,当前仓库中已是 17——说明自 v3.8.0 引入该机制以来,表结构经历了十余次受控演进,每次变更都走 schema.rs 中的版本迁移逻辑,这正是发布说明中「支持数据库结构升级迁移」的落地形式。

表结构:providers 表与外键级联

database/schema.rs 中的建表语句揭示了 v3.8.0 之后架构的重要组成。以供应商为核心的两张表:

CREATE TABLE IF NOT EXISTS providers (
    id TEXT NOT NULL,
    app_type TEXT NOT NULL,          -- 区分 Claude/Codex 等不同客户端
    name TEXT NOT NULL,
    settings_config TEXT NOT NULL,   -- 供应商完整配置(JSON)
    website_url TEXT,
    category TEXT,
    created_at INTEGER,
    sort_index INTEGER,
    notes TEXT,
    icon TEXT,                       -- 供应商图标(本版本新增)
    icon_color TEXT,
    meta TEXT NOT NULL DEFAULT '{}',
    is_current BOOLEAN NOT NULL DEFAULT 0,
    in_failover_queue BOOLEAN NOT NULL DEFAULT 0,
    PRIMARY KEY (id, app_type)
);

CREATE TABLE IF NOT EXISTS provider_endpoints (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    provider_id TEXT NOT NULL,
    app_type TEXT NOT NULL,
    url TEXT NOT NULL,
    added_at INTEGER,
    FOREIGN KEY (provider_id, app_type)
        REFERENCES providers(id, app_type) ON DELETE CASCADE
);

要点:

  1. 复合主键 (id, app_type):同一供应商配置可以分属不同客户端(Claude Code、Codex、OpenCode、Grok Build、Hermes),主键组合保证命名隔离;
  2. provider_endpoints 表外键级联删除ON DELETE CASCADE 意味着删除供应商行会自动清掉其自定义端点——这正是下文「INSERT OR REPLACE 丢端点」Bug 的引爆点;
  3. 此外还有 mcp_servers(按客户端记录 enabled 开关)、promptsskillssettings(键值对)等表,与发布说明中「云同步层」的数据类型一一对应。

技术实现四件套

发布说明总结的四个技术特性,都能在源码中验证:

特性 源码依据
Schema 版本管理 mod.rsSCHEMA_VERSION 常量与 apply_schema_migrations()
SQL 导入导出 backup.rsdump_sql / SQL 导入,支持二进制快照备份
事务支持 migration.rs 中迁移全程包裹在 rusqlite::Transaction 中,失败即整体回滚
自动迁移 首次启动检测旧 config.json,调用 migrate_from_json() 完成 JSON → SQLite 转换

值得一提的是 backup.rs 在后续版本中被显著加固:SQL 导出文件带 -- CC Switch SQLite 导出 头注释校验;导入外部 SQL 时挂了一个 authorizer 钩子,拒绝 ATTACH DATABASEVACUUM INTO、文件型虚拟表以及白名单(foreign_keysuser_version)之外的 PRAGMA——因为这些导入路径会被 WebDAV/S3 云同步复用,输入不可信。这体现了「SQL dump 便于云端存储」这一设计目标下对安全边界的持续打磨。

从 v3.7.x 升级:自动迁移与数据安全

自动迁移在首次启动时执行,migration.rs 中的 migrate_from_json() 实现如下流程:

  1. 检测旧 config.json 是否存在;
  2. 在单个事务中依次迁移五类数据:Providers → MCP Servers → Prompts → Skills → Common Config(见 migrate_from_json_tx 的 5 步调用);
  3. 设备级设置(窗口位置、路径覆盖、当前选中供应商)分流写入 settings.json
  4. 全部成功后显示迁移通知。

数据安全策略有三条,全部可从源码确认:

  • 原文件保留:迁移成功后 config.json 不被删除,用户可随时回退;
  • 失败可诊断:迁移失败弹出错误对话框并保留 config.json,因事务未提交,SQLite 中不会留下半成品数据;
  • Dry-run 验证migrate_from_json_dry_run()内存数据库上执行完整迁移流程但不落盘,供部署前回归验证迁移逻辑正确性——这是一个很少见但很值得称道的工程习惯。

全新用户界面

v3.8.0 同步完成了 UI 的整体重构,发布说明将其归为三类改进:

视觉改进

  • 重新设计的界面布局;
  • 统一的组件样式;
  • 更流畅的过渡动画;
  • 优化的视觉层次。

交互优化

  • Header toolbar 重新设计;
  • ConfirmDialog 样式统一(对应仓库中的 ConfirmDialog 组件);
  • 禁用主视图 overscroll 弹跳效果,减少桌面端「假滚动」观感;
  • 改进的表单验证反馈。

兼容性调整

  • Tailwind CSS 从 v4 降级到 v3.4,以提升浏览器/WebView 兼容性——从仓库根目录的 tailwind.config.cjspackage.json 可以确认项目确实运行在 Tailwind v3.4 体系下。这是一次「牺牲版本号换兼容性」的务实决策,对 Tauri 这类依赖系统 WebView 的桌面应用尤其重要。

日语支持:国际化扩展到三种语言

本版本新增日语(日本語)界面,国际化语言从两种扩展到三种:简体中文、English、日本語。从仓库可确认三个语言文件并列存在且体量相当:en.jsonja.json(3250 行)、zh.jsonzh-TW.json,配合 i18n 入口 加载。这也与「国际化文件:3 个文件变更」的技术统计吻合。


新增功能

Skills 递归扫描

Skills 管理系统支持递归扫描仓库目录,自动发现嵌套的技能文件:

  • 支持多层目录结构;
  • 自动发现所有 SKILL.md 文件;
  • 允许不同仓库的同名技能(使用完整路径去重)。

实现位于 src-tauri/src/services/skill.rs,其中技能元数据(显示名称、描述等)均从 SKILL.md 解析,扫描时按完整目录路径作为技能唯一标识,从而解决「两个仓库都有 git-commit 技能」这类同名冲突问题。

供应商图标配置

供应商预设支持自定义图标配置,与上文的 providersicon / icon_color 两个新字段直接对应:

  • 预设供应商包含默认图标;
  • 复制供应商时保留图标设置(本版本修复了复制时图标字段丢失的 Bug);
  • 图标颜色可自定义。

前端侧由 ProviderIcon 组件providerIcon 工具 负责渲染。

表单验证增强

供应商表单新增必填字段验证:

  • 必填字段实时校验;
  • 统一使用 Toast 通知显示验证错误;
  • 更清晰的错误信息。

开机自启

新增跨三平台(Windows / macOS / Linux)的开机自动启动,在设置中一键开关。源码 auto_launch.rs 展示了具体实现:

  • 基于 auto_launch crate 的 AutoLaunchBuilder 统一抽象平台差异;
  • Windows:注册表启动项;
  • macOS:注意源码中专门处理了 .app bundle 路径(/path/CC Switch.app/Contents/MacOS/CC Switch/path/CC Switch.app)——因为 AppleScript login item 直接指向可执行文件会弹出终端窗口,指向 bundle 才不会;
  • Linux:XDG autostart(.desktop 文件)。

新增供应商预设

  • MiniMax —— 官方合作伙伴,官方 Coding Plan 预设。

Bug 修复:根因级讲解

关键修复:自定义端点丢失

这是本版本最重要的一次修复,根因极具教学价值:

  • 现象:更新供应商时自定义请求地址(custom endpoints)意外丢失;
  • 根因:旧实现用 INSERT OR REPLACE 更新供应商。SQLite 中当 REPLACE 触发主键冲突时,底层实际执行 DELETE 旧行 + INSERT 新行;而 provider_endpoints 表对 providers 声明了 ON DELETE CASCADE,于是旧行被删的瞬间,其全部自定义端点随行被级联删除;
  • 修复:对已存在的供应商改用显式 UPDATE 语句。

这一修复在当前 dao/providers.rs 中可以验证——更新路径全部是 UPDATE providers SET ... WHERE id = ? AND app_type = ? 形式(如第 203、419、485 行附近),is_current 切换、settings_config 覆盖均走 UPDATE,不再有 DELETE 语义介入。这个案例也说明:SQLite 的 REPLACE 是「冲突即删插」而非「就地更新」,配合外键级联时会产生隐式数据丢失。

Gemini 配置问题

  • 修复自定义供应商环境变量未正确写入 .env 文件;
  • 修复安全认证配置错误写入到其他配置文件(Gemini 的 security.auth.selectedType 应写入 ~/.gemini/settings.json,相关逻辑见 gemini_config.rsgemini_auth.rs)。

供应商验证问题

  • 修复当前供应商 ID 不存在时的验证错误(迁移后 current 指针悬空会导致校验误报);
  • 修复供应商复制时图标字段丢失。

平台兼容性(Linux)

  • 解决 WebKitGTK 的 DMA-BUF 渲染问题(Linux 下 Tauri 基于 WebKitGTK,DMA-BUF 故障会表现为白屏/黑屏);
  • 保留用户已有的 .desktop 文件自定义(覆盖前不抹掉用户手工修改)。

其他修复

  • 切换应用时的冗余用量查询;
  • DMXAPI 预设使用错误的认证令牌字段;
  • 深链接组件缺少翻译键;
  • 用量脚本模板初始化逻辑。

技术改进:服务层与深链接的模块化

供应商服务模块化

发布说明给出的目标结构在仓库 services/provider 目录中得到印证:

services/provider/
├── mod.rs          核心服务 - add/update/delete/switch/validate
├── live.rs         Live 配置文件操作
├── gemini_auth.rs  Gemini 认证类型检测
├── endpoints.rs    自定义端点管理
└── usage.rs        用量脚本执行

其中 endpoints.rs 专职管理 provider_endpoints 表,与上文端点丢失修复直接相关:端点的增删被从供应商主体 CRUD 中拆出,边界清晰。(仓库当前版本还额外有 pi.rs,属后续版本扩展。)

深链接模块化

深链接(ccswitch:// 协议导入)拆分为独立模块 src-tauri/src/deeplink,与文档描述一致:

deeplink/
├── mod.rs       模块导出
├── parser.rs    URL 解析
├── provider.rs  供应商导入逻辑
├── mcp.rs       MCP 导入逻辑
├── prompt.rs    提示词导入
├── skill.rs     Skills 导入
└── utils.rs     工具函数

前端对应的确认交互组件位于 components/deeplink(MCP/Prompt/Skill 三类确认对话框)。

代码质量清理

  • 移除 JSON 时代遗留的导入导出死代码;
  • 移除未使用的 MCP 类型导出;
  • 统一错误处理方式(全部经由 error.rsAppError);
  • 测试侧:迁移测试整体切到 SQLite 架构(后端测试见 src-tauri/tests,如 provider_service.rsimport_export_sync.rs),前端组件测试与 MSW handlers 同步更新以适配新 API。

技术统计

总体变更:
- 提交数:51
- 文件数:207 个文件变更
- 新增:+17,297 行
- 删除:-6,870 行
- 净增:+10,427 行

提交类型分布:
- fix:25 个(Bug 修复)
- refactor:11 个(代码重构)
- feat:9 个(新功能)
- test:1 个(测试)
- 其他:5 个

改动区域分布:
- 前端源码:112 个文件
- Rust 后端:63 个文件
- 测试文件:20 个文件
- 国际化文件:3 个文件

删除量接近 7000 行,与「移除 JSON 时代死代码 + UI 重构」吻合,说明这并非简单堆功能,而是一次有意识的架构换血。


下载与安装

系统要求

  • Windows:Windows 10+
  • macOS:macOS 10.15(Catalina)+
  • Linux:Ubuntu 22.04+ / Debian 11+ / Fedora 34+

获取方式

  • 从项目 Releases 页下载对应安装包:Windows 为 .msi-Portable.zip,macOS 为 .tar.gz.zip,Linux 为 .AppImage.deb
  • macOS 用户也可以使用 Homebrew:
brew tap farion1231/ccswitch
brew install --cask cc-switch

更新:

brew upgrade --cask cc-switch

升级注意:从 v3.7.x 升级到 v3.8.0 无需任何手工操作,首次启动即触发上文所述的自动迁移;升级前无需导出备份,但建议知悉 config.json 会被保留、~/.cc-switch/cc-switch.db 将成为新的主数据文件。更多变更脉络可参考 CHANGELOG.md,项目中文文档见 README_ZH.md


未来展望

v3.8.0 明确为两个方向铺路(v3.9.0 预览,暂定):

  • 本地代理功能:SQLite 化的供应商配置(含端点、元数据)为本地代理的路由与故障切换提供了结构化的数据基础——仓库中 in_failover_queueprovider_health 等字段及 proxy 模块 已是后续版本的现实落点。

从源码结构看,「可同步数据进 SQLite、设备级数据留 JSON」的分层一旦稳定,后续任何同步方案(WebDAV/S3 等)只需围绕 cc-switch.db 的 SQL dump 做增量与冲突处理,而不会把窗口状态等噪音带进同步链路——这正是本版本架构决策的核心价值。

登录后查看全文
热门项目推荐
相关项目推荐