news 2026/9/20 3:16:34

Cherry Studio v1→v2 重构作战指南:数据层与 UI 技术栈拆除、Migrator 收尾与发布清理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Cherry Studio v1→v2 重构作战指南:数据层与 UI 技术栈拆除、Migrator 收尾与发布清理
  • 人工智能
  • 大模型
  • AI 应用
  • 交互助手
  • 本地部署

【免费下载链接】cherry-studio

🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端

项目地址:https://gitcode.com/CherryHQ/cherry-studio
点击查看免费下载

本文基于 Cherry Studio 开源仓库中的全局重构追踪文档 v2-todo.md 展开,系统梳理 v1→v2 重构中所有**跨切面(Cross-Cutting)**任务:Redux / Dexie / ElectronStore 三套 v1 数据栈的退役、antd / styled-components 向@cherrystudio/ui的收敛、14 个数据迁移器(Migrator)的收尾、Schema 迁移 SQL 的再生成、约 78 处@deprecated站点的清理,以及发布前的整目录清理流程。读完本文,你将掌握这次大型重构的整体推进顺序、各任务的状态判定方法,以及每项工作背后对应的源码实现位置,可作为二次开发与升级维护时的索引地图。

一、重构全景:一份"只跟踪全局任务"的作战文档

在 Cherry Studio 仓库中,v2 重构的文档组织遵循一个明确原则:全局性、跨模块的任务集中在 v2-todo.md 一处追踪,模块内部的细粒度 TODO 则保留在各模块自己的文档中,不在此重复。因此这份文档的定位是"顶层作战地图",而不是逐文件清单。

文档开篇给出了两个使用前提,理解它们对正确阅读本指南至关重要:

  • 计数是近似值:文中所有文件数、slice 数、匹配数均来自代码扫描,会随开发推进漂移,执行前需要重新验证;
  • 状态图例:✅ done(已完成)/🔲 todo(待办)/🟡 in progress(进行中)。

文档的 Overview 总表是整份重构的目录级快照:

CategoryScaleStatus
Remove Redux~100 files / 28 slices✅ done(store/deleted)
Remove Dexie~50 files🟡 mostly migrated, fallback paths pending
Remove ElectronStore~10 files🔲 awaiting migration-window close
Remove antd~145 files🟡 settings/knowledge pages already clean
Remove styled-components~112 files🟡 in progress
Migrator finalization4 explicit todos🟡 14 migrators mostly complete
Schema / migration SQL regenrelease gate🔲 before release

从这张表可以读出整次重构的骨架:数据层三栈拆除 + UI 层两库迁移 + 迁移器与 Schema 收尾 + 发布清理。下文按这四个维度逐一展开。

二、数据层拆除:Redux / Dexie / ElectronStore 三栈退役

v2 数据层的目标非常明确:移除全部三套 v1 数据栈(Redux / Dexie / ElectronStore),替换为 v2 的Cache / Preference / DataApi三层体系。围绕这三套栈的迁移进度与遗留策略,构成了数据层拆除的全部内容。

2.1 Redux(~100 文件 / 28 slices)— ✅ 已完成

Redux 是三个数据栈中第一个被完整移除的,文档记录了其拆除的完整路径:

  • 全部 28 个 slice 迁移至 Cache / Preference / DataApi;
  • 所有useAppSelector/useDispatch调用点重新指向 v2 的读取与写入 API;
  • 各窗口入口的<Provider>包裹被移除;
  • src/renderer/store/目录整体删除;
  • 主进程侧被 stub 的ReduxService桥接层一并删除。

从文档第 5 节还能看到配套动作:29 个store/*文件被列为移除待办的@deprecated站点,替代方向正是 "DataApi + Preference + SQLite"。也就是说 Redux 的拆除不是简单的删代码,而是先完成读写路径的重定向,再物理删除

2.2 Dexie(~50 文件)— 🟡 大部分已迁移,回退路径待清理

Dexie 的迁移处于"大部分完成、收尾待办"的状态:

  • 渲染进程侧的 Dexie schema 与升级入口(src/renderer/databases/)已移除;
  • 迁移专用访问仍保留:DexieExporterDexieFileReaderDexieSettingsReader三类读取器仅供 v1→v2 迁移流程使用,必须等到迁移窗口(migration window)关闭后才能删除(见文档 §6)。

这一策略在源码中有直接印证:迁移工具目录 中保留着DexieFileReader.tsDexieSettingsReader.tsReduxStateReader.tsLocalStorageReader.tsLegacyAgentsDbReader.tsLegacyHomeConfigReader.tsJsonStreamReader.ts等一系列只读型遗留数据访问器——它们是迁移器读取 v1 数据的"井盖",迁移结束即废弃。

从源码结构看,v1 数据读取被统一收敛在src/main/data/migration/v2/utils/下,迁移器通过它们读旧数据、通过 MigrationDbService.ts 写新库,实现了"旧数据只读、新数据只写"的隔离,降低迁移过程中破坏源数据的风险。

2.3 ElectronStore(~10 文件)— 🔲 等待迁移窗口关闭

ElectronStore 是最后退役的数据栈,文档给出了明确的删除顺序:

  • 入口最后删:文档将src/main/services/ConfigManager.ts(标注@deprecated Scheduled for removal in v2.0.0,内部有new Store())列为最后一个待删除入口;
  • Boot config 已先行:启动配置已由BootConfigMigrator迁移至 v2;
  • PreferencesMigrator 仍依赖:偏好迁移器需要通过遗留读取器读取 electron-store 的旧键,属于纯迁移期代码。

需要说明的是,这份文档是重构推进过程中的时间快照——截至本文撰写时,仓库中已无法直接检索到ConfigManager.ts文件,主进程的配置读取已全面切换至 v2 preference 体系;当前 MigrationEngine.ts 与 MigrationContext.ts 中仅保留对electron-store迁移期只读访问(例如读取config.json以探测遗留数据目录),这正符合文档"迁移专用、迁移后删除"的设计。

三、UI 层拆除:antd / styled-components 向@cherrystudio/ui收敛

UI 层的目标是把两套被禁用的组件库 antd 与 styled-components 完全迁移到统一的 @cherrystudio/ui(基于 Tailwind + Shadcn 的自研组件体系)。

3.1 当前进展

  • HeroUI 已完全移除(0 处 import);
  • @cherrystudio/ui已在约 400 个文件中被采用;
  • settings / knowledge / library / code / notes / mini-apps 页面已基本清理干净。

从源码可以直观验证这一规模:src/renderer/下大量组件、页面(如src/renderer/pages/settings/src/renderer/pages/knowledge/src/renderer/components/chat/src/renderer/windows/migrationV2/等)都已通过from '@cherrystudio/ui'引入组件,与文档描述的"约 400 文件采用"相互印证。

3.2 迁移策略:重叠优先 + 分区批量

文档给出了两条关键战术:

  1. 重叠文件优先:antd 与 styled-components 有约 21 个文件同时 import 两者,优先处理这些文件可以"一次清两笔账";
  2. 按区域分批迁移,每个区域标注了 antd 文件数、styled 文件数与优先级:
AreaantdstyledPriorityNotes
home(主聊天 UI)~80~58high核心 UX:Messages / Inputbar / Blocks
shared Popups~4~4highAddAssistantPopup / AgentModal / SelectModelPopup;高流量共享组件,迁移后级联解锁下游
agents~22~6medium可与 home 批量进行
paintings(各 provider 配置页)~13~11medium全部为 antd+styled 重叠,是很好的合并目标
windows~10~16mediumquickAssistant / selection / migrationV2 / trace
history / files / launchpad~5~8low轻量
单文件钉子户3lowSkillsSettings、ModelSelectorLegacy、ProviderLogoPicker

这份优先级表的思路值得借鉴:先啃高流量共享组件(Popups),因为它们的迁移会级联解锁依赖它们的下游页面;而占文件数最多的 home 主聊天区虽然工作量大,但因为处于核心 UX 路径,被列为最高优先级。

3.3 特殊用例:MarkdownShadowDomRenderer

文档特别点名了src/renderer/components/MarkdownShadowDomRenderer.tsx:它曾使用 styled-components 向 Shadow DOM 注入 CSS,需要专门处理而不能走常规迁移路径。从当前源码看,该组件的实现已经演进为原生 Web API 方案——通过attachShadow({ mode: 'open' })创建影子根、从document.styleSheets中抓取包含.markdown规则的样式表、将 CSS 规则文本注入 shadow 内的<style>节点,再用createPortal把子节点渲染进影子树。这也再次印证了本文的基调:文档是重构快照,源码在持续前进,阅读时两者需对照。

四、Migrator 收尾:14 个迁移器的最后 1%

数据迁移是 v1→v2 的心脏。文档记录迁移器总数约为 14 个(同样为扫描近似值),大部分已完成,仅剩 4 项显式 TODO。

4.1 四个显式 TODO

ItemLocationTODO
ChatMigrator i18nChatMigrator.ts:761// TODO: i18n;fallback 话题名为硬编码英文Unnamed Topic,需要 i18n key
KnowledgeVectorMigrator failure handlingKnowledgeVectorMigrator.tsBase 级执行失败被当作整体迁移失败(README 标记 IMPORTANT);需确认设计或实现 skippable-base 模式
TranslateMigrator missing testmigrators/__tests__/唯一没有配套测试的迁移器;需补充TranslateMigrator.test.ts
V1_REQUIRED_VERSION lock-inversionPolicy.ts:34TODO:待最终 v1 版本确定后更新(当时为1.9.0,预期 ~1.9.x)

对照当前源码,这 4 项的进展状态如下(再次强调:仓库代码已领先于文档快照):

  • ChatMigrator i18n:从 ChatMigrator.test.ts 的测试用例可以看到,迁移器已改为保留空的 topic nameexpect(result?.topic.name).toBe('')),让 UI 在渲染时调用t('chat.conversation.new')进行本地化,从而不再把英文Unnamed Topic写死进数据——这与 v2 原生创建的无名话题行为保持一致,中文用户不会再看到冻结的英文文案。也就是说,该 TODO 的"用 i18n 解决硬编码"方向已通过"空名 + 渲染时本地化"落地;
  • KnowledgeVectorMigrator failure handling:当前实现中已经存在每 base 非致命(per-base non-fatal)的处理路径——单个 base 失败时跳过该 base、将其计入skippedCount以通过引擎的targetCount < sourceCount - skippedCount对账,并把失败降级为 warning,不再拖垮整个迁移(见 KnowledgeVectorMigrator.ts 附近注释)。"一个锁死或损坏的 base 不再拖垮整体迁移"的设计已落地;
  • TranslateMigrator missing test:截至撰写时,migrators 测试目录 中确实没有TranslateMigrator.test.ts(仅mappings/__tests__/TranslateTransforms.test.ts覆盖了转换逻辑),该 TODO 仍待办;
  • V1_REQUIRED_VERSION:当前 versionPolicy.ts 中常量已更新为'1.9.12',且顶部 TODO 注释("Update this value once the final v1 version is determined")仍然保留——说明该条目处于"已锁值、待终版确认"状态。

4.2 版本升级策略(源码级补充)

与 V1_REQUIRED_VERSION 相关的版本策略在 versionPolicy.ts 中有完整实现,它强制一条线性升级路径

v1.old → v1.last(V1_REQUIRED_VERSION)→ v2.0.x(网关线)→ v2.1+

核心逻辑checkUpgradePathCompatibility会拦截三类非法路径:

  1. version.log且无历史版本 → 拦截(no_version_log);
  2. 历史版本低于V1_REQUIRED_VERSION→ 拦截(v1_too_old);
  3. 从 v1.x 或 v2.0.0-beta 直接跳到V2_DIRECT_MIGRATION_CEILING2.1.0)以上 → 拦截(v2_gateway_skipped),因为每个 v2.0.x 补丁都保留完整的一次性迁移,可能包含某些 v1 profile 所需的修复。

值得注意的细节是pre-release 的差异性处理currentVersion会通过semver.coerce()剥离 pre-release 标签(2.0.0-alpha视为2.0.0,防止误拦安装了预发布版的 v1 用户);而previousVersion不做 coerce(2.0.0-beta仍被视为"未通过网关")。这套语义保证了 alpha→beta→rc→2.0.0 的预发布链可以顺利升级,而 v1 用户则必须经由 2.0.x 网关完成一次性迁移。

4.3 有意跳过的内容(发布说明必须声明)

文档强调,以下有意为之的跳过必须在 release notes 中向用户明示:

  • Knowledgevideo/memory类条目不迁移;目录子项不重建;遗留 sitemap 条目以 URL 条目形式迁移;分组元数据丢失(groupId = null);
  • KnowledgeVector:v1 遗留向量库原地保留不迁移;迁移成功后这些库以"孤儿"形式残留在磁盘上(当前无清理触发,未来可由用户确认后清理以回收磁盘);
  • NoteactiveFilePath/activeNodeId不迁移,运行时重新建立;
  • MCP:provider 缓存不迁移,运行时重新拉取。

这些"主动放弃"的条目,配合上面的逐项 TODO,构成了迁移器收尾的完整画像:不是所有数据都值得迁移,明确放弃的数据需要作为产品级决策被记录和声明

4.4 迁移引擎的底层编排(源码补充)

迁移的执行骨架在 MigrationEngine.ts 中:引擎负责协调所有 migrator、管理进度、处理失败。其中MIGRATION_TARGET_TABLES常量是迁移会写入的所有表的单一事实来源(约 40 张表,覆盖 chat、agent、knowledge、file、preference 等全域),并显式标注了clearMigrationData() 清库时的子→父顺序约束

  • message必须先于topic清除(外键引用);
  • topic必须先于assistant清除;
  • user_model必须先于user_provider清除;
  • junction 表(assistant_mcp_serverassistant_knowledge_baseprompt_binding)必须先于其父表清除;
  • agents 域按agent_session_message_file_ref → agent_session_message → agent_channel_task → … → agent的依赖链逆序清理。

这套顺序约束保证了重试与跳过(retry / skip)时不会因外键约束而中断——引擎具备完整的"失败重试、部分跳过"能力,这也是 4.2 节 KnowledgeVector per-base 跳过机制能够成立的前提。

五、Schema 与迁移 SQL 收尾:重构出单条干净的初始迁移

文档第 4 节记录了 Schema 层面的发布门槛:

  • migrations/sqlite-drizzle/ 目录当前保存的是增量开发链(文档撰写时为00000012+meta/快照;截至本文撰写时该链已延伸至0020),"单条干净迁移"的再生成尚未发生
  • 发布前必须从最终 schema 重新生成一条干净的初始迁移,以清掉中间开发状态(这一要求在 CLAUDE.md 中已被强制规定);
  • 工具行为陷阱:drizzle-kit generate在分叉链(forked chain)上仍然以退出码 0 正常退出,只有pnpm db:migrations:check才能标记出分叉;因此开发中期的 schema 漂移是可接受的,但严禁手写 patch migration

这条规范的实际含义是:开发阶段允许 schema 频繁变动(毕竟迁移器还在收尾),但最终交付必须是一条自洽的、从零到一的干净迁移,避免把开发期的中间状态泄漏给用户升级路径。

六、@deprecated标记清理:约 78 处 / 58 文件

发布前还需清理代码中残留的@deprecated标记:约 78 处、分布在 58 个文件中,其中约 39 处明确写着Scheduled for removal in v2.0.0。文档按子系统分组给出了替代方向:

GroupScopeReplacement direction
Redux store slices29 files(store/*DataApi + Preference + SQLite
Dexie / message 数据源4 files(databases/DexieMessageDataSourceDbServiceDataApi(主聊天)/ AgentMessageDataSource(agent 会话)
Redux 耦合 hooks / 主进程桥6 files(useStore/useSettings/useTagsLegacyReduxService等)usePreference/useTags(v2);ReduxService已 stub
共享数据类型agent / message / provider 类型(分页响应、citation 格式、遗留 provider 标志)OffsetPaginationResponseMainTextBlock.references
协议 / 消息格式LanFile*JSON 格式、web-search 访问器二进制帧、CitationMessageBlock
组件 / 服务重构CodeEditor@cherrystudio/uiFileManager(不再扩展)、deleteMessageFilessafeDeleteFiles见各标注

在源码中可以看到这些标记的实际分布,例如 legacyTypes.ts(整文件标注@deprecated v1 legacy — do not extend)、FileStorage.ts(@deprecated LEGACY v1 CODE — being migrated to FileManager)、LegacyBackupManager.ts(@deprecated LEGACY v1 CODE — removed when the v2 migration is dropped)等。

文档还给出了迁移相关 TODO/FIXME 的分布统计(约 53 条,从约 157 条中过滤而来,其余为普通代码注释),主工作流按规模排序:

  1. Preference / Provider 设置迁移(最大头,约 18 条,含ProviderSettings/utils/v1ProviderShim.ts的 "delete after Phase 5");
  2. 服务架构 / 生命周期重构(约 10 条);
  3. Redux → SQLite/Drizzle(约 9 条,集中在apiServer/routes/knowledge/handlers.ts);
  4. Phase-2 文件服务 stub(约 8 条);
  5. 消息类型迁移(~5)、IPC handler 清理(~6)、DataApi 集成(~3)。

这组数字告诉读者:设置域是迁移后期最密集的战场,v1ProviderShim 这类过渡 shim 被明确标注了过期时间点(Phase 5 之后删除),是典型的"过渡代码要有明确生命周期"实践。

七、发布与清理:从迁移窗口关闭到整目录删除

文档第 6 节给出了发布期的三步收尾:

  1. 删除迁移专用代码DexieFileReaderDexieSettingsReader、electron-store 读取路径等仅被 v1→v2 迁移流程使用;一旦迁移窗口关闭(即最低支持的 v1 版本停止升级),立即删除;
  2. 聚合 breaking changes:发布负责人聚合 breaking-changes 目录中的记录,将其翻译成中文用户可见的发布说明。该目录的 README 定义了严格的记录规范:用户可感知的变更(功能移除、默认行为改变、设置位置移动、数据迁移字段丢失、快捷键/URL scheme 变更、平台要求变化)必须记录;纯内部重构(IPC 通道改名、服务拆分、schema 微调、类型改名)不得记录;拿不准时宁多勿少,发布期可随时丢弃;
  3. 删除整个v2-refactor-temp/目录:确认工具不再需要、把值得保留的文档移到正式位置、删除目录并清理.gitignore中的引用。这一步的依据是 v2-refactor-temp/README.md 中明示的 Cleanup plan——该目录不含任何生产代码,只承载重构期工具与工作笔记,重构落地即整体移除。

八、进一步阅读:重构相关的源码导航

如果希望深入本次重构的实现细节,以下仓库路径是最佳起点:

  • 迁移核心骨架:MigrationEngine.ts(编排与重试)、MigrationContext.ts(迁移上下文,含 electron-store 只读访问)、MigrationPaths.ts(遗留数据目录探测)、versionPolicy.ts(版本网关);
  • 迁移器与文档:migrators 目录 下的*Migrator.ts与配套README-*Migrator.md,注册总表见 migratorRegistry.ts;
  • 迁移测试:migrators/tests与 core/tests,覆盖引擎跳过、版本策略、错误处理与各迁移器行为;
  • 遗留数据读取器:migration/v2/utils(Dexie / Redux / LocalStorage / legacy DB 等只读访问器);
  • 迁移窗口 UI 与 IPC:window/MigrationWindowManager.ts、window/MigrationIpcHandler.ts,渲染端入口在 migrationV2 窗口;
  • 数据迁移相关文档总入口:migration/README.md 与 v2-refactor-temp/README.md。

最后提醒一点阅读姿势v2-todo.md是重构进行中的状态快照,其统计数字(文件数、TODO 数、迁移链编号)会随开发演进,部分条目(如 ChatMigrator 的 i18n、KnowledgeVector 的 per-base 失败处理)在本文撰写时已被源码层面的新实现覆盖。将文档与当前仓库代码对照阅读,才能得到最准确的实时状态。

  • 人工智能
  • 大模型
  • AI 应用
  • 交互助手
  • 本地部署

【免费下载链接】cherry-studio

🍒 Cherry Studio 是一款支持多个 LLM 提供商的桌面客户端

项目地址:https://gitcode.com/CherryHQ/cherry-studio
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 3:15:49

Telegram频道媒体下载器:绕过限制批量下载与API限速实战

1. 从“保存失败”说起&#xff1a;频道媒体下载的真实痛点如果你长期混迹于各类兴趣社群、资源分享频道&#xff0c;大概率遇到过这种场景&#xff1a;在某个频道里翻到一段特别有价值的视频、一份设计素材或者一套完整的课程录音&#xff0c;手指习惯性地点向“保存到相册”或…

作者头像 李华
网站建设 2026/9/20 3:15:12

nvm安装Node.js报错not yet released:6种原因与排查方法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 3:14:21

开放研究实操指南:从数据到代码全流程可复现的工作流

有一个词&#xff0c;我关注了很久&#xff1a;OpenResearch。单独拆开看&#xff0c;open是开放&#xff0c;research是研究&#xff0c;连在一起像是某个机构的名字&#xff0c;但在我这些年做独立项目、整理数据、写代码、发文档的日常里&#xff0c;这个词已经变成了一套很…

作者头像 李华
网站建设 2026/9/20 3:12:55

RGB转YUV详解:从色度子采样到有限范围,视频编码的色彩基础

1. 为什么RGB是彩色图像的标准答案&#xff0c;而视频却要装进YUV这个壳子做数字图像处理的同学&#xff0c;大概率第一天学的就是RGB三通道模型。红、绿、蓝三种基色按不同比例叠加&#xff0c;就能得到自然界里绝大多数颜色。这个模型足够直观&#xff0c;也跟显示器、相机的…

作者头像 李华
网站建设 2026/9/20 3:12:09

半导体专利视觉化:如何用3D动画突破二维图纸局限

去年我在处理一个高密度功率器件的专利申请案时&#xff0c;第一次真正体会到&#xff1a;传统的二维图纸已经撑不住半导体结构的表达需求了。那个器件一共九层金属&#xff0c;中间还有两段立体沟槽电容&#xff0c;无论我怎么画剖面图、立体示意图&#xff0c;代理人和审查员…

作者头像 李华