Back to Prompt Optimizer

Desktop模块修复计划

docs/archives/110-desktop-indexeddb-fix/fix-details.md

2.10.27.2 KB
Original Source

Desktop模块修复计划

问题分析

🚨 关键问题(会导致应用无法启动)

  1. 缺少必要依赖

    • dotenv: main.js第8行require('dotenv'),但package.json中未声明
    • @prompt-optimizer/core: main.js第27行require('@prompt-optimizer/core'),但package.json中未声明
  2. 构建配置不一致

    • build-desktop.bat使用electron-version=33.0.0
    • package.json使用electron ^37.1.0
    • 构建工具:build-desktop.bat使用@electron/packager,package.json使用electron-builder
  3. 缺少资源文件

    • package.json中electron-builder配置引用icon.ico,但文件不存在

⚠️ 次要问题(影响功能和兼容性)

  1. 跨平台兼容性问题

    • build:web脚本使用robocopy(仅Windows)
    • 路径使用双反斜杠转义可能在某些环境下有问题
  2. 构建路径问题

    • build-desktop.bat引用../desktop-standalone,但实际结构可能不匹配

修复计划

阶段1:修复关键依赖问题

  • 1.1 更新package.json添加缺少的依赖
    • 添加了dotenv: ^16.0.0
    • 添加了@prompt-optimizer/core: workspace:*
  • 1.2 验证依赖版本兼容性
    • 依赖安装成功,无版本冲突

阶段2:统一构建配置

  • 2.1 选择electron-builder作为主要构建工具
  • 2.2 更新构建脚本
    • 改进build:web脚本使用跨平台Node.js方法替代robocopy
    • 添加build:cross-platform脚本使用Node.js构建脚本
  • 2.3 移除icon配置要求

阶段3:修复API调用错误

  • 3.1 修复ModelManager API调用
    • 将getModels()改为getAllModels()
    • 修复addModel()参数传递问题

阶段4:改进构建脚本

  • 4.1 创建跨平台构建脚本build.js
  • 4.2 使用Node.js fs.cpSync替代robocopy

阶段5:测试验证

  • 5.1 测试开发模式启动 ✅
    • 应用成功启动,无API错误
    • 服务初始化正常
    • 模板加载成功
  • 5.2 测试生产构建
  • 5.3 验证IPC通信正常

执行时间

  • 开始时间:2025-01-01
  • 预计完成:2025-01-01
  • 状态:🔄 进行中

修复详情

已完成的修复

1. 依赖问题修复

json
// packages/desktop/package.json
"dependencies": {
  "node-fetch": "^2.7.0",
  "dotenv": "^16.0.0",           // 新增
  "@prompt-optimizer/core": "workspace:*"  // 新增
}

2. API调用修复

javascript
// packages/desktop/main.js
// 修复前:
const result = await modelManager.getModels();

// 修复后:
const result = await modelManager.getAllModels();

// 修复addModel参数传递:
const { key, ...config } = model;
await modelManager.addModel(key, config);

3. 构建脚本改进

  • 创建了跨平台构建脚本 build.js
  • 改进了 build:web 脚本使用Node.js方法替代Windows专用的robocopy
  • 移除了electron-builder配置中的icon要求

4. 测试结果

  • ✅ 依赖安装成功
  • ✅ 开发模式启动成功
  • ✅ 服务初始化正常
  • ✅ 模板加载成功(7个模板)
  • ✅ 环境变量正确加载

🚨 重要发现:架构问题

问题:为什么desktop模式下仍能看到IndexedDB?

根本原因:useAppInitializer.ts中的架构设计错误

typescript
// 错误的实现(修复前)
if (isRunningInElectron()) {
  storageProvider = StorageFactory.create('memory'); // ❌ 渲染进程不应该有存储
  dataManager = createDataManager(..., storageProvider); // ❌ 使用了渲染进程存储
  const languageService = createTemplateLanguageService(storageProvider); // ❌ 重复创建服务
}

问题分析

  1. 渲染进程创建了独立的memory storage,与主进程隔离
  2. 某些组件可能绕过代理服务,直接使用web版本的IndexedDB
  3. 数据来源混乱:主进程memory storage vs 渲染进程storage vs IndexedDB

修复:正确的Electron架构

typescript
// 正确的实现(修复后)
if (isRunningInElectron()) {
  storageProvider = null; // ✅ 渲染进程不使用本地存储
  // 只创建代理服务,所有操作通过IPC
  modelManager = new ElectronModelManagerProxy();
  // ...其他代理服务
}

正确架构

  • 主进程:唯一的数据源,使用memory storage
  • 渲染进程:只有代理类,所有操作通过IPC
  • 无本地存储:渲染进程不应该有任何存储实例

🔧 关键修复:模块级存储创建问题

发现的根本问题

packages/core/src/services/prompt/factory.ts中发现模块级别的存储创建:

typescript
// 问题代码(已修复)
const storageProvider = StorageFactory.createDefault(); // ❌ 模块加载时就创建IndexedDB

影响:无论在什么环境下,只要导入这个模块就会创建IndexedDB存储!

修复内容

  1. 移除模块级存储创建:修改factory.ts,不再在模块加载时创建存储
  2. 重构工厂函数:改为接收依赖注入的方式
  3. 移除重复函数定义:清理service.ts中的重复工厂函数
typescript
// 修复后的代码
export function createPromptService(
  modelManager: IModelManager,
  llmService: ILLMService,
  templateManager: ITemplateManager,
  historyManager: IHistoryManager
): PromptService {
  return new PromptService(modelManager, llmService, templateManager, historyManager);
}

🎯 最终修复:彻底删除createDefault()

根本解决方案

按照用户建议,彻底删除了StorageFactory.createDefault()方法

typescript
// 删除的问题方法
static createDefault(): IStorageProvider {
  // 这个方法会自动创建IndexedDB,无论在什么环境下
}

修复内容

  1. 删除createDefault()方法:从StorageFactory中完全移除
  2. 修复TemplateLanguageService:构造函数改为必须传入storage参数
  3. 更新测试文件:移除所有对createDefault()的测试
  4. 清理相关代码:移除defaultInstance相关的代码

架构改进

  • 强制明确性:所有地方都必须明确指定存储类型
  • 避免意外创建:防止在不合适的环境下自动创建IndexedDB
  • 提高代码质量:让依赖关系更加明确和可控

✅ 修复验证

  • 修复Electron架构问题
  • 修复模块级存储创建问题
  • 彻底删除createDefault()方法
  • 修复TemplateLanguageService依赖注入
  • 更新测试文件
  • 测试修复后的应用启动 ✅
  • 验证主进程使用memory storage ✅
  • 验证无IndexedDB创建 ✅
  • 最终用户验证IndexedDB状态 ✅

🧹 代码清理

  • 移除DexieStorageProvider中的过度防御代码
  • 简化useAppInitializer中的调试信息
  • 删除不必要的listTemplatesByTypeAsync方法
  • 删除无用的getCurrentDefault()方法

📋 最终状态

任务状态:✅ 完成 问题根源:历史遗留的IndexedDB数据 + 模块级存储创建 解决方案:删除createDefault()方法 + 手动清理IndexedDB 验证结果:Desktop应用正常运行,无IndexedDB创建

🎯 核心收获

  1. 架构原则:强制明确性比便利性更重要
  2. 问题定位:历史遗留数据可能掩盖真正的修复效果
  3. 过度工程:修复过程中要避免不必要的复杂化
  4. 代码清理:及时清理无用代码,保持代码库整洁