• v2.0.0 298b5aa931

    gavin released this 2025-10-16 12:45:12 +08:00 | 3 commits to main since this release

    重构时间: 2025-10-16

    Phase 1: 核心服务拆分 (Day 1-2) 已完成

    • Step 1: 创建服务目录结构 /web/src/services/chat/
    • Step 2: 提取 MessageService - 消息 CRUD 操作(20+ 方法)
    • Step 3: 提取 ConversationService - 对话管理(10+ 方法)
    • Step 4: 创建统一日志系统 Logger (支持日志级别、命名空间、格式化)
    • Step 5: 创建错误处理体系 AppError (ValidationError, NetworkError, APIError, ServiceError, StorageError + ErrorHandler)
    • Step 6: 提取 StreamProcessor - 流式响应处理(性能监控、批量输出、工具集成)
    • Step 7: 提取 ToolExecutor - 工具调用执行(递归调用链、错误处理)
    • Step 8: 创建 ChatOrchestrator - 协调所有服务(话题管理、消息管理、流式发送、持久化 + togglePin/Favorite/Archive)
    • Step 9: 更新 chatStore 使用新服务(已完成:chatService → chatOrchestrator)
    • ⏸️ Step 10: 测试验证,确保无功能回归

    Phase 1 重构完成!旧的 chatService.ts (1147行) 已完全被新架构替代。

    服务架构总结:

    ChatOrchestrator (协调器)
    ├── MessageService (消息 CRUD)
    ├── ConversationService (对话管理)
    ├── StreamProcessor (流式处理)
    └── ToolExecutor (工具执行)
    
    工具层:
    ├── Logger (统一日志)
    └── AppError + ErrorHandler (错误处理)
    
    ┌─────────────────────────────────────────────────────────┐
    │                    用户界面层 (UI)                        │
    │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐ │
    │  │ 聊天视图 │  │ 设置视图 │  │ 模型管理 │  │ MCP管理  │ │
    │  └──────────┘  └──────────┘  └──────────┘  └──────────┘ │
    └─────────────────────────────────────────────────────────┘
                            ↓ ↑
    ┌─────────────────────────────────────────────────────────┐
    │                 状态管理层 (Pinia Stores)                 │
    │  ┌──────────┐  ┌──────────┐  ┌──────────┐               │
    │  │chatStore │  │modelStore│  │ mcpStore │               │
    │  └──────────┘  └──────────┘  └──────────┘               │
    └─────────────────────────────────────────────────────────┘
                            ↓ ↑
    ┌─────────────────────────────────────────────────────────┐
    │                  业务服务层 (Services)                    │
    │  ┌─────────────────────────────────────────────────────┐│
    │  │           ChatOrchestrator (协调器)                  ││
    │  │  ┌────────────┐ ���────────────┐ ┌────────────┐      ││
    │  │  │  Message   │ │Conversation│ │   Stream   │      ││
    │  │  │  Service   │ │  Service   │ │ Processor  │      ││
    │  │  └────────────┘ └────────────┘ └────────────┘      ││
    │  │  ┌────────────┐                                     ││
    │  │  │   Tool     │                                     ││
    │  │  │ Executor   │                                     ││
    │  │  └────────────┘                                     ││
    │  └─────────────────────────────────────────────────────┘│
    │  ┌──────────────┐  ┌──────────────┐                    │
    │  │ModelService  │  │MCPClientSvc  │                    │
    │  │  Manager     │  │              │                    │
    │  └──────────────┘  └──────────────┘                    │
    └─────────────────────────────────────────────────────────┘
                            ↓ ↑
    ┌─────────────────────────────────────────────────────────┐
    │                   工具层 (Utils)                          │
    │  ┌──────────┐  ┌──────────┐  ┌──────────┐              │
    │  │  Logger  │  │  Error   │  │Validation│              │
    │  │          │  │ Handler  │  │          │              │
    │  └──────────┘  └──────────┘  └──────────┘              │
    └─────────────────────────────────────────────────────────┘
                            ↓ ↑
    ┌─────────────────────────────────────────────────────────┐
    │                 数据持久化层 (Storage)                    │
    │  ┌──────────┐  ┌──────────┐                             │
    │  │localStorage│  │IndexedDB │  (未来)                   │
    │  └──────────┘  └──────────┘                             │
    └─────────────────────────────────────────────────────────┘
                            ↓ ↑
    ┌─────────────────────────────────────────────────────────┐
    │                  后端服务 (Node.js)                       │
    │  ┌──────────┐  ┌──────────┐                             │
    │  │LLMService│  │MCPManager│                             │
    │  └──────────┘  └──────────┘                             │
    └─────────────────────────────────────────────────────────┘
                            ↓ ↑
    ┌────────────────────────────────────────────────���────────┐
    │              外部服务 (External APIs)                     │
    │  ┌──────────┐  ┌──────────┐  ┌──────────┐              │
    │  │阿里通义  │  │ 火山方舟 │  │MCP Servers│              │
    │  └──────────┘  └──────────┘  └──────────┘              │
    └─────────────────────────────────────────────────────────┘
    

    发送消息流程

    用户输入消息
        ↓
    ChatLayout 组件触发事件
        ↓
    chatStore.sendMessage()
        ↓
    ChatOrchestrator.sendMessageStream()
        ↓
    1. MessageService 创建用户消息
    2. 更新话题信息
    3. 持久化到 localStorage
        ↓
    4. MessageService 创建助手消息占位符
        ↓
    5. StreamProcessor.processStream()
       ├─ 准备工具列表(如有 MCP)
       ├─ 准备上下文消息(限制 20 条)
       ├─ 选择服务和模型
       └─ 执行流式请求
        ↓
    6. 流式响应 onChunk 回调
       └─ MessageService.appendMessageContent()
       └─ 触发 UI 更新
        ↓
    7. 检查是否有工具调用
       └─ 是: ToolExecutor.executeToolCalls()
            ├─ 执行每个工具
            ├─ 收集工具结果
            └─ 发送结果给 AI(递归)
       └─ 否: 完成
        ↓
    8. 更新消息状态为 'success'
    9. 更新话题最后消息
    10. 持久化
        ↓
    UI 展示最终消息
    

    核心服务

    1. ChatOrchestrator(聊天协调器)

    职责

    • 统一对外接口
    • 协调各服务完成业务流程
    • 管理话题和对话
    • 处理持久化

    核心方法

    class ChatOrchestrator {
      // 话题管理
      createTopic(name: string, options?: CreateTopicOptions): Topic
      getTopics(filter?: TopicFilter): Topic[]
      updateTopic(topicId: string, updates: Partial<Topic>): boolean
      deleteTopic(topicId: string): boolean
      
      // 消息管理
      getMessages(topicId: string): Message[]
      deleteMessage(topicId: string, messageId: string): boolean
      
      // 发送消息
      sendMessageStream(
        options: SendMessageOptions,
        onChunk: (event: StreamEvent) => void,
        mcpServerId?: string,
        signal?: AbortSignal
      ): Promise<void>
      
      // 重新生成
      regenerateMessage(topicId: string, messageId: string): Promise<Message>
      
      // 持久化
      private saveTopics(): void
      private loadTopics(): void
      private saveConversations(): void
      private loadConversations(): void
    }
    

    2. MessageService(消息服务)

    职责

    • 消息 CRUD
    • 消息状态管理
    • 消息查询和过滤

    核心方法

    class MessageService {
      createMessage(conversationId: string, options: CreateMessageOptions): Message
      getMessages(conversationId: string): Message[]
      getMessagesByTopicId(topicId: string): Message[]
      updateMessage(conversationId: string, messageId: string, options: UpdateMessageOptions): boolean
      updateMessageStatus(conversationId: string, messageId: string, status: MessageStatus): boolean
      appendMessageContent(conversationId: string, messageId: string, content: string): boolean
      deleteMessage(conversationId: string, messageId: string): boolean
      deleteMessagesAfter(conversationId: string, messageId: string): boolean
      getSuccessMessages(conversationId: string): Message[]
      getRecentSuccessMessages(conversationId: string, limit: number): Message[]
    }
    

    3. ConversationService(对话服务)

    职责

    • 对话创建、读取、删除
    • 对话元数据管理
    • 对话与话题的关联

    核心方法

    class ConversationService {
      createConversation(options: CreateConversationOptions): Conversation
      getConversation(conversationId: string): Conversation | undefined
      getConversationByTopicId(topicId: string): Conversation | undefined
      deleteConversation(conversationId: string): boolean
      deleteConversationByTopicId(topicId: string): boolean
      updateMetadata(conversationId: string, metadata: Partial<Conversation['metadata']>): boolean
      clearMessages(conversationId: string): boolean
    }
    

    4. StreamProcessor(流式处理器)

    职责

    • 处理流式响应
    • 性能监控
    • 批量输出
    • 工具集成

    核心方法

    class StreamProcessor {
      async processStream(options: StreamOptions): Promise<StreamResult>
      
      private prepareTools(mcpServerId?: string): Promise<{ tools: any[], mcpServerName: string }>
      private prepareMessages(conversation: Conversation, tools: any[], mcpServerName: string): any[]
      private selectServiceAndModel(requestedModel?: string): { service: any, selectedModel: string }
      private executeStream(...): Promise<StreamResult>
    }
    

    特性

    • 上下文限制:最近 20 条消息
    • 批量输出:每 3 个字符一次(增强流式效果)
    • 性能监控:首字延迟、总耗时、chunk 数
    • 工具集成:自动注入系统提示词

    5. ToolExecutor(工具执行器)

    职责

    • 解析工具调用请求
    • 执行 MCP 工具
    • 处理工具结果
    • 支持递归工具链

    核心方法

    class ToolExecutor {
      async executeToolCalls(options: ToolCallOptions): Promise<void>
      
      private executeTools(toolCalls: any[], mcpServerId: string, onChunk: Function): Promise<ToolCallResult[]>
      private executeSingleTool(toolCall: any, mcpServerId: string, onChunk: Function): Promise<ToolCallResult>
      private sendToolResultsToAI(...): Promise<void>
      private buildMessagesWithToolResults(...): any[]
    }
    
    Downloads
  • v1.0.3 e5f69b3aef

    v1.0.3 Stable

    gavin released this 2025-10-15 17:32:46 +08:00 | 8 commits to main since this release

    发布时间: 2025-10-15

    重大功能:停止生成 & UI 优化

    本版本实现了完整的停止生成功能,参考 Cherry Studio 的 PAUSED 状态设计,提供更好的用户体验。

    核心功能

    智能停止生成

    • 点击停止按钮立即中断 AI 回复(响应时间 < 100ms)
    • 保留已生成的内容,标记为"已停止"状态
    • 区分用户主动停止和系统错误
    • 停止后可立即继续对话

    UI 体验优化

    • 按钮文字从"确认"改为"发送"
    • 停止后显示黄色"已停止"标签(而非红色"发送失败")
    • 停止的消息可以复制、重新生成、删除
    • 实时状态反馈(发送中 → 已停止 → 可操作)

    状态管理增强

    • 新增 paused 消息状态
    • 新增 paused 流式事件类型
    • 完整的 AbortController 信号传递链
    • 流读取循环实时检查中止信号

    技术实现

    按钮事件修复

    • 修复点击事件绑定问题(从三元表达式改为函数调用)
    • 运行时动态判断状态,而非编译时
    // Before: @click="store.state.isSending ? handleStopGeneration : handleSendMessage"
    // After:  @click="handleButtonClick"
    const handleButtonClick = () => {
      if (store.state.isSending) {
        handleStopGeneration()
      } else {
        handleSendMessage()
      }
    }
    

    中止信号传递链

    UI (点击停止)
      ↓ handleStopGeneration()
      ↓ store.stopGeneration()
      ↓ abortController.abort()
      ↓ chatService.sendMessageStream(signal)
      ↓ modelServiceManager.makeChatRequestStream(signal)
      ↓ while循环检查 signal.aborted
      ↓ reader.cancel() + 抛出 AbortError
      ↓ 状态设置为 'paused'
      ↓ UI 更新显示"已停止"
    

    流读取中止检查

    while (true) {
      // 关键:每次读取前检查中止信号
      if (signal?.aborted) {
        console.log('检测到中止信号,停止读取流')
        reader.cancel()
        throw new DOMException('用户中止操作', 'AbortError')
      }
      
      const { done, value } = await reader.read()
      if (done) break
      
      // 处理数据...
    }
    

    错误处理优化

    catch (error) {
      const isAborted = error instanceof Error && error.name === 'AbortError'
      
      if (isAborted) {
        // 用户主动停止 - 标记为 paused,保留内容
        assistantMessage.status = 'paused'
        assistantMessage.error = undefined
        onChunk({ type: 'paused', messageId: assistantMessage.id })
        
        // 关键:更新消息列表,触发 UI 刷新
        state.messages = [...chatService.getMessages(currentTopicId)]
      } else {
        // 真实错误 - 标记为 error
        assistantMessage.status = 'error'
        assistantMessage.error = error.message
      }
    }
    

    Bug 修复

    Emoji 测试

    为验证发布脚本对 emoji 的处理(例如某些 emoji 属于 4 字节 unicode,可能触发服务器端 collation 问题),在此插入若干 emoji 供测试:

    • 表情类:
    • 物品/动作:
    • 动物/自然:
    • 标志/符号:️

    示例行(包含中文和 emoji):

    测试:本行包含中文与 emoji,目的是验证脚本对 emoji 的过滤与回退逻辑。示例 emoji: ️

    • 修复按钮点击无响应问题(事件绑定错误)
    • 修复停止后仍显示"发送中..."状态
    • 修复停止后消息列表不更新
    • 修复 AbortError 被错误标记为失败
    • 修复按钮文字显示"确认"而非"发送"

    修改的文件

    类型定义

    • /web/src/types/chat.ts
      • MessageStatus 添加 'paused' 类型
      • StreamEvent 添加 'paused' 事件类型

    UI 组件

    • /web/src/components/Chat/ChatLayout.vue
      • 修复按钮点击事件绑定
      • 按钮文字改为"发送"
      • 添加"已停止"状态标签显示
      • paused 状态消息显示操作按钮

    服务层

    • /web/src/services/chatService.ts

      • 区分 AbortError 和其他错误
      • 设置 paused 状态和事件
    • /web/src/services/modelServiceManager.ts

      • 流读取循环中检查 signal.aborted
      • 调用 reader.cancel() 中止读取
      • 正确处理 AbortError

    状态管理

    • /web/src/stores/chatStore.ts
      • 在 catch 块中更新消息列表
      • 确保 UI 显示最新状态

    使用示例

    1. 用户发送:"请详细介绍 Vue 3 的新特性"
    2. AI 开始回复,显示"发送中..."
    3. 用户点击"停止"按钮
    4. 立即响应:
       - 输出停止
       - 标签变为"已停止"(黄色)
       - 显示已生成的内容
       - 显示操作按钮
    5. 用户可以:
       - 复制已生成的内容
       - 重新生成完整回复
       - 删除该消息
       - 继续发送新消息
    

    设计亮点

    1. 参考 Cherry Studio - 借鉴成熟产品的设计理念
    2. 立即响应 - 停止操作 < 100ms 响应
    3. 内容保留 - 部分生成的内容依然有价值
    4. 状态区分 - paused vs error,语义更清晰
    5. 完整操作 - 停止的消息仍可进行各种操作
    6. 信号传递 - 完整的中止信号链,确保可靠性

    用户体验对比

    修复前

    • 点击停止无反应
    • 继续显示"发送中..."
    • 显示 loading 动画
    • 按钮文字为"确认"

    修复后

    • 点击立即停止
    • 显示"已停止"(黄色)
    • 隐藏 loading 动画
    • 按钮文字为"发送"
    • 可以操作停止的消息
    • 立即可继续对话

    相关文档

    • STOP_GENERATION_SUMMARY.md - 修复总结
    • STOP_GENERATION_FIX.md - 详细技术文档
    • STOP_GENERATION_PATCH.md - 补充修复说明
    • STOP_GENERATION_TEST.md - 测试指南
    • STOP_GENERATION_VERIFY.md - 快速验证清单

    升级指南

    # 拉取最新代码
    git pull origin main
    
    # 安装依赖
    cd web && npm install
    
    # 启动开发服务器
    npm run dev
    
    # 测试停止功能
    # 1. 发送消息
    # 2. 在 AI 回复时点击"停止"
    # 3. 验证显示"已停止"标签
    # 4. 验证可以继续对话
    

    验收标准

    • 按钮点击有明显反应
    • 流输出在 100ms 内停止
    • 显示"已停止"而非"失败"
    • 保留已生成内容
    • 停止后可立即继续对话
    • 可对停止的消息进行操作
    • 无意外错误日志

    下一步计划

    • 停止后自动保存草稿
    • 停止历史记录统计
    • 批量停止多个会话
    • 停止原因记录(用户主动/超时/错误)
    • 性能监控和优化

    v1.0.3 - 完美的停止体验,让对话更可控!

    Downloads
  • v1.0.2 e581c70489

    v1.0.2 Stable

    gavin released this | 7 commits to main since this release

    发布时间: 2025-10-14

    重大功能:MCP 工具调用集成

    本版本实现了完整的 MCP 工具调用功能,AI 可以智能调用 MCP 服务器提供的工具并整合结果。

    核心功能

    ** 智能工具调用**

    • AI 自动识别何时需要调用工具
    • 支持 OpenAI Function Calling 协议
    • 兼容多个 AI 服务商(OpenAI、火山引擎、阿里云等)
    • 完整的多轮对话支持(AI → Tool → AI)

    ** 流式工具执行**

    • 实时显示工具调用进度
    • 流式体验不中断
    • 友好的状态提示:
      • 正在调用工具: [工具名]...
      • 工具执行完成
      • 工具执行失败: [错误信息]
      • 正在生成回复...

    ** 工具格式转换**

    • MCP 工具 → OpenAI Function 格式
    • 自动提取 inputSchema 作为 parameters
    • 支持完整的 JSON Schema 定义

    ️ 技术实现

    服务层改进

    • MCPClientService.getTools() - 获取工具列表
    • chatService.convertToolsToOpenAIFormat() - 格式转换
    • chatService.executeToolCalls() - 工具执行逻辑
    • modelServiceManager.sendChatRequestStream() - 增强工具参数支持

    流式解析增强

    • SSE 流中检测 tool_calls
    • 累积多个流片段中的工具调用数据
    • 正确拼接 function.arguments JSON 字符串
    • 返回完整的工具调用数组

    消息格式支持

    // 工具调用消息
    {
      role: 'assistant',
      content: '',
      tool_calls: [{
        id: '...',
        type: 'function',
        function: { name: '...', arguments: '{}' }
      }]
    }
    
    // 工具结果消息
    {
      tool_call_id: '...',
      role: 'tool',
      name: 'tool_name',
      content: '{...}'
    }
    

    使用方式

    1. 配置 AI 服务 - 在"模型服务"中添加支持函数调用的 AI
    2. 连接 MCP 服务器 - 在"MCP 设置"中添加工具服务器
    3. 选择模型和 MCP - 在对话界面选择
    4. 开始对话 - AI 会自动调用相关工具

    使用示例

    用户: "查询今天北京的天气"
    
    系统:  正在调用工具: get_weather...
          ✅ 工具执行完成
           正在生成回复...
    
    AI: "根据天气数据,今天北京晴天,温度 15-25°C,
         空气质量良好,适合户外活动。"
    

    Bug 修复

    • 修复 MCPClientService 类型导入问题
    • 修复 types.ts 和 types/index.ts 路径冲突
    • 修复 modelServiceManager 返回类型
    • 修复未使用变量警告

    技术细节

    修改的文件

    • /web/src/services/chatService.ts - 工具调用主逻辑
    • /web/src/services/modelServiceManager.ts - 工具参数支持
    • /web/src/services/MCPClientService.ts - 工具列表获取

    新增方法

    • MCPClientService.getTools(serverId) - 获取服务器工具
    • chatService.convertToolsToOpenAIFormat() - 格式转换
    • chatService.executeToolCalls() - 执行工具调用

    改进方法

    • modelServiceManager.sendChatRequestStream() - 支持 tools 参数
    • modelServiceManager.makeChatRequestStream() - 检测和收集 tool_calls

    设计亮点

    1. 无缝集成 - 不改变现有对话流程
    2. 错误恢复 - 工具调用失败不影响对话继续
    3. 类型安全 - 完整的 TypeScript 类型定义
    4. 性能优化 - 流式处理保持响应速度
    5. 用户友好 - 清晰的进度提示

    ⚙️ 配置要求

    AI 服务要求

    • 支持 OpenAI Function Calling 格式
    • 推荐:OpenAI GPT-3.5+, GPT-4+
    • 兼容:火山引擎、阿里云等 OpenAI 兼容服务

    MCP 服务器要求

    • 实现 tools/list 接口
    • 实现 tools/call 接口
    • 提供标准的 inputSchema (JSON Schema)

    相关文档

    升级指南

    # 拉取最新代码
    git pull origin main
    
    # 安装依赖(如有更新)
    cd web && npm install
    
    # 启动开发服务器
    npm run dev
    

    下一步计划

    • 工具调用历史记录
    • 工具执行超时控制
    • 批量工具调用优化
    • 工具调用权限管理
    • 工具调用性能监控

    v1.0.2 - AI + MCP 工具调用,让对话更智能!

    Downloads