# 数据模型与类型 **本文档引用的文件** - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs) - [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) - [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs) - [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs) - [http_result.rs](file://crates/shared_types/src/model/http_result.rs) - [agent_project_runner_model.rs](file://crates/shared_types/src/model/agent_project_runner_model.rs) - [agent.proto](file://crates/shared_types/proto/agent.proto) - [config.yml](file://config.yml) - [rcoder_default.yml](file://crates/rcoder/src/rcoder_default.yml) - [agent-abstraction-layer-design.md](file://specs/agent-abstraction-layer-design.md) ## 目录 1. [引言](#引言) 2. [核心实体与关系](#核心实体与关系) 3. [字段定义与数据类型](#字段定义与数据类型) 4. [主键/外键、索引与约束](#主键外键索引与约束) 5. [数据验证规则与业务规则](#数据验证规则与业务规则) 6. [数据库模式图](#数据库模式图) 7. [示例数据](#示例数据) 8. [数据访问模式、缓存策略与性能考虑](#数据访问模式缓存策略与性能考虑) 9. [数据生命周期、保留策略与归档规则](#数据生命周期保留策略与归档规则) 10. [数据迁移路径与版本管理](#数据迁移路径与版本管理) ## 引言 RCoder项目是一个基于AI代理的开发辅助系统,其数据模型设计围绕AI代理服务、会话管理、项目状态和用户交互等核心功能构建。本数据模型文档旨在全面介绍RCoder项目的数据结构、类型定义、实体关系以及相关的业务规则和性能策略。通过分析`shared_types` crate中的Rust结构体和`proto`文件中的gRPC消息定义,我们能够理解系统中数据的组织方式和流转过程。该模型支持多代理类型(如Claude和Codex)、灵活的模型提供商配置、丰富的附件类型,并通过gRPC协议实现服务间的通信。此外,系统的配置文件(YAML)定义了服务部署和运行时的参数,这些参数也构成了系统数据模型的一部分。 ## 核心实体与关系 RCoder项目的数据模型围绕几个核心实体构建,这些实体通过明确的关系相互连接,形成了一个支持AI代理服务生命周期管理的系统。主要实体包括`Agent`(代理)、`Project`(项目)、`Session`(会话)、`ModelProvider`(模型提供商)和`Attachment`(附件)。 `Project`(项目)是用户工作的核心单元,每个项目由唯一的`project_id`标识。一个项目可以关联一个正在运行的`Agent`实例。这种关系通过`ProjectAndAgentInfo`结构体体现,其中`project_id`作为关键字段将项目与代理实例绑定。`Agent`实例的生命周期由`AgentLifecycleGuard`管理,当代理被创建时,它会与一个`Session`(会话)相关联,会话ID(`session_id`)是代理与用户交互过程中的唯一标识。 `ModelProvider`(模型提供商)为`Agent`提供AI模型能力。`Agent`通过`model_provider`字段引用一个`ModelProviderConfig`对象,该对象包含了访问AI模型API所需的所有信息,如API密钥、基础URL和默认模型名称。一个`ModelProvider`可以被多个`Agent`实例共享,但一个`Agent`在同一时间只能使用一个`ModelProvider`。 `Attachment`(附件)是用户在与AI代理交互时可以附加到提示(prompt)中的数据。一个`ChatPrompt`请求可以包含多个`Attachment`,形成一对多的关系。`Attachment`是一个枚举类型,支持多种媒体类型,如文本、图像、音频和文档,这使得用户可以提供丰富的上下文信息给AI代理。 最后,`Session`(会话)不仅是代理运行的上下文,也是状态更新和消息通知的载体。`AgentSessionUpdate`、`SessionPromptStart`和`SessionPromptEnd`等结构体都包含`session_id`,用于将状态更新与特定的会话关联起来。这些更新通过`SessionNotify`枚举被统一处理,并最终转换为`UnifiedSessionMessage`发送给前端,实现服务端到客户端的实时通信。 ```mermaid erDiagram PROJECT { string project_id PK datetime created_at datetime last_activity } SESSION { string session_id PK string project_id FK string request_id datetime created_at datetime last_activity string status } AGENT { string agent_type string status string session_id FK string model_provider_id FK } MODEL_PROVIDER { string id PK string name string base_url string api_key string default_model string api_protocol } ATTACHMENT { string id PK string session_id FK string source_type string mime_type string filename text description } CHAT_PROMPT { string project_id FK string session_id FK string prompt string request_id string agent_type string service_type } CHAT_RESPONSE { string project_id FK string session_id FK string request_id string error } PROJECT ||--o{ SESSION : "1 to many" SESSION ||--|| AGENT : "1 to 1" SESSION ||--o{ ATTACHMENT : "1 to many" AGENT }|--|| MODEL_PROVIDER : "uses" CHAT_PROMPT }|--|| SESSION : "references" CHAT_RESPONSE }|--|| SESSION : "references" ``` **图源** - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L47-L68) - [chat_prompt.rs](file://crates/shared_types/src/model/chat_prompt.rs#L8-L29) - [chat_response.rs](file://crates/shared_types/src/model/chat_response.rs#L5-L17) - [attachment.rs](file://crates/shared_types/src/model/attachment.rs#L93-L104) - [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L45-L67) **本节来源** - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs) - [chat_prompt.rs](file://crates/shared_types/src/model/chat_prompt.rs) - [attachment.rs](file://crates/shared_types/src/model/attachment.rs) - [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs) ## 字段定义与数据类型 本节详细定义RCoder数据模型中各核心实体的字段及其数据类型。所有类型均基于Rust语言定义,并通过`serde`和`utoipa`等库支持序列化、反序列化和API文档生成。 ### ProjectAndAgentInfo (项目与代理信息) 该结构体是`rcoder`和`agent_runner`共用的核心结构,代表一个项目与其实例化代理的关联。 - `project_id` (`String`): 项目的唯一标识符。 - `session_id` (`SessionId`): 代理服务的会话ID,由代理启动时创建。 - `prompt_tx` (`mpsc::UnboundedSender`): 用于向代理发送提示请求的异步通道。 - `cancel_tx` (`mpsc::UnboundedSender`): 用于向代理发送取消通知的异步通道。 - `model_provider` (`Option`): 可选的模型提供商配置,为代理提供AI模型能力。 - `request_id` (`Option`): 当前活跃的用户请求ID,用于追踪单个请求。 - `status` (`AgentStatus`): 代理的当前服务状态(`Active`, `Idle`, `Terminating`)。 - `last_activity` (`DateTime`): 代理最后一次活动的时间戳。 - `created_at` (`DateTime`): 代理实例的创建时间戳。 - `stop_handle` (`Option>`): 代理生命周期管理的句柄,用于优雅停止代理。 ### ChatPrompt (聊天提示) 该结构体定义了用户向AI代理发送的请求。 - `project_id` (`String`): 关联的项目ID。 - `project_path` (`PathBuf`): 项目在文件系统中的路径。 - `session_id` (`Option`): 可选的会话ID。如果未提供,代理将自动创建一个新会话。 - `prompt` (`String`): 用户输入的提示内容。 - `attachments` (`Vec`): 可选的附件列表,`Builder`模式下默认为空。 - `data_source_attachments` (`Vec`): 用于AI开发的外部数据源信息,以JSON字符串数组形式传递。 - `agent_type` (`AgentType`): 指定使用的代理类型(`Claude`或`Codex`),`Builder`模式下默认值。 - `service_type` (`ServiceType`): 必填字段,指定使用的服务类型(`rcoder`或`agent-runner`)。 - `request_id` (`Option`): 可选的请求ID,用于标识和追踪。 - `model_provider` (`Option`): 可选的模型提供商配置,用于覆盖默认配置。 ### ChatResponse (聊天响应) 该结构体定义了AI代理对用户请求的响应。 - `project_id` (`String`): 关联的项目ID。 - `session_id` (`String`): 代理的会话ID。 - `error` (`Option`): 可选的错误信息,如果请求失败则填充。 - `request_id` (`Option`): 请求ID,用于标识和追踪。 - `service_type` (`ServiceType`): 使用的服务类型。 ### Attachment (附件) `Attachment`是一个枚举类型,支持多种媒体格式。 - **通用字段**: - `id` (`String`): 附件的唯一标识符,使用UUID生成。 - `source` (`AttachmentSource`): 附件数据源,枚举类型,包含`FilePath`、`Base64`和`Url`。 - `filename` (`Option`): 可选的文件名。 - `description` (`Option`): 可选的描述。 - **TextAttachment (文本附件)**: 无额外字段。 - **ImageAttachment (图像附件)**: - `mime_type` (`String`): MIME类型(如`image/jpeg`)。 - `dimensions` (`Option`): 可选的图像尺寸信息。 - **AudioAttachment (音频附件)**: - `mime_type` (`String`): MIME类型(如`audio/mp3`)。 - `duration` (`Option`): 可选的音频时长(秒)。 - **DocumentAttachment (文档附件)**: - `mime_type` (`String`): MIME类型(如`application/pdf`)。 - `size` (`Option`): 可选的文件大小(字节)。 ### ModelProviderConfig (模型提供商配置) 该结构体封装了访问AI模型API所需的所有凭证和配置。 - `id` (`String`): 模型提供商的唯一ID。 - `name` (`String`): 提供商名称(如`openai`, `anthropic`)。 - `base_url` (`String`): API的基础URL。 - `api_key` (`String`): 访问API的密钥。 - `requires_openai_auth` (`bool`): 是否需要OpenAI兼容的认证头。 - `default_model` (`String`): 默认使用的模型名称。 - `api_protocol` (`Option`): 模型接口协议类型(`anthropic`或`openai`),可选。 ### AgentSessionUpdate (代理会话更新) 该结构体封装了代理在执行任务过程中产生的各种更新事件。 - `session_id` (`String`): 关联的会话ID。 - `session_update` (`SessionUpdate`): 具体的更新内容,为枚举类型,包含`UserMessageChunk`、`AgentMessageChunk`、`ToolCall`等。 - `request_id` (`Option`): 可选的请求ID。 **本节来源** - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L47-L68) - [chat_prompt.rs](file://crates/shared_types/src/model/chat_prompt.rs#L8-L29) - [chat_response.rs](file://crates/shared_types/src/model/chat_response.rs#L5-L17) - [attachment.rs](file://crates/shared_types/src/model/attachment.rs#L23-L90) - [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L45-L67) - [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L61-L65) ## 主键外键索引与约束 RCoder的数据模型主要在内存和进程间通信层面运作,其“主键”和“外键”概念更多地体现在数据结构的逻辑关联和唯一性保证上,而非传统的关系型数据库约束。 ### 主键 (Primary Keys) - **`project_id`**: 在`ProjectAndAgentInfo`和`ChatPrompt`等结构体中,`project_id`是项目实体的逻辑主键。它确保了每个项目在系统中的唯一性,并作为查找和管理项目相关资源(如代理、会话)的主要依据。 - **`session_id`**: 在`ProjectAndAgentInfo`和`AgentSessionUpdate`等结构体中,`session_id`是会话实体的逻辑主键。它唯一标识一个代理的运行实例,所有与该代理的交互(如发送提示、接收更新、取消任务)都通过此ID进行。 - **`id`**: 在`Attachment`结构体中,`id`字段(由`Uuid::new_v4()`生成)是每个附件的唯一标识符,作为附件的主键。 ### 外键 (Foreign Keys) - **`project_id` in `ProjectAndAgentInfo`**: 该字段作为外键,将`ProjectAndAgentInfo`记录与一个具体的`Project`实体关联起来。它确保了代理实例的归属。 - **`session_id` in `ProjectAndAgentInfo`**: 该字段作为外键,将`ProjectAndAgentInfo`记录与一个具体的`Session`实体关联起来。它建立了项目、代理和会话三者之间的联系。 - **`session_id` in `AgentSessionUpdate`**: 该字段作为外键,将状态更新事件与一个具体的会话关联,确保前端能够正确地将更新渲染到对应的会话流中。 - **`request_id` in `ChatPrompt` and `ChatResponse`**: 虽然`request_id`不是严格的外键,但它起到了关联请求和响应的作用,是实现请求-响应追踪的关键。 ### 索引与约束 由于数据主要存储在内存数据结构(如`DashMap`)中,索引是隐式存在的。 - **内存索引**: `ProjectAndAgentInfo`通常被存储在以`project_id`为键的`DashMap`中。这使得通过`project_id`查找代理信息的操作具有接近O(1)的时间复杂度,相当于在`project_id`上创建了一个哈希索引。 - **业务约束**: 1. **唯一性约束**: 系统设计上保证一个`project_id`在同一时间只能关联一个活跃的`Agent`实例。当为一个已有代理的项目创建新会话时,旧的代理实例会被终止。 2. **非空约束**: `ChatPrompt`中的`project_id`、`prompt`和`service_type`字段是必填的,由`Builder`模式和业务逻辑保证。 3. **枚举约束**: `AgentType`和`AgentStatus`等字段的值被限制在预定义的枚举范围内,由Rust的类型系统强制执行。 4. **格式约束**: `model_provider.api_key`等敏感字段在日志中会被脱敏(如显示为`sk-***abc`),通过`Display` trait的实现来保证。 **本节来源** - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L47-L68) - [chat_prompt.rs](file://crates/shared_types/src/model/chat_prompt.rs#L10-L29) - [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L61-L65) ## 数据验证规则与业务规则 RCoder项目通过Rust的强类型系统、`derive_builder`宏和自定义验证逻辑来实施数据验证和业务规则。 ### 数据验证规则 - **类型安全**: Rust的编译时类型检查确保了字段的数据类型正确,例如`last_activity`必须是`DateTime`,`status`必须是`AgentStatus`枚举的成员。 - **必填字段验证**: `ChatPrompt`结构体使用`derive_builder`宏。`project_id`、`prompt`和`service_type`没有`#[builder(default)]`属性,因此在构建时必须显式提供,否则编译失败。 - **枚举值验证**: `AgentType`实现了`FromStr` trait,当从字符串解析时,会检查输入是否为有效的类型(`"claude"`或`"codex"`),否则返回错误。 - **附件处理验证**: `Attachment`模块定义了`AttachmentError`枚举,用于处理文件读取、Base64解码、URL访问等操作中可能出现的错误,确保附件数据的完整性和可用性。 ### 业务规则 - **代理生命周期管理**: 代理的创建、运行和销毁遵循严格的业务流程。`AgentLifecycleGuard`实现了RAII(资源获取即初始化)原则,当其被`drop`时会自动触发资源清理。`graceful_stop`方法首先发送取消信号,等待任务自然退出,最后强制清理资源,确保了代理的优雅关闭。 - **会话与项目绑定**: 一个`project_id`在同一时间只能有一个活跃的代理会话。当收到新的`ChatPrompt`请求时,如果该项目已有代理在运行,系统会先取消旧的会话,再启动新的会话,避免资源冲突。 - **模型提供商推断**: `AgentType::from_model_provider`方法根据`ModelProviderConfig`的`name`字段自动推断应使用的代理类型(`anthropic` -> `Claude`),简化了用户配置。 - **环境变量注入**: `AgentType`提供了`claude_from_env`和`codex_from_env`等方法,能够从进程环境变量中读取配置,并自动注入必要的启动参数(如`--dangerously-skip-permissions`),确保代理能够正确启动。 - **状态更新的统一处理**: 所有的会话状态更新(开始、结束、错误、进度)都通过`SessionNotify`枚举被转换为统一的`UnifiedSessionMessage`格式。这保证了前端接收到的消息格式一致,简化了前端的处理逻辑。 - **配置优先级**: 当`ChatPrompt`中提供了`model_provider`时,它会覆盖系统默认的模型提供商配置,实现了按请求级别的配置覆盖。 **本节来源** - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L339-L403) - [chat_prompt.rs](file://crates/shared_types/src/model/chat_prompt.rs#L6-L29) - [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L115-L124) - [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L77-L162) ## 数据库模式图 RCoder项目并未使用传统的关系型数据库,其数据主要存储在内存中,并通过gRPC进行服务间通信。因此,其“数据库”模式更准确地描述为**数据结构与通信协议模式**。 ```mermaid classDiagram class ProjectAndAgentInfo { +project_id : String +session_id : SessionId +prompt_tx : mpsc : : UnboundedSender +cancel_tx : mpsc : : UnboundedSender +model_provider : Option +request_id : Option +status : AgentStatus +last_activity : DateTime +created_at : DateTime +stop_handle : Option> } class ChatPrompt { +project_id : String +project_path : PathBuf +session_id : Option +prompt : String +attachments : Vec +data_source_attachments : Vec +agent_type : AgentType +service_type : ServiceType +request_id : Option +model_provider : Option } class ChatResponse { +project_id : String +session_id : String +error : Option +request_id : Option +service_type : ServiceType } class Attachment { +id : String +source : AttachmentSource +filename : Option +description : Option } class AttachmentSource { <> +FilePath{ path : String } +Base64{ data : String, mime_type : String } +Url{ url : String } } class ModelProviderConfig { +id : String +name : String +base_url : String +api_key : String +requires_openai_auth : bool +default_model : String +api_protocol : Option } class AgentSessionUpdate { +session_id : String +session_update : SessionUpdate +request_id : Option } class SessionUpdate { <> +UserMessageChunk +AgentMessageChunk +ToolCall +Plan +AvailableCommandsUpdate +CurrentModeUpdate } class UnifiedSessionMessage { +session_id : String +message_type : SessionMessageType +sub_type : String +data : serde_json : : Value +timestamp : DateTime } class HttpResult~T~ { +code : String +message : String +data : Option~T~ +tid : Option +success : bool } ProjectAndAgentInfo --> ModelProviderConfig : "uses" ChatPrompt --> Attachment : "has many" ChatPrompt --> ModelProviderConfig : "can override" AgentSessionUpdate --> SessionUpdate : "contains" AgentSessionUpdate --> UnifiedSessionMessage : "converts to" HttpResult --> ChatResponse : "wraps" HttpResult --> AgentStatusResponse : "wraps" ``` **图源** - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs) - [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) - [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs) - [http_result.rs](file://crates/shared_types/src/model/http_result.rs) ## 示例数据 以下是根据数据模型生成的JSON格式示例数据,展示了API请求和响应的典型结构。 ### ChatPrompt 请求示例 ```json { "project_id": "my-web-app", "project_path": "/home/user/project_workspace/my-web-app", "session_id": null, "prompt": "请帮我创建一个React组件,实现一个带有搜索功能的用户列表。", "attachments": [ { "type": "text", "content": { "id": "att-123", "source": { "source_type": "FilePath", "data": { "path": "src/components/UserList.js" } }, "filename": "UserList.js", "description": "现有用户列表组件" } } ], "data_source_attachments": [], "agent_type": "Claude", "service_type": "rcoder", "request_id": "req-abc123", "model_provider": { "id": "openai-gpt4", "name": "openai", "base_url": "https://api.openai.com/v1", "api_key": "sk-very-long-secret-key", "requires_openai_auth": true, "default_model": "gpt-4-turbo", "api_protocol": "openai" } } ``` ### ChatResponse 响应示例 ```json { "project_id": "my-web-app", "session_id": "sess-456def", "error": null, "request_id": "req-abc123", "service_type": "rcoder" } ``` ### AgentStatusResponse 响应示例 ```json { "project_id": "my-web-app", "is_alive": true, "session_id": "sess-456def", "status": "Active", "last_activity": "2024-01-01T12:05:30Z", "created_at": "2024-01-01T12:00:00Z", "model_provider": { "id": "openai-gpt4", "name": "openai", "api_protocol": "openai", "default_model": "gpt-4-turbo" } } ``` ### UnifiedSessionMessage (SSE流) 示例 ```json { "session_id": "sess-456def", "message_type": "AgentSessionUpdate", "sub_type": "agent_message_chunk", "data": { "content": { "text": "好的,我将为您创建一个React组件...", "type": "text" }, "request_id": "req-abc123" }, "timestamp": "2024-01-01T12:05:35Z" } ``` **本节来源** - [chat_prompt.rs](file://crates/shared_types/src/model/chat_prompt.rs) - [chat_response.rs](file://crates/shared_types/src/model/chat_response.rs) - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L71-L97) - [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L17-L30) ## 数据访问模式缓存策略与性能考虑 RCoder项目的数据访问模式、缓存策略和性能优化紧密围绕其高并发、低延迟的实时交互需求设计。 ### 数据访问模式 - **内存优先**: 核心状态(如`ProjectAndAgentInfo`)存储在全局的`DashMap`或`RwLock`中,提供极快的读写速度。通过`project_id`作为键进行哈希查找,实现O(1)的平均时间复杂度。 - **异步通道通信**: `rcoder`主服务与`agent_runner`代理服务之间通过`tokio`的`mpsc`(多生产者单消费者)无界通道进行通信。`prompt_tx`用于发送提示,`cancel_tx`用于发送取消指令。这种模式避免了直接的函数调用开销,实现了服务间的解耦和非阻塞通信。 - **gRPC流式传输**: 代理的执行进度通过gRPC的服务器流式RPC(`SubscribeProgress`)或SSE(Server-Sent Events)实时推送给前端。`UnifiedSessionMessage`被序列化为JSON并通过流发送,确保了低延迟的用户体验。 - **原子操作与锁优化**: `ProjectState`结构体使用`Arc`和`Arc`,结合`Arc::make_mut`实现写时复制(Copy-on-Write),在读多写少的场景下极大减少了锁竞争。`AtomicBool`用于`AgentLifecycleGuard`的状态标记,避免了对整个结构体的加锁。 ### 缓存策略 - **配置缓存**: `MultiImageConfig`中的`cache_config`允许缓存Docker镜像选择的结果,避免重复的镜像解析和选择计算,提高容器启动速度。 - **内存缓存**: 整个`ProjectAndAgentInfo`映射本身就是一种内存缓存,避免了每次请求都重新创建或查询代理实例。 - **无持久化缓存**: 项目未使用Redis等外部缓存系统,所有缓存均为进程内内存缓存,简化了架构,但依赖于单个进程的可用性。 ### 性能考虑 - **零拷贝与高效克隆**: 广泛使用`Arc`(原子引用计数)来共享数据,避免了不必要的数据复制。`ProjectState`的设计确保了核心状态的高效克隆。 - **异步非阻塞I/O**: 整个系统基于`tokio`异步运行时构建,所有I/O操作(文件读写、网络通信、进程管理)都是非阻塞的,能够高效处理大量并发连接。 - **资源限制**: 通过`docker_config`中的`resource_limits`(如`memory_limit`, `cpu_limit`)对Docker容器施加资源限制,防止单个代理消耗过多系统资源,影响整体稳定性。 - **连接池与复用**: 虽然未明确提及,但`reqwest`客户端等HTTP库通常会内部维护连接池,复用TCP连接,减少握手开销。 - **批处理与合并**: `ProjectAndContainerInfo`的`update_extended_from_request`方法允许一次性批量更新多个字段,减少状态更新的次数。 **本节来源** - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L47-L68) - [agent_project_runner_model.rs](file://crates/shared_types/src/model/agent_project_runner_model.rs) - [config.yml](file://config.yml#L144-L147) - [agent.proto](file://crates/shared_types/proto/agent.proto#L9-L11) ## 数据生命周期保留策略与归档规则 RCoder项目的数据生命周期管理主要通过自动化和配置驱动的策略来实现,侧重于临时性和运行时数据的管理。 ### 数据生命周期 1. **创建 (Creation)**: - 当用户发起`ChatPrompt`请求时,系统检查`project_id`。 - 如果该项目没有活跃的代理,则创建一个新的`ProjectAndAgentInfo`实例,启动`agent_runner`进程,并生成新的`session_id`。 - 代理的生命周期由`AgentLifecycleGuard`管理,其创建标志着代理生命周期的开始。 2. **活跃 (Active)**: - 代理处于`Active`状态,通过`prompt_tx`接收用户提示,并通过`SessionNotify`发送状态更新。 - `last_activity`字段在每次交互时被更新,用于判断代理的活跃度。 3. **终止 (Termination)**: - **正常终止**: 当代理完成任务或用户主动取消时,调用`AgentLifecycleGuard::graceful_stop`。该方法发送取消信号,等待任务退出,然后清理资源(终止子进程、关闭通道)。 - **超时终止**: 配置文件中的`container_ttl_seconds`(默认3600秒)定义了容器的存活时间。后台任务会定期检查超过TTL的代理并自动终止。 - **错误终止**: 如果代理进程崩溃或发生严重错误,`Drop`实现会确保资源被清理。 4. **销毁 (Destruction)**: - `AgentLifecycleGuard`被`drop`时,其`Drop`实现会执行最终的清理工作,确保子进程被杀死,通道被关闭。 - `ProjectAndAgentInfo`记录从`DashMap`中被移除,相关内存被回收。 ### 保留策略与归档规则 - **临时性数据**: 会话(`Session`)和代理(`Agent`)实例被视为临时工作负载。它们的生命周期与用户的开发会话绑定,一旦任务完成或超时,就会被销毁。 - **无长期归档**: 项目当前的设计中,没有明确的机制将聊天记录、生成的代码或会话日志归档到持久化存储(如数据库或文件系统)。所有数据在代理终止后即丢失。 - **配置驱动的保留**: `container_ttl_seconds`是主要的保留策略配置,它强制性地保留了代理实例的最长时间。 - **自动清理**: `docker_config.auto_cleanup`设置为`true`,表明系统会在代理终止后自动清理Docker容器,释放系统资源。 **本节来源** - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L218-L249) - [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L348-L403) - [config.yml](file://config.yml#L160-L161) - [rcoder_default.yml](file://crates/rcoder/src/rcoder_default.yml#L173-L174) ## 数据迁移路径与版本管理 RCoder项目的数据迁移和版本管理主要体现在配置文件和gRPC协议的演进上。 ### 数据迁移路径 - **配置文件迁移**: 从`config.yml`到`rcoder_default.yml`的演变,以及`multi_image_config`的引入,代表了系统配置的演进。迁移路径通常由代码中的默认值和向后兼容逻辑处理。例如,`create_legacy_multi_image_config`函数可以将旧的简单配置转换为新的多镜像配置格式。 - **gRPC协议迁移**: `agent.proto`文件定义了服务间的通信协议。当需要添加新功能(如新的`ProgressEvent`类型)时,会通过添加新的字段或消息来实现,遵循gRPC的向后兼容原则(如使用`optional`关键字)。 - **数据结构演进**: Rust结构体通过添加新字段(通常为`Option`类型)来实现向后兼容。例如,`ChatPrompt`中的`data_source_attachments`是一个后来添加的字段,旧的客户端可以忽略它,而新的服务器可以安全地处理缺失的字段。 ### 版本管理 - **语义化版本控制**: 项目使用`Cargo.toml`进行依赖管理,遵循语义化版本控制(SemVer)。`crates/shared_types`等内部crate的版本号变化反映了API的稳定性。 - **配置版本**: 配置文件本身没有明确的`version`字段,但其结构的变化(如`docker_config`的复杂化)隐式地代表了版本迭代。代码通过检查字段是否存在来处理不同版本的配置。 - **gRPC服务版本**: `agent.proto`中的`package agent;`和`service AgentService`定义了服务的命名空间。未来可以通过创建新的`AgentServiceV2`服务来实现不兼容的API变更。 - **环境变量映射**: `agent-abstraction-layer-design.md`中的JSON配置展示了如何通过模板(如`{MODEL_PROVIDER_API_KEY}`)将不同模型提供商的环境变量映射到代理的启动参数中,这是一种灵活的配置版本管理方式。 **本节来源** - [config.yml](file://config.yml) - [rcoder_default.yml](file://crates/rcoder/src/rcoder_default.yml) - [agent.proto](file://crates/shared_types/proto/agent.proto) - [agent-abstraction-layer-design.md](file://specs/agent-abstraction-layer-design.md#L545-L610)