Files
cherry-studio/docs/technical/how-to-use-messageThunk.md
MyPrototypeWhat 4225d20760 feat: 添加 messageBlock、messageThunk 和 useMessageOperations 使用指南文档
- 新增 `how-to-use-messageBlock.md`,详细介绍 `messageBlock.ts` 的 Redux Slice 及其状态管理、actions 和 selectors。
- 新增 `how-to-use-messageThunk.md`,概述 `messageThunk.ts` 的核心功能和主要 Thunks 的使用。
- 新增 `how-to-use-useMessageOperations.md`,提供 `useMessageOperations` Hook 的使用示例和功能说明,简化组件与消息数据的交互。
2025-04-29 15:14:55 +08:00

7.4 KiB
Raw Blame History

messageThunk.ts 使用指南

该文件包含用于管理应用程序中消息流、处理助手交互以及同步 Redux 状态与 IndexedDB 数据库的核心 Thunk Action Creators。主要围绕 MessageMessageBlock 对象进行操作。

核心功能

  1. 发送/接收消息: 处理用户消息的发送,触发助手响应,并流式处理返回的数据,将其解析为不同的 MessageBlock
  2. 状态管理: 确保 Redux store 中的消息和消息块状态与 IndexedDB 中的持久化数据保持一致。
  3. 消息操作: 提供删除、重发、重新生成、编辑后重发、追加响应、克隆等消息生命周期管理功能。
  4. Block 处理: 动态创建、更新和保存各种类型的 MessageBlock(文本、思考过程、工具调用、引用、图片、错误、翻译等)。

主要 Thunks

以下是一些关键的 Thunk 函数及其用途:

  1. sendMessage(userMessage, userMessageBlocks, assistant, topicId)

    • 用途: 发送一条新的用户消息。
    • 流程:
      • 保存用户消息 (userMessage) 及其块 (userMessageBlocks) 到 Redux 和 DB。
      • 检查 @mentions 以确定是单模型响应还是多模型响应。
      • 创建助手消息(们)的存根 (Stub)。
      • 将存根添加到 Redux 和 DB。
      • 将核心处理逻辑 fetchAndProcessAssistantResponseImpl 添加到该 topicId 的队列中以获取实际响应。
    • Block 相关: 主要处理用户消息的初始 MessageBlock 保存。
  2. fetchAndProcessAssistantResponseImpl(dispatch, getState, topicId, assistant, assistantMessage)

    • 用途: (内部函数) 获取并处理单个助手响应的核心逻辑,被 sendMessage, resend..., regenerate..., append... 等调用。
    • 流程:
      • 设置 Topic 加载状态。
      • 准备上下文消息。
      • 调用 fetchChatCompletion API 服务。
      • 使用 createStreamProcessor 处理流式响应。
      • 通过各种回调 (onTextChunk, onThinkingChunk, onToolCallComplete, onImageGenerated, onError, onComplete 等) 处理不同类型的事件。
    • Block 相关:
      • 根据流事件创建初始 UNKNOWN 块。
      • 实时创建和更新 MAIN_TEXTTHINKING 块,使用 throttledBlockUpdatethrottledBlockDbUpdate 进行节流更新。
      • 创建 TOOL, CITATION, IMAGE, ERROR 等类型的块。
      • 在事件完成时(如 onTextComplete, onToolCallComplete)将块状态标记为 SUCCESSERROR,并使用 saveUpdatedBlockToDB 保存最终状态。
      • 使用 handleBlockTransition 管理非流式块(如 TOOL, CITATION)的添加和状态更新。
  3. loadTopicMessagesThunk(topicId, forceReload)

    • 用途: 从数据库加载指定主题的所有消息及其关联的 MessageBlock
    • 流程:
      • 从 DB 获取 Topic 及其 messages 列表。
      • 根据消息 ID 列表从 DB 获取所有相关的 MessageBlock
      • 使用 upsertManyBlocks 将块更新到 Redux。
      • 将消息更新到 Redux。
    • Block 相关: 负责将持久化的 MessageBlock 加载到 Redux 状态。
  4. 删除 Thunks

    • deleteSingleMessageThunk(topicId, messageId): 删除单个消息及其所有 MessageBlock
    • deleteMessageGroupThunk(topicId, askId): 删除一个用户消息及其所有相关的助手响应消息和它们的所有 MessageBlock
    • clearTopicMessagesThunk(topicId): 清空主题下的所有消息及其所有 MessageBlock
    • Block 相关: 从 Redux 和 DB 中移除指定的 MessageBlock
  5. 重发/重新生成 Thunks

    • resendMessageThunk(topicId, userMessageToResend, assistant): 重发用户消息。会重置(清空 Block 并标记为 PENDING所有与该用户消息关联的助手响应然后重新请求生成。
    • resendUserMessageWithEditThunk(topicId, originalMessage, mainTextBlockId, editedContent, assistant): 用户编辑消息内容后重发。先更新用户消息的 MAIN_TEXT 块内容,然后调用 resendMessageThunk
    • regenerateAssistantResponseThunk(topicId, assistantMessageToRegenerate, assistant): 重新生成单个助手响应。重置该助手消息(清空 Block 并标记为 PENDING然后重新请求生成。
    • Block 相关: 删除旧的 MessageBlock,并在重新生成过程中创建新的 MessageBlock
  6. appendAssistantResponseThunk(topicId, existingAssistantMessageId, newModel, assistant)

    • 用途: 在已有的对话上下文中,针对同一个用户问题,使用新选择的模型追加一个新的助手响应。
    • 流程:
      • 找到现有助手消息以获取原始 askId
      • 创建使用 newModel 的新助手消息存根(使用相同的 askId)。
      • 添加新存根到 Redux 和 DB。
      • fetchAndProcessAssistantResponseImpl 添加到队列以生成新响应。
    • Block 相关: 为新的助手响应创建全新的 MessageBlock
  7. cloneMessagesToNewTopicThunk(sourceTopicId, branchPointIndex, newTopic)

    • 用途: 将源主题的部分消息(及其 Block克隆到一个已存在的新主题中。
    • 流程:
      • 复制指定索引前的消息。
      • 为所有克隆的消息和 Block 生成新的 UUID。
      • 正确映射克隆消息之间的 askId 关系。
      • 复制 MessageBlock 内容,更新其 messageId 指向新的消息 ID。
      • 更新文件引用计数(如果 Block 是文件或图片)。
      • 将克隆的消息和 Block 保存到新主题的 Redux 状态和 DB 中。
    • Block 相关: 创建 MessageBlock 的副本,并更新其 ID 和 messageId
  8. initiateTranslationThunk(messageId, topicId, targetLanguage, sourceBlockId?, sourceLanguage?)

    • 用途: 为指定消息启动翻译流程,创建一个初始的 TRANSLATION 类型的 MessageBlock
    • 流程:
      • 创建一个状态为 STREAMINGTranslationMessageBlock
      • 将其添加到 Redux 和 DB。
      • 更新原消息的 blocks 列表以包含新的翻译块 ID。
    • Block 相关: 创建并保存一个占位的 TranslationMessageBlock。实际翻译内容的获取和填充需要后续步骤。

内部机制和注意事项

  • 数据库交互: 通过 saveMessageAndBlocksToDB, updateExistingMessageAndBlocksInDB, saveUpdatesToDB, saveUpdatedBlockToDB, throttledBlockDbUpdate 等辅助函数与 IndexedDB (db) 交互,确保数据持久化。
  • 状态同步: Thunks 负责协调 Redux Store 和 IndexedDB 之间的数据一致性。
  • 队列 (getTopicQueue): 使用 AsyncQueue 确保对同一主题的操作(尤其是 API 请求)按顺序执行,避免竞态条件。
  • 节流 (throttle): 对流式响应中频繁的 Block 更新(文本、思考)使用 lodash.throttle 优化性能,减少 Redux dispatch 和 DB 写入次数。
  • 错误处理: fetchAndProcessAssistantResponseImpl 内的回调函数(特别是 onError)处理流处理和 API 调用中可能出现的错误,并创建 ERROR 类型的 MessageBlock

开发者在使用这些 Thunks 时,通常需要提供 dispatch, getState (由 Redux Thunk 中间件注入),以及如 topicId, assistant 配置对象, 相关的 MessageMessageBlock 对象/ID 等参数。理解每个 Thunk 的职责和它如何影响消息及块的状态至关重要。