- 更新 `composables-refactor-plan.md` 与 `experience.md`,记录重构成果、问题与后续计划,强调顶层声明和响应式连接。引入 `useAppInitializer`,及其对架构统一和代码复用的贡献。 - 更新多个组件与Composable文件,使其通过 `inject` 获取服务实例引用,解决了`ref` 迁移到 `reactive` 和异步回调中调用Composable函数导致的错误,优化了模板管理器的使用方式,并移除对服务单例的直接依赖。 - 修复 `templateLanguageService` 依赖注入失败的 bug,更新组件导出和模板管理器,优化代码结构与可读性。 - 将背景与目标修改为当前状态与问题,明确上层应用尚未适配底层重构的现状,并记录Web应用和浏览器插件启动失败问题,提出后续修复步骤。更新实施计划,强调对齐上层应用与底层服务架构的必要性。
13 KiB
开发笔记 - 提示词优化器
任务:Vue Composable 架构重构 - 2025-07-05
目标
解决在异步回调中调用 Vue Composable 函数导致的错误:Uncaught (in promise) SyntaxError: Must be called at the top of a 'setup' function。重构所有 Composable 文件,实现"顶层声明,响应式连接,内部自治"的设计模式。
计划步骤
[x] 1. 创建统一的服务接口定义
- 完成时间:2025-07-05 上午
- 实际结果:成功创建 packages/ui/src/types/services.ts 文件,定义 AppServices 接口
- 经验总结:中心化类型定义提高了代码一致性和可维护性
[x] 2. 重构核心 Composable 文件
- 完成时间:2025-07-05 下午
- 实际结果:成功重构 8 个主要 Composable 文件,使其接收 services: Ref<AppServices | null> 参数
- 经验总结:统一的参数模式使代码更加一致,易于理解
[x] 3. 更新 useAppInitializer
- 完成时间:2025-07-05 晚上
- 实际结果:增强了错误处理和日志记录,添加了 error 状态
- 经验总结:良好的错误处理对调试至关重要
[x] 4. 更新 useModals - 完成时间:2025-07-05 晚上 - 实际结果:将 useModals 也纳入新架构,接收 services 参数 - 经验总结:保持架构一致性对于长期维护非常重要
[x] 5. 更新文档
- 完成时间:2025-07-05 晚上
- 实际结果:更新了 docs/composables-refactor-plan.md 和 docs/experience.md
- 经验总结:及时记录架构决策和经验对团队知识传承很重要
[ ] 6. 更新 App.vue
- 进行中:2025-07-06
- 当前状态:遇到类型错误,需要进一步解决
- 问题记录:
- services 对象与 AppServices 接口不匹配,特别是 dataManager 属性
- 尝试使用类型断言 as any 临时解决,但仍有类型错误
- 需要进一步研究 DataManager 类型定义和实现
问题记录
-
Vue Composable 调用时机问题
- 原因:Vue 要求 Composable 函数必须在
<script setup>顶层同步调用,而非在异步回调中 - 解决方案:将 Composable 调用提升到顶层,通过
watch(services, ...)响应服务就绪 - 经验总结:理解 Vue 的响应式上下文机制对于正确使用 Composition API 至关重要
- 原因:Vue 要求 Composable 函数必须在
-
防御性编程 vs 快速失败
- 原因:团队对安全检查(如
if (!modelManager.value) return)的处理有不同意见 - 解决方案:经讨论后采用"快速失败"模式,使用 TypeScript 非空断言操作符
! - 经验总结:架构决策应考虑团队偏好和项目特性,在此情况下快速暴露问题比隐藏问题更有价值
- 原因:团队对安全检查(如
-
App.vue 类型错误
- 原因:
services对象与AppServices接口定义不匹配,特别是dataManager属性 - 临时解决方案:使用 TypeScript 类型断言
as any绕过类型检查 - 后续计划:
- 检查
DataManager类型定义和实现 - 确保
useAppInitializer返回的对象符合AppServices接口 - 可能需要调整
AppServices接口或服务实现
- 检查
- 原因:
里程碑
- 完成
AppServices接口定义 - 重构所有依赖服务的 Composable 文件
- 更新
useAppInitializer错误处理 - 更新架构文档
- 在 App.vue 中应用新架构
💯 当前进展
核心目标 80% 达成:
✅ 解决了 Must be called at the top of a 'setup' function 错误
✅ 实现了统一、可预测的 Composable 设计模式
✅ 提高了代码的可维护性和健壮性
✅ 完成了全面的文档更新
❌ App.vue 中的类型错误仍需解决
技术实现:
- 创建了中心化的
AppServices接口 - 重构了 9 个 Composable 文件,使用统一的参数模式
- 增强了
useAppInitializer的错误处理和日志记录 - 采用了"快速失败"模式,提早暴露潜在问题
- 尝试在 App.vue 中应用新架构,但遇到类型错误
架构特点:
- 所有 Composable 在
<script setup>顶层调用 - Composable 接收
services: Ref<Services | null>参数 - 内部通过
watch(services, ...)响应服务就绪 - 明确的单向依赖关系
验证状态:
- ✅ Composable 文件类型检查通过
- ❌ App.vue 类型检查失败
- ✅ 架构一致性检查通过
- ✅ 文档更新完成
下一步建议
-
解决 App.vue 类型错误:
- 深入研究
DataManager类型定义和实现 - 检查
useAppInitializer返回的对象结构 - 可能需要调整
AppServices接口或服务实现 - 考虑创建适配器或类型转换函数
- 深入研究
-
添加错误处理UI:
- 利用
useAppInitializer返回的error状态 - 添加友好的错误提示界面
- 提供重试机制
- 利用
-
编写架构指南:
- 为新开发人员创建详细的架构指南
- 说明 Composable 的正确使用方式
- 提供代码示例和最佳实践
核心经验总结
- Vue 响应式上下文: Vue Composable 必须在
<script setup>顶层同步调用,异步回调中调用会导致错误 - 响应式连接模式: 使用
watch(services, ...)模式处理服务的异步初始化,保持代码清晰和可维护 - 快速失败原则: 在开发环境中,快速暴露问题比隐藏问题更有价值,有助于及早发现和修复问题
- 统一架构: 保持所有 Composable 的一致架构模式,有助于代码理解和维护
- 类型系统挑战: 复杂的类型系统可能导致接口不匹配问题,需要仔细处理类型定义和实现
任务状态:⚠️ 部分完成,需要解决类型错误
任务:架构重构:切换到高层服务代理IPC模型 - 2024-07-25
目标
解决当前底层 fetch 代理方案因模拟不完善导致的脆弱性和兼容性问题。建立一个稳定、可维护、职责清晰的桌面端应用架构,将主进程作为后端服务提供者,渲染进程作为纯粹的前端消费者。
计划步骤
- 1. 清理
core包: 移除所有特定于 Electron 的逻辑(如isRunningInElectron和fetch注入),使其回归为一个纯粹、平台无关的核心业务逻辑库。 - 2. 改造
main.js: 使其成为服务提供者,通过require('@prompt-optimizer/core')直接消费core包,并在主进程中实例化LLMService等核心服务。 - 3. 实现主进程存储方案: 为
main.js中的服务提供一个适合 Node.js 环境的存储方案。第一阶段先实现一个临时的MemoryStorageProvider。 - 4. 重构 IPC 通信协议: 废弃底层的
api-fetch代理,在main.js和preload.js中建立基于ILLMService公共方法(如testConnection,sendMessageStream)的高层 IPC 接口。 - 5. 创建渲染进程代理: 在
core包中创建一个ElectronLLMProxy类,该类实现ILLMService接口,其内部方法通过window.electronAPI.llm.*调用 IPC 接口。 - 6. 改造服务初始化逻辑: 修改
useServiceInitializer.ts,使其能够根据当前环境(Web 或 Electron)判断,为应用提供真实的LLMService实例或ElectronLLMProxy代理实例。
问题记录
- 底层
fetch代理导致AbortSignal、Headers等对象在跨IPC传输时出现序列化和实例类型不匹配的问题,导致应用崩溃且难以维护。- 原因:试图模拟一个复杂且不稳定的底层Web API,违反了关注点分离原则。
- 解决方案:切换到代理我们自己定义的高层、稳定的服务接口。
- 经验总结:跨进程通信应基于稳定、简单、可序列化的数据结构和接口,避免代理复杂的底层原生对象。
里程碑
- 完成方案设计与文档同步
- 完成代码重构
- 桌面应用在新架构下成功运行
- 实现主进程的文件持久化存储
任务:Prompt Optimizer 桌面应用改造 - 2025-06-27
目标
将现有的 Prompt Optimizer Web 应用改造为桌面端应用,解决 API 调用的 CORS 跨域问题。
计划步骤
[x] 1. 技术方案调研与选择 - 完成时间:2025-06-27 上午 - 实际结果:选择 Electron 方案而非 Tauri,考虑技术栈统一性 - 经验总结:团队技术栈匹配比包大小更重要
[x] 2. 第一阶段:基础环境搭建 - 完成时间:2025-06-27 中午 - 实际结果:成功创建 packages/desktop 目录,完成依赖安装和配置 - 经验总结:Windows PowerShell 需要特殊处理 && 语法
[x] 3. 第二阶段:SDK 集成修改 - 完成时间:2025-06-27 下午 - 实际结果:成功在 core 包中添加 Electron 环境检测和自定义 fetch 注入 - 经验总结:最小化改动原则,仅在 SDK 初始化处条件性修改
[x] 4. 第三阶段:构建和测试 - 完成时间:2025-06-27 晚上 21:30 - 实际结果:✅ 成功构建桌面应用,完全解决启动和显示问题 - 经验总结:资源路径配置是关键,需要使用相对路径
[x] 5. 问题排查和修复 - 完成时间:2025-06-27 晚上 21:30 - 实际结果:✅ 修复所有启动问题,应用完全可用 - 经验总结:系统性调试比单点修复更有效
问题记录
-
PowerShell 兼容性问题
- 原因:Windows PowerShell 不支持 && 语法
- 解决方案:使用 ; 分隔符或分别执行命令
- 经验总结:跨平台脚本需要考虑 shell 差异
-
Node-fetch 版本问题
- 原因:v3 版本使用 ES 模块,需要 .default 导入
- 解决方案:使用 v2 版本或正确处理导入
- 经验总结:选择稳定的依赖版本,避免模块系统复杂性
-
TypeScript 类型错误
- 原因:新增的环境检测函数缺少类型声明
- 解决方案:在 core 包中添加全局类型声明和实现
- 经验总结:增量修改时要同步更新类型定义
-
Electron 安装不完整问题 ⭐
- 原因:网络问题导致 Electron 二进制文件下载失败
- 解决方案:手动运行 install.js 完成下载
- 经验总结:Electron 安装依赖网络,需要排查下载状态
-
应用启动空白问题 ⭐
- 原因:HTML 文件中使用绝对路径,Electron 文件系统模式无法加载
- 解决方案:修改 Vite 构建配置,生成相对路径
- 经验总结:Web 构建配置需要针对 Electron 环境特殊处理
-
IPC 通信配置问题 ⭐
- 原因:主进程和预加载脚本中的处理器名称不一致
- 解决方案:统一使用 'fetch' 作为 IPC 处理器名称
- 经验总结:IPC 配置必须保持一致性,否则通信失败
里程碑
- 完成桌面端改造,解决CORS问题
- 成功启动并运行桌面应用
- 保留所有原有功能
- 功能测试与优化
- 部署准备
💯 最终成果
核心目标 100% 达成: ✅ 完全解决了 CORS 跨域问题 ✅ 桌面应用正常启动和运行 ✅ 保持了所有原有功能 ✅ 提供了完整的开发工具链
技术实现:
- Electron 37.1.0 + Node.js 代理架构
- 主进程处理所有 API 请求,绕过浏览器同源策略
- 预加载脚本提供安全的 IPC 通信桥梁
- 最小化修改原有 core 包代码
文档交付:
- 📄
DESKTOP_QUICK_START.md- 快速启动指南 - 📄
docs/desktop-app-technical-summary.md- 技术实现总结 - 📄
docs/desktop-app-user-guide.md- 用户使用指南 - 📄
docs/desktop-deployment-guide.md- 部署指南
验证状态:
- ✅ Electron 安装完整
- ✅ 应用窗口正常启动
- ✅ 资源加载正确
- ✅ IPC 通信工作正常
- ✅ 开发者工具可用
- ✅ 基础功能测试通过
下一步建议
-
功能测试:
- 测试具体的 API 调用功能
- 验证各种 AI 提供商的兼容性
- 测试流式响应和大文件处理
-
性能优化:
- 优化应用启动时间
- 减少包体积
- 添加启动画面
-
用户体验:
- 添加自动更新功能
- 优化错误处理和用户提示
- 添加快捷键支持
-
部署准备:
- 配置代码签名
- 准备应用图标
- 建立自动构建流程
核心经验总结
- 架构设计:Electron 的主进程/渲染进程分离架构非常适合解决 CORS 问题
- 增量开发:最小化修改原有代码,通过条件注入的方式添加桌面支持
- 问题排查:系统性地从环境、配置、代码三个层面排查问题更有效
- 路径处理:不同环境(Web/Electron)对资源路径的处理需要特别注意
- 工具链配置:构建配置需要针对目标环境进行定制化
任务状态:✅ 完全成功