Files
2026-06-01 13:54:52 +08:00

336 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 聊天数据模型
<cite>
**本文引用的文件**
- [chat_prompt.rs](file://crates/shared_types/src/model/chat_prompt.rs)
- [chat_response.rs](file://crates/shared_types/src/model/chat_response.rs)
- [attachment.rs](file://crates/shared_types/src/model/attachment.rs)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs)
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs)
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs)
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs)
- [router.rs](file://crates/agent_runner/src/router.rs)
- [http_test.rest](file://http_test.rest)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件聚焦于聊天数据模型,系统性阐述 ChatPrompt 与 ChatResponse 的结构定义、提示词构造规则、上下文管理机制与附件处理方式;同时结合 chat_handler 的实现逻辑完整描述从请求到响应的数据转换流程并给出流式响应SSE的数据分块格式、进度更新机制与终止条件。最后提供 HTTP 请求/响应示例与边界情况、错误处理模式,帮助开发者快速理解并正确使用该系统。
## 项目结构
围绕聊天数据模型的关键文件分布如下:
- 共享类型层:定义 ChatPrompt、ChatResponse、附件与模型提供商配置等核心数据结构
- 业务处理器层chat_handler 负责接收请求、构建 ChatPrompt、调度代理并返回统一响应
- 实时通知层SSE 通道 agent_session_notification 将会话消息以事件形式推送给客户端
- 会话缓存层session_cache 提供会话级消息缓冲与推送,支持心跳、取消与清理
- 代理服务层:根据模型提供商选择具体代理类型并启动 ACP 代理服务
```mermaid
graph TB
subgraph "共享类型层"
A["ChatPrompt<br/>ChatResponse<br/>Attachment<br/>ModelProviderConfig"]
end
subgraph "业务处理器层"
B["chat_handler.handle_chat"]
end
subgraph "代理服务层"
C["agent_service.AcpAgentService"]
end
subgraph "实时通知层"
D["agent_session_notification.SSE"]
E["session_cache.SessionData<br/>SessionWorker"]
end
B --> A
B --> C
C --> E
E --> D
```
图表来源
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L320)
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
章节来源
- [router.rs](file://crates/agent_runner/src/router.rs#L41-L70)
## 核心组件
- ChatPrompt承载一次聊天请求的全部上下文包括项目ID、工作目录、会话ID、提示词、附件、数据源附件、代理类型、服务类型、请求ID与模型提供商配置
- ChatResponse统一的聊天响应载体包含项目ID、会话ID、可选错误信息与请求ID
- Attachment多形态附件抽象支持文本、图像、音频、文档统一通过 AttachmentSource 表达数据来源文件路径、Base64、URL
- ModelProviderConfig模型提供商配置决定代理类型与 API 协议
- HttpResult统一的 HTTP 响应包装,包含 code、message、data、tid 与 success 字段
- AppError应用级错误封装统一映射为 HTTP 响应
章节来源
- [chat_prompt.rs](file://crates/shared_types/src/model/chat_prompt.rs#L1-L52)
- [chat_response.rs](file://crates/shared_types/src/model/chat_response.rs#L1-L18)
- [attachment.rs](file://crates/shared_types/src/model/attachment.rs#L1-L216)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L1-L132)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L1-L103)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
## 架构总览
下图展示从 HTTP 请求到 SSE 实时推送的整体流程,涵盖提示词构造、代理调度、会话管理与事件分发。
```mermaid
sequenceDiagram
participant Client as "客户端"
participant Handler as "chat_handler.handle_chat"
participant Builder as "ChatPromptBuilder"
participant Agent as "AcpAgentService"
participant Worker as "LocalSetAgentRequest"
participant Cache as "SessionData/SessionWorker"
participant SSE as "agent_session_notification.SSE"
Client->>Handler : POST /chat {prompt, attachments, ...}
Handler->>Handler : 校验参数/生成project_id/request_id
Handler->>Builder : 构建ChatPrompt
Builder-->>Handler : ChatPrompt
Handler->>Worker : 发送LocalSetAgentRequest
Worker->>Agent : 启动代理服务并执行
Agent->>Cache : 推送SessionNotify消息
Cache-->>SSE : 通过mpsc通道分发消息
SSE-->>Client : 事件流prompt_start/prompt_end/agent_message_chunk/heartbeat
```
图表来源
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L320)
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L140-L222)
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
## 详细组件分析
### ChatPrompt 与 ChatResponse 数据模型
- ChatPrompt 字段要点
- project_id项目唯一标识用于隔离工作空间
- project_path项目工作目录路径
- session_id会话标识可选若未提供则由代理自动创建并返回
- prompt用户提示词
- attachments附件列表支持文本、图像、音频、文档
- data_source_attachments数据源附件JSON 字符串数组),用于外部数据源信息传递
- agent_type代理类型由模型提供商配置推导
- service_type服务类型固定为 RCoder
- request_id请求追踪ID可选
- model_provider模型提供商配置决定代理与协议
- ChatResponse 字段要点
- project_id项目ID
- session_id会话ID
- error可选错误信息
- request_id可选请求追踪ID
提示词构造规则
- 若未提供 project_id处理器会自动生成 UUID 并移除连字符,随后创建项目工作目录
- 若未提供 session_id处理器会清理该项目下的所有旧会话确保全新开始
- 若未提供 request_id处理器会自动生成 UUID 并移除连字符
- 代理类型由模型提供商配置推导,服务类型固定为 RCoder
附件处理方式
- 附件通过统一的 Attachment 抽象表达,支持三种数据源:
- FilePath相对项目目录的文件路径
- Base64包含数据与 MIME 类型
- Url远程链接
- 附件类型包括 Text、Image、Audio、Document均包含可选的元数据如文件名、尺寸、时长、大小
章节来源
- [chat_prompt.rs](file://crates/shared_types/src/model/chat_prompt.rs#L1-L52)
- [chat_response.rs](file://crates/shared_types/src/model/chat_response.rs#L1-L18)
- [attachment.rs](file://crates/shared_types/src/model/attachment.rs#L1-L216)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L1-L132)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L198-L210)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L225-L258)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L266-L283)
### 上下文管理机制
- 项目与会话映射
- 通过 PROJECT_SESSION_MAP 确保同一 project_id 仅对应一个活跃 session_id
- 当 session_id 变化时,自动清理旧 session 的数据并更新映射
- 会话缓存与推送
- SessionData 维护当前连接与取消令牌,支持即时推送与环形缓冲
- SessionWorker 负责将消息写入环形缓冲并实时推送到当前连接
- 心跳消息定期发送,保持连接活性
- 会话清理策略
- 处理器在收到请求时,若指定 session_id 则移除该会话;否则清理该项目下所有会话
- 取消任务时,主动触发 CancellationToken 并关闭发送端,确保连接及时断开
章节来源
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L140-L222)
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L224-L355)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L225-L258)
### 流式响应SSE数据分块格式与终止条件
SSE 事件格式
- 事件名称与消息类型映射
- prompt_start会话开始
- prompt_end会话结束包含停止原因与可选错误信息
- agent_message_chunk代理输出片段
- user_message_chunk用户输入片段
- agent_thought_chunk代理思考片段
- tool_call/tool_call_update工具调用与更新
- plan/available_commands_update/current_mode_update计划、可用命令与当前模式更新
- heartbeat心跳事件
- 数据内容
- 统一以 UnifiedSessionMessage 形式推送,包含 session_id、message_type、sub_type、data 与时间戳
- data 内容根据子类型不同而异,例如 agent_message_chunk 的 data.content 包含文本内容与类型
进度更新机制
- SSE 连接建立后立即发送 heartbeat随后持续推送实时更新
- 心跳定时器每 30 秒发送一次,用于维持连接活性
- 当取消令牌被触发或发送端被关闭时SSE 自然断开
终止条件
- 会话结束事件prompt_end携带停止原因如 EndTurn、MaxTokens、MaxTurnRequests、Refusal、Cancelled
- 取消任务时,主动关闭连接并清理旧消息
- 容器连接失败或读取 SSE 流失败时,发送 error 事件并断开连接
章节来源
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L36-L57)
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L1-L180)
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L140-L222)
### 请求到响应的完整数据转换流程
- 输入HTTP 请求体包含 prompt、可选 project_id、session_id、attachments、data_source_attachments、model_provider、request_id
- 处理:
- 参数校验prompt 非空)
- 自动生成 project_id 与 request_id如缺失
- 清理旧会话(按 session_id 或项目维度)
- 构建 ChatPrompt 并发送到本地任务通道
- 等待 ChatPromptResponse若包含错误则返回统一错误响应
- 输出HttpResult<ChatResponse>包含项目ID、会话ID与可选错误信息
```mermaid
flowchart TD
Start(["进入 handle_chat"]) --> Validate["校验 prompt 非空"]
Validate --> GenIds{"是否提供 project_id/request_id?"}
GenIds --> |否| GenPid["生成 project_id 并创建工作目录"]
GenIds --> |是| UseProvided["使用提供的 project_id/request_id"]
GenPid --> CleanSessions["清理旧会话按 session_id 或项目"]
UseProvided --> CleanSessions
CleanSessions --> BuildPrompt["构建 ChatPrompt"]
BuildPrompt --> SendTask["发送 LocalSetAgentRequest"]
SendTask --> AwaitResp{"收到 ChatPromptResponse?"}
AwaitResp --> |是且有错误| ReturnErr["返回统一错误响应"]
AwaitResp --> |是且无错误| ReturnOk["返回 HttpResult.success(ChatResponse)"]
AwaitResp --> |否| ReturnLocalErr["返回本地发送错误"]
```
图表来源
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L320)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L1-L103)
章节来源
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L320)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L1-L103)
### 代理类型与模型提供商配置
- 代理类型选择
- 根据模型提供商配置推导代理类型Claude、Codex 等)
- 通过 AcpAgentService trait 启动对应代理服务
- 模型提供商配置
- 包含 id、name、base_url、api_key、requires_openai_auth、default_model、api_protocol
- api_protocol 默认 OpenAI支持 Anthropic 与 OpenAI
章节来源
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L1-L132)
## 依赖关系分析
- 组件耦合与内聚
- chat_handler 与 shared_types 的 ChatPrompt/ChatResponse 强耦合,但通过 Builder 模式降低复杂度
- 代理服务通过 trait 解耦,便于扩展新代理类型
- SSE 层通过 SessionData/SessionWorker 与处理器解耦,实现高内聚低耦合
- 外部依赖
- Axum 路由与响应封装
- Tokio mpsc 通道用于异步消息传递
- DashMap 用于全局会话缓存
```mermaid
graph LR
chat_handler["chat_handler.handle_chat"] --> shared_types["shared_types.ChatPrompt/ChatResponse"]
chat_handler --> agent_service["AcpAgentService"]
agent_service --> session_cache["SessionData/SessionWorker"]
session_cache --> agent_session_notification["SSE 事件推送"]
```
图表来源
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L320)
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
章节来源
- [router.rs](file://crates/agent_runner/src/router.rs#L41-L70)
## 性能考量
- 会话消息缓冲
- 使用环形缓冲ringbuf提升消息吞吐避免阻塞
- 心跳消息不入环形缓冲,确保实时性
- 连接管理
- 通过 CancellationToken 主动关闭旧连接,避免资源泄漏
- 即时推送失败时自动降级为丢弃,保证系统稳定性
- 并发控制
- 项目级并发限制:同一项目仅允许一个活跃代理任务
- 会话级清理:确保新会话不会混入旧消息
章节来源
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L140-L222)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L211-L224)
## 故障排查指南
常见错误与处理
- 参数校验失败
- prompt 为空:返回统一错误响应
- 并发请求限制
- 项目存在活跃代理任务返回“Agent正在执行任务请等待当前任务完成后再发送新请求”
- 本地发送错误
- 任务通道发送失败:返回本地发送错误
- SSE 连接问题
- 容器连接失败或读取流失败:发送 error 事件并断开连接
- 未找到对应容器:返回“未找到 session_id 对应的活跃容器”
章节来源
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L137-L168)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L211-L224)
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L135-L153)
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L231-L244)
## 结论
本文系统梳理了聊天数据模型的核心结构与处理流程,明确了提示词构造规则、上下文管理机制与附件处理方式,并深入解析了 SSE 的事件格式、进度更新与终止条件。结合 chat_handler 的实现逻辑,读者可以准确把握从请求到响应的全链路数据转换过程,并据此编写正确的 HTTP 请求与客户端消费逻辑。
## 附录
### HTTP 请求/响应示例
- 创建聊天会话POST /chat
- 请求体字段prompt、project_id可选、session_id可选、attachments可选、data_source_attachments可选、model_provider可选、request_id可选
- 成功响应HttpResult.success(ChatResponse),包含 project_id、session_id、request_id
- 错误响应HttpResult.error(code, message)
- 建立 SSE 连接GET /agent/progress/{session_id}
- 事件类型prompt_start、prompt_end、agent_message_chunk、user_message_chunk、agent_thought_chunk、tool_call、tool_call_update、plan、available_commands_update、current_mode_update、heartbeat
- 断开条件:取消令牌触发、发送端关闭、容器连接失败
- 取消会话POST /agent/session/cancel
- 参数project_id、session_id
- 行为:主动关闭 SSE 连接并清理旧消息
章节来源
- [http_test.rest](file://http_test.rest#L1-L109)
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L102-L173)
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)