Skip to content

Conversation

@jsrcode
Copy link
Collaborator

@jsrcode jsrcode commented Dec 13, 2025

概述

本 PR 包含一系列重构工作,主要聚焦于代码架构优化、版本解析统一和代理配置管理增强。

主要变更

1. 配置服务模块化重构 (配置管理系统 v2)

  • 架构拆分:将原 services/config.rs (1137行) 拆分为 6 个子模块
    • types.rs:共享类型定义(60行)
    • utils.rs:工具函数(85行)
    • claude.rscodex.rsgemini.rs:各工具配置管理(~180行/模块)
    • watcher.rs:外部变更检测 + 文件监听(550行)
  • 统一接口ToolConfigManager trait 定义标准的 read/save/get_schema 方法
  • 代码减少:从 1416 行(config.rs + config_watcher.rs)减少到 1329 行,消除重复代码

2. 工具命令层模块化 (三层架构优化)

  • 命令层拆分:原 tool_commands.rs (1001行) 按职责拆分为 6 个模块
    • installation.rsdetection.rsvalidation.rsupdate.rsscanner.rsmanagement.rs
  • 服务层增强ToolRegistry 新增 7 个方法,InstallerService 新增 1 个方法
  • 代码质量:命令层从 1001 行减少到 548 行(-45%),平均函数从 62 行减少到 8 行(-87%)
  • 测试覆盖:新增 11 个单元测试(version.rs: 6个,registry.rs: 5个)

3. 版本解析统一架构

  • 单一数据源:所有版本解析逻辑统一到 utils/version.rs 模块
  • 两个公共方法
    • parse_version_string(raw: &str) -> String:提取版本字符串
    • parse_version(raw: &str) -> Option<semver::Version>:解析为强类型对象
  • 格式支持2.0.61v1.2.32.0.61 (Claude Code)1.2.3-beta.1
  • 测试覆盖:7 个测试函数,覆盖所有格式

4. 透明代理系统增强

4.1 ProfileManager 集成

  • 核心功能:代理启动时自动切换到内置 Profile (dc_proxy_*),关闭时还原原 Profile
  • 保留前缀校验:禁止用户创建 dc_proxy_ 开头的 Profile(系统保留)
  • 列表查询过滤:UI 不显示内置系统 Profile

4.2 SessionManager 重构

  • 架构迁移:删除独立 db.rs (366行) → db_utils.rs (工具函数)
  • 直接使用 DataManager:利用 LRU 查询缓存(容量 100,TTL 5分钟)
  • 测试覆盖扩展:新增 3 个集成测试(缓存性能、配置更新)

5. 前端组件化重构

5.1 Tauri 命令包装器模块化

  • 拆分结构:原 lib/tauri-commands.ts (979行) 拆分为 10 个模块
  • 类型定义独立types.ts 存储所有 Tauri 命令相关类型(317行)

5.2 AddInstanceDialog 组件化

  • 拆分结构:原 AddInstanceDialog.tsx (995行) 拆分为 9 个子组件
  • Hook 解耦:3 个自定义 Hook(useAddInstanceStateuseInstallerScanneruseToolScanner
  • 步骤组件:5 个独立的配置步骤组件

6. 其他优化

  • 余额监控存储:从 localStorage 迁移到 JSON 文件(~/.duckcoding/balance_configs.json
  • 命令执行优化:智能重试机制解决 npm 全局包依赖缺失问题
  • 平台兼容性:修复 macOS GUI 应用中工具检测失败问题
  • 许可证更新:切换到 AGPL v3

测试情况

  • 单元测试:新增 21 个测试(version.rs: 7个, registry.rs: 5个, installer.rs: 3个, session: 3个, balance: 3个)
  • 架构验证:16 个 DataManager 迁移测试通过
  • 前端类型:TypeScript 类型定义完整,无类型错误

破坏性变更

  • Gemini CLI 的 model 字段:从必填改为可选(需要前端 UI 适配,已完成)
  • 用户无法再创建 dc_proxy_ 开头的 Profile(已存在的不受影响)

代码统计

  • 101 个文件变更
  • +8715 / -5154 行 (净增 3561 行)
  • 17 个提交
  • 平均提交粒度:~210 行/提交

风险评估

  • 低风险:主要为代码结构重构,业务逻辑保持不变
  • 测试覆盖充分:新增功能均有单元测试
  • 向后兼容:保留旧 API 兼容层,平滑迁移

检查清单

  • 已运行 npm run check 且全部通过
  • Rust 单元测试已运行(21 个新测试通过)
  • 前端类型定义完整
  • CLAUDE.md 文档已更新
  • 遵循 Conventional Commits 规范
  • 代码质量符合零警告标准

相关 Issue

无(主动重构优化)

审查重点

  1. 配置服务模块化拆分是否合理
  2. 版本解析逻辑是否覆盖所有场景
  3. ProfileManager 与代理系统的集成是否符合预期
  4. SessionManager 的 DataManager 迁移是否正确
  5. 前端组件拆分是否提高了可维护性

备注:此 PR 为多个独立重构任务的集合,每个提交都是独立可回滚的。建议按提交顺序审查。

- **核心功能**:代理启动时自动切换到内置 Profile (dc_proxy_*), 关闭时还原原 Profile
  - 启动流程:保存 original_active_profile → 激活内置 Profile → 启动代理
  - 关闭流程:停止代理 → 还原 original_active_profile
  - 新增字段:ToolProxyConfig::original_active_profile 存储启动前的 Profile 名称

- **ProfileManager 增强**(services/profile_manager/):
  - 保留前缀校验:禁止用户创建 dc_proxy_ 开头的 Profile(系统保留)
  - 列表查询过滤:list_*_profiles() 自动过滤 dc_proxy_ 前缀的内置 Profile
  - Gemini 字段调整:model 改为 Option<String>,允许不填(内置代理 Profile 不设置 model)
  - 类型定义更新:GeminiProfile::model 与前端 ProfilePayload 保持一致

- **SessionManager 重构**(services/session/):
  - 删除独立数据库模块:db.rs (366 行) → db_utils.rs (工具函数)
  - 直接使用 DataManager:manager.rs 持有 Arc<DataManager> + db_path
  - 查询缓存优化:利用 SqliteManager 的 LRU 缓存(容量 100, TTL 5分钟)
  - 工具函数私有化:parse_proxy_session/parse_count/parse_session_config 仅内部使用
  - 测试覆盖扩展:新增 3 个集成测试(缓存性能、配置更新)

- **前端适配**(src/pages/ProfileManagementPage/):
  - ProfileEditor:Gemini model 字段改为可选输入(与后端类型一致)
  - TypeScript 类型:GeminiProfilePayload::model 改为 string | null

- **文档同步**:CLAUDE.md 更新架构记忆(代理配置管理机制 + 会话管理重构)

**技术细节**:
- 保留前缀验证在 save_*_profile() 的最前面,阻止创建系统保留名称
- 列表查询使用 filter() 过滤保留前缀,确保 UI 不显示内置 Profile
- SessionManager 测试使用 TempDir 隔离环境,避免全局单例干扰
- 代理启停逻辑与 ProfileManager 完全解耦(通过 Profile 名称关联)

**BREAKING CHANGE**:
- Gemini CLI 的 model 字段从必填改为可选(需要前端 UI 适配)
- 用户无法再创建 dc_proxy_ 开头的 Profile(已存在的不受影响)
@DuckCoding-dev DuckCoding-dev merged commit 6f6e7c0 into DuckCoding-dev:main Dec 16, 2025
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants