添加qiming-rcoder模块
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
# HTTP API架构
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs)
|
||||
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.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)
|
||||
- [health_handler.rs](file://crates/agent_runner/src/handler/health_handler.rs)
|
||||
- [agent_status_handler.rs](file://crates/agent_runner/src/handler/agent_status_handler.rs)
|
||||
- [proxy_handler_api.rs](file://crates/agent_runner/src/handler/proxy_handler_api.rs)
|
||||
- [proxy_api.rs](file://crates/agent_runner/src/handler/proxy_api.rs)
|
||||
- [config.rs](file://crates/agent_runner/src/config.rs)
|
||||
- [lib.rs](file://crates/agent_runner/src/lib.rs)
|
||||
- [model.rs](file://crates/agent_runner/src/model.rs)
|
||||
- [mod.rs](file://crates/agent_runner/src/handler/mod.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概述](#架构概述)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
RCoder AI服务API是一个基于ACP(Agent Client Protocol)的AI驱动开发平台,提供完整的AI代理集成解决方案。该系统采用Rust语言构建,基于Axum框架实现高性能HTTP API服务,通过Server-Sent Events(SSE)协议提供实时通信能力。系统支持多种AI代理类型(Codex、Claude、Proxy),并集成了基于Cloudflare Pingora的高性能反向代理服务。API设计遵循RESTful原则,提供清晰的端点划分和完整的OpenAPI文档支持。
|
||||
|
||||
## 项目结构
|
||||
系统采用Rust工作区(workspace)结构,核心功能模块化组织。HTTP API服务主要由`agent_runner` crate实现,该模块负责处理所有HTTP请求、路由分发和状态管理。系统通过清晰的目录结构分离关注点,包括处理器(handler)、中间件(middleware)、代理代理(proxy_agent)、服务(service)和工具(utils)等模块。这种结构化设计提高了代码的可维护性和可扩展性,同时便于团队协作开发。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "crates"
|
||||
subgraph "agent_runner"
|
||||
H[handler]
|
||||
M[middleware]
|
||||
PA[proxy_agent]
|
||||
S[service]
|
||||
U[utils]
|
||||
R[router]
|
||||
C[config]
|
||||
end
|
||||
subgraph "shared_types"
|
||||
ST[共享类型定义]
|
||||
end
|
||||
subgraph "pingora-proxy"
|
||||
PP[Pingora代理服务]
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs)
|
||||
- [config.rs](file://crates/agent_runner/src/config.rs)
|
||||
|
||||
**章节来源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs)
|
||||
- [config.rs](file://crates/agent_runner/src/config.rs)
|
||||
|
||||
## 核心组件
|
||||
系统的核心组件包括基于Axum框架的HTTP服务器、基于DashMap的会话状态管理、基于MPMC通道的异步任务处理机制,以及集成的OpenTelemetry遥测系统。`AppState`结构体作为全局应用状态,封装了会话映射、配置信息、任务发送器和Pingora服务引用等关键数据。系统通过`LocalSet`在独立线程中运行非Send的代理工作器,确保了不同类型代理的兼容性。OpenAPI文档通过utoipa自动生成,提供完整的API描述和交互式Swagger UI界面。
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L1-L232)
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L1-L200)
|
||||
|
||||
## 架构概述
|
||||
系统采用分层架构设计,从下到上分别为基础设施层、服务层、应用层和接口层。基础设施层提供日志、遥测和配置管理;服务层封装核心业务逻辑;应用层处理HTTP请求和响应;接口层暴露REST API和SSE流。系统通过清晰的组件分离和依赖注入,实现了高内聚低耦合的设计目标。Pingora反向代理作为独立的服务组件,与主HTTP服务器并行运行,提供高性能的端口路由和负载均衡能力。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "接口层"
|
||||
A[REST API]
|
||||
B[SSE流]
|
||||
C[Swagger UI]
|
||||
end
|
||||
subgraph "应用层"
|
||||
D[Axum服务器]
|
||||
E[路由分发]
|
||||
F[中间件链]
|
||||
end
|
||||
subgraph "服务层"
|
||||
G[代理管理]
|
||||
H[会话缓存]
|
||||
I[任务调度]
|
||||
end
|
||||
subgraph "基础设施层"
|
||||
J[配置管理]
|
||||
K[日志系统]
|
||||
L[遥测系统]
|
||||
end
|
||||
A --> D
|
||||
B --> D
|
||||
C --> D
|
||||
D --> E
|
||||
E --> F
|
||||
F --> G
|
||||
F --> H
|
||||
F --> I
|
||||
G --> J
|
||||
H --> K
|
||||
I --> L
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L1-L232)
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L1-L200)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 路由设计分析
|
||||
系统基于Axum框架实现RESTful路由设计,通过模块化方式组织API端点。路由配置在`router.rs`文件中集中管理,使用`Router::new()`创建根路由器,并通过`merge()`方法合并多个子路由。API端点按功能分组,包括系统健康检查、聊天交互、代理状态管理和反向代理接口。每个端点通过`route()`方法绑定到相应的处理器函数,并使用`with_state()`方法注入共享的应用状态。OpenAPI文档通过`utoipa`属性宏自动生成,确保API文档与实现保持同步。
|
||||
|
||||
**章节来源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L40-L69)
|
||||
|
||||
#### 路由结构图
|
||||
```mermaid
|
||||
graph TD
|
||||
R[根路由器] --> API[API路由]
|
||||
R --> Proxy[代理API路由]
|
||||
R --> Swagger[Swagger UI]
|
||||
API --> Health[/health]
|
||||
API --> Chat[/chat]
|
||||
API --> Progress[/agent/progress/{session_id}]
|
||||
API --> Cancel[/agent/session/cancel]
|
||||
API --> Status[/agent/status/{project_id}]
|
||||
Proxy --> ProxyStatus[/proxy/status]
|
||||
Proxy --> ProxyStats[/proxy/stats]
|
||||
Proxy --> ProxyConfig[/proxy/config]
|
||||
Proxy --> ProxyPort[/proxy/{port}]
|
||||
Proxy --> ProxyPath[/proxy/{port}/{*path}]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L40-L69)
|
||||
|
||||
### 请求处理流程分析
|
||||
HTTP请求处理流程始于TCP监听器,通过Axum服务器接收请求并应用中间件链。`tracing_middleware`作为核心中间件,负责请求追踪、日志记录和trace_id管理。请求经过路由匹配后,分发到相应的处理器函数。处理器函数从共享状态中获取必要信息,执行业务逻辑,并通过MPMC通道与代理工作器通信。响应结果通过统一的`HttpResult`格式返回,确保API响应的一致性。错误处理通过`AppError`枚举和`IntoResponse` trait实现,提供结构化的错误信息。
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L130-L171)
|
||||
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L72-L130)
|
||||
|
||||
#### 请求处理序列图
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Server as "Axum服务器"
|
||||
participant Middleware as "tracing_middleware"
|
||||
participant Handler as "处理器"
|
||||
participant Agent as "代理工作器"
|
||||
Client->>Server : HTTP请求
|
||||
Server->>Middleware : 应用中间件
|
||||
Middleware->>Middleware : 生成trace_id
|
||||
Middleware->>Middleware : 创建日志span
|
||||
Middleware->>Handler : 调用处理器
|
||||
Handler->>Handler : 验证请求参数
|
||||
Handler->>Handler : 构建ChatPrompt
|
||||
Handler->>Agent : 发送任务请求
|
||||
Agent->>Handler : 返回响应
|
||||
Handler->>Middleware : 返回结果
|
||||
Middleware->>Middleware : 记录响应信息
|
||||
Middleware->>Client : HTTP响应
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L130-L171)
|
||||
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L72-L130)
|
||||
|
||||
### 中间件链分析
|
||||
`tracing_middleware`是系统的核心中间件,负责实现分布式追踪和结构化日志记录。该中间件通过`info_span!`宏创建请求级别的追踪span,包含方法、URI、trace_id等关键信息。trace_id的生成遵循优先级顺序:首先尝试从请求头(x-trace-id、x-request-id等)提取,若不存在则生成新的UUID。中间件使用`instrument`方法将整个请求处理过程包装在span中,确保所有日志都关联到正确的trace上下文。OpenTelemetry集成确保trace信息可以在分布式系统中传播,便于跨服务的性能分析和故障排查。
|
||||
|
||||
**章节来源**
|
||||
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L138)
|
||||
|
||||
#### 中间件处理流程图
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([请求进入]) --> Extract["提取trace_id<br/>从请求头"]
|
||||
Extract --> HasTraceId{存在trace_id?}
|
||||
HasTraceId --> |是| UseExisting["使用现有trace_id"]
|
||||
HasTraceId --> |否| Generate["生成新trace_id"]
|
||||
Generate --> UseExisting
|
||||
UseExisting --> CreateSpan["创建tracing span"]
|
||||
CreateSpan --> Execute["执行请求处理"]
|
||||
Execute --> LogResponse["记录响应信息"]
|
||||
LogResponse --> End([响应返回])
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L138)
|
||||
|
||||
### 处理器模块分析
|
||||
处理器模块采用模块化设计,每个API端点对应独立的处理器文件。`mod.rs`文件作为公共接口,重新导出所有处理器函数。`chat_handler`处理聊天请求,验证输入参数,管理项目工作目录,并通过MPMC通道与代理工作器通信。`agent_session_notification`实现SSE流,为前端提供实时的代理执行进度更新。`health_handler`提供基本的健康检查功能,返回服务状态和时间戳。`agent_status_handler`查询代理状态,返回详细的会话信息和模型配置。所有处理器函数使用`utoipa::path`宏注解,自动生成OpenAPI文档。
|
||||
|
||||
**章节来源**
|
||||
- [mod.rs](file://crates/agent_runner/src/handler/mod.rs#L1-L17)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L320)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L356-L483)
|
||||
- [health_handler.rs](file://crates/agent_runner/src/handler/health_handler.rs#L29-L35)
|
||||
- [agent_status_handler.rs](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L121)
|
||||
|
||||
#### 处理器模块类图
|
||||
```mermaid
|
||||
classDiagram
|
||||
class ChatHandler {
|
||||
+handle_chat(state : Arc~AppState~, request : Json~ChatRequest~) Result~HttpResult~ChatResponse~~, AppError~
|
||||
}
|
||||
class NotificationHandler {
|
||||
+agent_session_notification(params : Path~SessionNotificationParams~) Result~Sse~Stream~, AppError~
|
||||
}
|
||||
class HealthHandler {
|
||||
+health_check() Json~HealthResponse~
|
||||
}
|
||||
class StatusHandler {
|
||||
+agent_status(Path~project_id~) Result~HttpResult~AgentStatusResponse~~, AppError~
|
||||
}
|
||||
ChatHandler --> AppState : "使用"
|
||||
NotificationHandler --> AppState : "使用"
|
||||
StatusHandler --> AppState : "使用"
|
||||
AppState --> DashMap : "包含"
|
||||
AppState --> AppConfig : "包含"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L320)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L356-L483)
|
||||
- [health_handler.rs](file://crates/agent_runner/src/handler/health_handler.rs#L29-L35)
|
||||
- [agent_status_handler.rs](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L121)
|
||||
|
||||
## 依赖分析
|
||||
系统依赖关系清晰,核心依赖包括Axum(HTTP框架)、Tokio(异步运行时)、Serde(序列化)、Tracing(日志和追踪)和Utoipa(OpenAPI文档)。`agent_runner` crate依赖`shared_types` crate获取共享的数据结构和枚举类型,依赖`pingora-proxy` crate实现反向代理功能。配置管理通过Clap实现命令行参数解析,通过Serde YAML实现配置文件加载。日志系统使用Tracing Subscriber,支持文件和控制台双输出,文件按天滚动并保留最近5天的日志。遥测系统集成OpenTelemetry,支持trace上下文传播和分布式追踪。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[agent_runner] --> B[axum]
|
||||
A --> C[tokio]
|
||||
A --> D[serde]
|
||||
A --> E[tracing]
|
||||
A --> F[utoipa]
|
||||
A --> G[shared_types]
|
||||
A --> H[pingora-proxy]
|
||||
A --> I[clap]
|
||||
A --> J[serde_yaml]
|
||||
B --> K[tower]
|
||||
C --> L[tokio-util]
|
||||
E --> M[tracing-subscriber]
|
||||
E --> N[tracing-opentelemetry]
|
||||
M --> O[tracing-appender]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml#L1-L79)
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L1-L232)
|
||||
|
||||
**章节来源**
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml#L1-L79)
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L1-L232)
|
||||
|
||||
## 性能考虑
|
||||
系统在性能方面进行了多项优化。会话状态使用`DashMap`实现,提供高性能的并发访问能力。异步任务通过MPMC通道传递,避免了阻塞操作。SSE流使用`async-stream`库实现,支持高效的异步流处理。日志系统采用非阻塞的`tracing-appender`,确保日志写入不会影响主请求处理流程。Pingora反向代理基于Rust异步I/O构建,提供高性能的代理能力。系统通过`LocalSet`在独立线程中运行代理工作器,避免了Send约束对性能的影响。配置加载采用优先级策略,确保配置解析的高效性。
|
||||
|
||||
## 故障排除指南
|
||||
常见问题包括代理并发请求限制、会话状态不一致和配置加载失败。代理并发请求限制通过在`handle_chat`处理器中检查`PROJECT_AND_AGENT_INFO_MAP`实现,当代理处于活动状态时拒绝新的聊天请求。会话状态不一致问题通过在每次请求时清理旧会话解决,确保状态的纯净性。配置加载失败时系统会自动创建默认配置文件,并提供详细的错误日志。SSE连接问题可以通过检查`SESSION_CACHE`和`create_new_connection`方法的实现来诊断。日志文件位于`logs`目录,按天滚动,便于问题追溯。
|
||||
|
||||
**章节来源**
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L211-L223)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L364-L369)
|
||||
- [config.rs](file://crates/agent_runner/src/config.rs#L117-L131)
|
||||
|
||||
## 结论
|
||||
RCoder AI服务API架构设计合理,采用现代化的Rust技术栈,实现了高性能、高可用的HTTP服务。系统通过清晰的模块划分和依赖管理,提供了良好的可维护性和可扩展性。Axum框架的使用简化了路由和中间件的实现,Tracing和OpenTelemetry的集成提供了强大的可观测性。SSE流的实现为前端提供了实时的代理执行进度更新,增强了用户体验。整体架构充分考虑了性能、可靠性和可维护性,为AI驱动的开发平台提供了坚实的基础。
|
||||
@@ -0,0 +1,296 @@
|
||||
# 中间件链
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs)
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs)
|
||||
- [crates/agent_runner/src/router.rs](file://crates/agent_runner/src/router.rs)
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs)
|
||||
- [Cargo.toml](file://Cargo.toml)
|
||||
- [crates/agent_runner/src/handler/mod.rs](file://crates/agent_runner/src/handler/mod.rs)
|
||||
- [crates/rcoder/src/handler/mod.rs](file://crates/rcoder/src/handler/mod.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [引言](#引言)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 引言
|
||||
本文件聚焦于HTTP API中间件链的设计与实现,重点阐述tracing_middleware的作用机制与在Tower Layer模式下的可复用性,说明如何利用该中间件实现请求级别的上下文追踪、日志记录与性能监控;解释OpenTelemetry集成方式,包括trace ID生成、span生命周期管理以及与外部观测系统的对接;梳理中间件执行顺序及其对请求/响应流的影响;并提供自定义中间件扩展的实践建议及在调试与性能分析中的价值。
|
||||
|
||||
## 项目结构
|
||||
本仓库采用多crate工作区组织,其中与HTTP中间件链最相关的两个服务分别为agent_runner与rcoder。两者均内置了相同的tracing_middleware实现,且在各自main中初始化了Tracing与OpenTelemetry传播器,随后在路由上叠加中间件层以形成中间件链。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "agent_runner"
|
||||
ARMain["main.rs<br/>初始化遥测与传播器"]
|
||||
ARRouter["router.rs<br/>创建Axum路由"]
|
||||
ARMW["middleware/tracing_middleware.rs<br/>Tracing中间件"]
|
||||
end
|
||||
subgraph "rcoder"
|
||||
RMain["main.rs<br/>初始化遥测与传播器"]
|
||||
RRouter["router.rs<br/>创建Axum路由"]
|
||||
RMW["middleware/tracing_middleware.rs<br/>Tracing中间件"]
|
||||
end
|
||||
ARMain --> ARRouter
|
||||
ARRouter --> ARMW
|
||||
RMain --> RRouter
|
||||
RRouter --> RMW
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs#L181-L231)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs#L274-L320)
|
||||
- [crates/agent_runner/src/router.rs](file://crates/agent_runner/src/router.rs#L40-L70)
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs#L52-L84)
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L132-L139)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L132-L139)
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs#L181-L231)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs#L274-L320)
|
||||
- [crates/agent_runner/src/router.rs](file://crates/agent_runner/src/router.rs#L40-L70)
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs#L52-L84)
|
||||
|
||||
## 核心组件
|
||||
- Tracing中间件:负责为每个HTTP请求生成或提取trace_id,创建请求span,记录请求/响应信息,并将trace_id注入到请求扩展中,供后续处理器使用。
|
||||
- 遥测初始化:在main中设置全局TextMapPropagator为TraceContext,初始化tracing订阅器,输出到文件与控制台。
|
||||
- 路由与中间件叠加:通过add_tracing_layer将中间件作为Tower Layer叠加到Axum Router上,形成中间件链。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L139)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L1-L139)
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs#L181-L231)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs#L274-L320)
|
||||
|
||||
## 架构总览
|
||||
下图展示了请求在中间件链中的流转过程,以及与OpenTelemetry的集成点。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Router as "Axum Router"
|
||||
participant MW as "Tracing中间件"
|
||||
participant Handler as "业务处理器"
|
||||
participant Otel as "OpenTelemetry传播器"
|
||||
Client->>Router : "HTTP请求"
|
||||
Router->>MW : "进入中间件链"
|
||||
MW->>MW : "提取/生成trace_id"
|
||||
MW->>Otel : "设置TraceContext传播器"
|
||||
MW->>MW : "创建请求span并记录开始"
|
||||
MW->>Handler : "next.run(req)"
|
||||
Handler-->>MW : "返回响应"
|
||||
MW->>MW : "记录响应状态"
|
||||
MW-->>Router : "返回响应"
|
||||
Router-->>Client : "HTTP响应"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L71-L130)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L71-L130)
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs#L212-L225)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs#L302-L314)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### Tracing中间件类图
|
||||
Tracing中间件以函数式中间件形式实现,提供add_tracing_layer用于将中间件叠加到Axum Router上;内部通过extract_trace_id_from_headers与generate_trace_id实现trace_id策略;通过info_span与tracing::info记录请求/响应事件;通过req.extensions_mut插入trace_id供后续处理器使用。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class TracingMiddleware {
|
||||
+new() TracingMiddleware
|
||||
}
|
||||
class TracingFunctions {
|
||||
+generate_trace_id() String
|
||||
+extract_trace_id_from_headers(headers) Option~String~
|
||||
+tracing_middleware_handler(req, next) Response
|
||||
+add_tracing_layer(router) Router
|
||||
}
|
||||
TracingMiddleware --> TracingFunctions : "封装函数式中间件逻辑"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L12-L139)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L12-L139)
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L139)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L1-L139)
|
||||
|
||||
### 中间件处理流程(序列图)
|
||||
该序列图展示一次请求从进入中间件到返回响应的完整流程,包括trace_id策略、span创建与日志记录。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as "客户端"
|
||||
participant R as "Axum Router"
|
||||
participant T as "Tracing中间件"
|
||||
participant N as "Next(下游处理器)"
|
||||
C->>R : "发起请求"
|
||||
R->>T : "进入中间件"
|
||||
T->>T : "尝试从请求头提取trace_id"
|
||||
alt "未提取到"
|
||||
T->>T : "生成新的trace_id"
|
||||
end
|
||||
T->>T : "创建请求span并记录开始"
|
||||
T->>N : "next.run(req)"
|
||||
N-->>T : "返回响应"
|
||||
T->>T : "记录响应状态"
|
||||
T-->>R : "返回响应"
|
||||
R-->>C : "返回HTTP响应"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L71-L130)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L71-L130)
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L71-L130)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L71-L130)
|
||||
|
||||
### 中间件执行顺序与对请求/响应流的影响
|
||||
- 叠加位置:add_tracing_layer将中间件作为顶层Layer叠加到Router上,因此它会最先拦截请求,最后才返回响应。
|
||||
- 对请求的影响:中间件在进入下游处理器前记录请求开始、注入trace_id到请求扩展;对上游调用方透明,仅增加少量开销。
|
||||
- 对响应的影响:中间件在下游返回后记录响应状态,便于统一观测与排障。
|
||||
- 与OpenTelemetry的关系:main中设置了TraceContextPropagator,使trace_id在分布式链路中可被传播;中间件通过tracing_span与tracing日志记录,形成可观测闭环。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L132-L139)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L132-L139)
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs#L212-L225)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs#L302-L314)
|
||||
|
||||
### OpenTelemetry集成与span生命周期
|
||||
- TraceContext传播器:在main中设置全局TextMapPropagator为TraceContext,确保trace_id在跨进程/服务间传播。
|
||||
- span创建与记录:中间件创建“http_request”与“http_request_processing”两类span,分别用于请求级追踪与处理阶段记录。
|
||||
- 日志与span关联:通过tracing::info与info_span,将trace_id写入日志字段,便于与span关联检索。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs#L212-L225)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs#L302-L314)
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L85-L124)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L85-L124)
|
||||
|
||||
### 外部观测系统对接
|
||||
- 日志输出:main中配置tracing_subscriber输出到文件与控制台,日志为JSON格式,便于后续导入ELK/Promtail等系统。
|
||||
- trace ID与span:通过中间件与传播器,trace_id贯穿请求全链路,可与Jaeger/Tempo等分布式追踪系统对接。
|
||||
- 指标采集:rcoder还集成了Pingora代理,可通过其stats接口获取真实后端指标,结合日志与trace可形成端到端观测。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs#L190-L210)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs#L283-L301)
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs#L68-L84)
|
||||
|
||||
### 自定义中间件扩展建议
|
||||
- 设计原则
|
||||
- 保持无状态与纯函数式:中间件应尽量避免持有可变共享状态,减少竞态与副作用。
|
||||
- 明确职责边界:每个中间件专注单一职责(鉴权、限流、日志、追踪等),通过Tower Layer组合。
|
||||
- 顺序敏感性:将更通用的中间件置于外层,将更具体的中间件置于内层;例如鉴权/限流在外层,业务处理器在内层。
|
||||
- 实现要点
|
||||
- 使用axum::middleware::from_fn或实现tower::Layer,将中间件以Layer形式叠加到Router。
|
||||
- 在进入下游前记录关键信息(如trace_id、用户标识、请求参数摘要),在返回后记录响应状态与耗时。
|
||||
- 通过req.extensions_mut传递上下文数据,避免全局状态污染。
|
||||
- 调试与性能分析价值
|
||||
- trace_id串联:便于跨服务定位问题,快速回溯请求路径。
|
||||
- 统一日志字段:统一的trace_id与span字段,便于日志聚合与检索。
|
||||
- 性能瓶颈定位:结合响应状态与日志时间戳,识别慢请求与异常路径。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L132-L139)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L132-L139)
|
||||
|
||||
## 依赖关系分析
|
||||
- 依赖组件
|
||||
- axum:HTTP框架,提供Router、Request、Response、Next等。
|
||||
- tower/tower-http:中间件与服务抽象,支持Layer叠加。
|
||||
- tracing/tracing-opentelemetry:日志与OpenTelemetry集成。
|
||||
- opentelemetry/opentelemetry_sdk:SDK与传播器。
|
||||
- uuid:生成trace_id。
|
||||
- 关键依赖关系
|
||||
- main中设置TraceContextPropagator,为后续中间件与OpenTelemetry提供传播基础。
|
||||
- 中间件通过tracing与tracing_opentelemetry记录span与日志。
|
||||
- Router通过add_tracing_layer叠加中间件,形成Tower Layer链。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Cargo["Cargo.toml 依赖声明"] --> Axum["axum"]
|
||||
Cargo --> Tower["tower / tower-http"]
|
||||
Cargo --> Tracing["tracing / tracing-opentelemetry"]
|
||||
Cargo --> Otel["opentelemetry / opentelemetry_sdk"]
|
||||
Cargo --> Uuid["uuid"]
|
||||
ARMain["agent_runner/main.rs"] --> Otel
|
||||
RMain["rcoder/main.rs"] --> Otel
|
||||
ARMW["agent_runner/tracing_middleware.rs"] --> Tracing
|
||||
RMW["rcoder/tracing_middleware.rs"] --> Tracing
|
||||
ARRouter["agent_runner/router.rs"] --> Axum
|
||||
RRouter["rcoder/router.rs"] --> Axum
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [Cargo.toml](file://Cargo.toml#L59-L105)
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs#L212-L225)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs#L302-L314)
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L1-L139)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L1-L139)
|
||||
- [crates/agent_runner/src/router.rs](file://crates/agent_runner/src/router.rs#L40-L70)
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs#L52-L84)
|
||||
|
||||
章节来源
|
||||
- [Cargo.toml](file://Cargo.toml#L59-L105)
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs#L212-L225)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs#L302-L314)
|
||||
|
||||
## 性能考量
|
||||
- 中间件开销:中间件在请求进入与返回时各做一次日志记录与span创建,开销极低,适合在生产环境长期开启。
|
||||
- trace_id生成:使用UUID v4简单格式,长度固定,生成成本低。
|
||||
- 日志落盘:按天滚动与保留策略,避免日志膨胀;JSON格式利于外部系统解析。
|
||||
- 观测成本:trace_id与span字段统一,便于日志聚合与检索,但需关注日志量与存储成本。
|
||||
|
||||
## 故障排查指南
|
||||
- trace_id缺失
|
||||
- 检查请求头是否携带trace_id或x-request-id等常见头;若无则中间件会自动生成。
|
||||
- 确认main中已设置TraceContextPropagator,确保trace_id在跨服务传播。
|
||||
- 日志未输出或格式异常
|
||||
- 检查tracing_subscriber初始化与EnvFilter配置;确认文件appender路径与权限。
|
||||
- 响应异常
|
||||
- 通过中间件记录的trace_id在日志中定位具体请求,结合span层级排查下游处理器异常。
|
||||
- 与外部观测系统对接
|
||||
- 确保OpenTelemetry SDK与Exporter配置正确;trace_id字段与span字段一致,便于检索。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L49-L69)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L49-L69)
|
||||
- [crates/agent_runner/src/main.rs](file://crates/agent_runner/src/main.rs#L190-L210)
|
||||
- [crates/rcoder/src/main.rs](file://crates/rcoder/src/main.rs#L283-L301)
|
||||
|
||||
## 结论
|
||||
本项目通过Tower Layer模式将Tracing中间件以可复用的方式叠加到Axum Router上,实现了请求级上下文追踪、统一日志记录与性能监控。OpenTelemetry传播器在main中初始化,配合中间件的span与日志,形成了从请求入口到响应返回的完整可观测闭环。该设计易于扩展,可按需叠加更多中间件以满足安全、限流、审计等需求,并在调试与性能分析中具有显著价值。
|
||||
|
||||
## 附录
|
||||
- 中间件叠加位置
|
||||
- agent_runner:在路由创建后通过add_tracing_layer叠加。
|
||||
- rcoder:同样在路由创建后通过add_tracing_layer叠加。
|
||||
- 路由与处理器
|
||||
- 两个服务的router.rs均定义了API路由与代理路由,并通过with_state注入应用状态。
|
||||
- Handler模块
|
||||
- 两个服务的handler/mod.rs导出了各自的处理器模块,供路由绑定。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs#L132-L139)
|
||||
- [crates/rcoder/src/middleware/tracing_middleware.rs](file://crates/rcoder/src/middleware/tracing_middleware.rs#L132-L139)
|
||||
- [crates/agent_runner/src/router.rs](file://crates/agent_runner/src/router.rs#L40-L70)
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs#L52-L84)
|
||||
- [crates/agent_runner/src/handler/mod.rs](file://crates/agent_runner/src/handler/mod.rs#L1-L17)
|
||||
- [crates/rcoder/src/handler/mod.rs](file://crates/rcoder/src/handler/mod.rs#L1-L19)
|
||||
@@ -0,0 +1,334 @@
|
||||
# 请求处理流程
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs)
|
||||
- [agent_status_handler.rs](file://crates/agent_runner/src/handler/agent_status_handler.rs)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs)
|
||||
- [agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs)
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.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)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.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_response.rs](file://crates/shared_types/src/model/chat_response.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
本文件深入解析 RCoder Agent Runner 服务的 HTTP API 请求处理生命周期,重点覆盖以下方面:
|
||||
- 从请求进入路由到最终响应返回的完整链路
|
||||
- chat_handler、agent_status_handler、agent_session_notification、agent_cancel_handler 等核心处理器的实现逻辑
|
||||
- 请求体解析、服务调用(container_manager 或 agent_runner)、响应构造的细节
|
||||
- SSE 流式响应在进度通知中的应用机制
|
||||
- 典型请求处理链路的时序图,展示数据在 handler、service 与 proxy_agent 之间的流转
|
||||
- 错误处理模式与状态码映射策略
|
||||
|
||||
## 项目结构
|
||||
Agent Runner 采用模块化组织,核心模块包括:
|
||||
- handler:HTTP 路由与处理器
|
||||
- proxy_agent:ACPI 协议代理与会话管理
|
||||
- service:会话缓存与消息推送
|
||||
- model:共享模型与错误类型
|
||||
- router:Axum 路由注册与 OpenAPI 文档
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "HTTP 层"
|
||||
R["Router<br/>注册路由"]
|
||||
CH["chat_handler<br/>POST /chat"]
|
||||
ASH["agent_status_handler<br/>GET /agent/status/{project_id}"]
|
||||
ASN["agent_session_notification<br/>GET /agent/progress/{session_id}<br/>SSE"]
|
||||
AC["agent_cancel_handler<br/>POST /agent/session/cancel"]
|
||||
end
|
||||
subgraph "业务层"
|
||||
PA["proxy_agent<br/>ACPI 代理与会话管理"]
|
||||
SVC["service<br/>会话缓存与消息推送"]
|
||||
MOD["model<br/>共享模型与错误类型"]
|
||||
end
|
||||
R --> CH
|
||||
R --> ASH
|
||||
R --> ASN
|
||||
R --> AC
|
||||
CH --> PA
|
||||
CH --> SVC
|
||||
ASH --> PA
|
||||
ASH --> SVC
|
||||
AC --> PA
|
||||
AC --> SVC
|
||||
PA --> SVC
|
||||
SVC --> ASN
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L41-L70)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L321)
|
||||
- [agent_status_handler.rs](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L356-L484)
|
||||
- [agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs#L110-L258)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L200)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
|
||||
章节来源
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L41-L70)
|
||||
|
||||
## 核心组件
|
||||
- 路由与状态
|
||||
- AppState:持有会话映射、本地任务发送器、Pingora 代理服务引用
|
||||
- 路由注册:/health、/chat、/agent/progress/{session_id}、/agent/session/cancel、/agent/status/{project_id}、/proxy/*
|
||||
- 处理器
|
||||
- chat_handler:解析 ChatRequest,校验参数,生成或复用 project_id 与 session_id,构建 ChatPrompt,发送到本地任务通道,等待 oneshot 响应并返回 HttpResult
|
||||
- agent_status_handler:查询 PROJECT_AND_AGENT_INFO_MAP,返回 AgentStatusResponse
|
||||
- agent_session_notification:建立 SSE 连接,推送 UnifiedSessionMessage,支持心跳与取消
|
||||
- agent_cancel_handler:通过 cancel_tx 发送取消通知,清理 SSE 连接与缓存
|
||||
- 代理与会话
|
||||
- proxy_agent:维护 PROJECT_AND_AGENT_INFO_MAP,封装 ACP 连接信息,启动代理服务,转发 session_notification
|
||||
- channel_utils:通用的 Prompt/Cancellation 处理任务,负责状态更新、消息推送与超时保护
|
||||
- session_cache:全局 SESSION_CACHE,RingBuffer 缓冲与实时推送,支持连接级取消令牌与显式关闭
|
||||
|
||||
章节来源
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L25-L70)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L321)
|
||||
- [agent_status_handler.rs](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L356-L484)
|
||||
- [agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs#L110-L258)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L200)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
|
||||
## 架构总览
|
||||
整体架构围绕“请求-代理-通知”三段式展开:
|
||||
- 请求阶段:Axum 路由将 HTTP 请求交由对应 handler 解析与校验
|
||||
- 代理阶段:handler 将 ChatPrompt 通过本地任务通道发送给 agent_worker,后者启动 ACPI 代理并发送 Prompt
|
||||
- 通知阶段:代理通过 session_notification 回调,经由 push_session_update 推送到 SESSION_CACHE,SSE 连接从 SESSION_CACHE 拉取并推送至客户端
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as "客户端"
|
||||
participant H as "chat_handler"
|
||||
participant W as "agent_worker"
|
||||
participant P as "ACPI 代理"
|
||||
participant S as "SESSION_CACHE"
|
||||
participant N as "agent_session_notification"
|
||||
C->>H : POST /chat
|
||||
H->>H : 校验参数/生成 project_id/session_id/request_id
|
||||
H->>W : 发送 LocalSetAgentRequest(含 ChatPrompt)
|
||||
W->>P : 启动代理并发送 Prompt
|
||||
P-->>W : 返回 ChatPromptResponse
|
||||
W-->>H : oneshot 响应
|
||||
H-->>C : HttpResult 成功/错误
|
||||
C->>N : GET /agent/progress/{session_id}
|
||||
N->>S : 创建/获取 SessionData 并建立连接
|
||||
P-->>S : session_notification -> 推送 UnifiedSessionMessage
|
||||
S-->>N : 拉取消息并转为SSE事件
|
||||
N-->>C : 事件流推送(progress_start/end/updates/heartbeat)
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L321)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L164-L200)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L92-L230)
|
||||
- [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#L356-L484)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### chat_handler:聊天请求处理
|
||||
- 输入解析:Json<ChatRequest>,包含 prompt、project_id、session_id、attachments、data_source_attachments、model_provider、request_id
|
||||
- 参数校验:prompt 非空校验
|
||||
- 项目与会话管理:
|
||||
- 若未提供 project_id,自动生成 UUID(去除横杠)并创建 ./project_workspace/{project_id}
|
||||
- 若 Agent 正处于 Active 状态,拒绝并发请求
|
||||
- 若提供了 session_id,移除该 session;否则清空该项目下的所有 session
|
||||
- 任务构建:根据 model_provider 自动选择 AgentType,构建 ChatPrompt,并通过 LocalSetAgentRequest.new 生成 oneshot 通道
|
||||
- 任务提交:通过 AppState.local_task_sender 发送 LocalSetAgentRequest
|
||||
- 响应构造:等待 chat_prompt_rx.await,若 error 非空返回 PROMPT001,否则返回 HttpResult.success,包含 project_id、session_id、request_id
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进入 handle_chat"]) --> Validate["校验 prompt 非空"]
|
||||
Validate --> GenPID{"是否提供 project_id?"}
|
||||
GenPID --> |否| CreateWS["生成 project_id 并创建工作目录"]
|
||||
GenPID --> |是| UsePID["使用请求中的 project_id"]
|
||||
CreateWS --> CheckAgent["检查 Agent 是否 Active"]
|
||||
UsePID --> CheckAgent
|
||||
CheckAgent --> |Active| Reject["返回并发请求错误"]
|
||||
CheckAgent --> |Idle| CleanSess["清理旧 session按 session_id 或按 project_id"]
|
||||
CleanSess --> BuildPrompt["构建 ChatPrompt含 attachments、data_source_attachments、model_provider"]
|
||||
BuildPrompt --> SendTask["发送 LocalSetAgentRequest 到本地任务通道"]
|
||||
SendTask --> AwaitResp{"等待 oneshot 响应"}
|
||||
AwaitResp --> |error 非空| RespErr["返回 PROMPT001 错误"]
|
||||
AwaitResp --> |成功| RespOK["返回 HttpResult.success包含 project_id/session_id/request_id"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L321)
|
||||
|
||||
章节来源
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L321)
|
||||
|
||||
### agent_status_handler:Agent 状态查询
|
||||
- 路径参数:project_id
|
||||
- 参数校验:project_id 非空
|
||||
- 查询逻辑:从 PROJECT_AND_AGENT_INFO_MAP 获取 Agent 信息
|
||||
- 若存在:返回包含 is_alive=true、session_id、status、last_activity、created_at、model_provider 的 AgentStatusResponse
|
||||
- 若不存在:返回 is_alive=false 的简化响应
|
||||
|
||||
章节来源
|
||||
- [agent_status_handler.rs](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L22-L39)
|
||||
|
||||
### agent_session_notification:SSE 实时进度
|
||||
- 路径参数:session_id
|
||||
- 连接建立:为 session_id 创建新的 SessionData,插入 SESSION_CACHE
|
||||
- 连接管理:
|
||||
- 立即发送 heartbeat 事件,随后每 30 秒发送一次心跳
|
||||
- 使用 CancellationToken 监听取消信号:当新连接建立或用户取消任务时,旧连接自然断开
|
||||
- 当 channel 发送端被 drop 时,recv() 返回 None,连接自然断开
|
||||
- 事件类型映射:根据 UnifiedSessionMessage.message_type 动态设置事件名(prompt_start、prompt_end、各类 agent_session_update、heartbeat)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as "客户端"
|
||||
participant H as "agent_session_notification"
|
||||
participant S as "SESSION_CACHE"
|
||||
participant W as "SessionWorker"
|
||||
participant P as "ACPI 代理"
|
||||
C->>H : GET /agent/progress/{session_id}
|
||||
H->>S : SessionData : : new + 插入 SESSION_CACHE
|
||||
H->>S : create_new_connection(1000)
|
||||
H-->>C : 发送 initial heartbeat 事件
|
||||
loop 心跳/消息循环
|
||||
alt 收到 CancellationToken
|
||||
H-->>C : 断开旧连接
|
||||
else 收到 UnifiedSessionMessage
|
||||
H-->>C : 事件流推送按 message_type 映射
|
||||
else 心跳定时器
|
||||
H-->>C : 发送 heartbeat 事件
|
||||
end
|
||||
end
|
||||
note over P,S : 代理通过 session_notification 推送消息到 SESSION_CACHE
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L356-L484)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L142-L207)
|
||||
|
||||
章节来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L356-L484)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
|
||||
### agent_cancel_handler:任务取消
|
||||
- 查询参数:project_id(可选 session_id)
|
||||
- 逻辑:
|
||||
- 若未提供 session_id,从 PROJECT_AND_AGENT_INFO_MAP 中解析
|
||||
- 通过 cancel_tx 发送 CancelNotificationRequest,并等待响应
|
||||
- 成功后:主动关闭 SSE 连接(close_current_connection),移除 SESSION_CACHE 条目
|
||||
- 未找到活跃连接:同样主动关闭并清理 SESSION_CACHE
|
||||
- 返回:HttpResult.success(CancelResponse{success, session_id})
|
||||
|
||||
章节来源
|
||||
- [agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs#L110-L258)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L200)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L91)
|
||||
|
||||
### 代理与会话管理(proxy_agent 与 channel_utils)
|
||||
- AcpAgentService:根据 AgentType 启动 Claude 或 Codex 代理服务,返回 AcpConnectionInfo(包含 session_id、prompt_tx、cancel_tx、stop_handle)
|
||||
- AcpAgentClient:实现 agent_client_protocol::Client,处理权限请求、文件读写、session_notification 回调
|
||||
- session_notification:将 AgentSessionUpdate 包装为 SessionNotify,调用 push_session_update 推送
|
||||
- request_id 优先从 SessionNotification.meta 获取,否则通过 PROJECT_AND_AGENT_INFO_MAP + SESSION_REQUEST_CONTEXT 解析
|
||||
- channel_utils:
|
||||
- spawn_prompt_handler_for_agent:监听 prompt_rx,更新 Agent 状态为 Active,推送 SessionPromptStart,调用 Agent.prompt,推送 SessionPromptEnd 或 SessionPromptError
|
||||
- spawn_cancel_handler_for_agent:监听 cancel_rx,调用 Agent.cancel,超时保护,完成后将 Agent 状态恢复为 Idle
|
||||
|
||||
章节来源
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L200)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
|
||||
## 依赖关系分析
|
||||
- handler 依赖
|
||||
- chat_handler 依赖 AppState(sessions、local_task_sender)、ChatPromptBuilder、AgentType、HttpResult/AppError
|
||||
- agent_status_handler 依赖 PROJECT_AND_AGENT_INFO_MAP
|
||||
- agent_session_notification 依赖 SESSION_CACHE、UnifiedSessionMessage
|
||||
- agent_cancel_handler 依赖 PROJECT_AND_AGENT_INFO_MAP、CancelNotificationRequest
|
||||
- proxy_agent 依赖
|
||||
- AcpAgentService/AcpAgentClient、PROJECT_AND_AGENT_INFO_MAP、AcpConnectionInfo
|
||||
- service 依赖
|
||||
- SESSION_CACHE、PROJECT_SESSION_MAP、SessionData、SessionWorker、UnifiedSessionMessage
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
CH["chat_handler"] --> PA["proxy_agent"]
|
||||
CH --> SVC["service"]
|
||||
ASH["agent_status_handler"] --> PA
|
||||
ASN["agent_session_notification"] --> SVC
|
||||
AC["agent_cancel_handler"] --> PA
|
||||
AC --> SVC
|
||||
PA --> SVC
|
||||
SVC --> ASN
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L321)
|
||||
- [agent_status_handler.rs](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L356-L484)
|
||||
- [agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs#L110-L258)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L200)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
|
||||
章节来源
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L41-L70)
|
||||
|
||||
## 性能考量
|
||||
- 会话缓存与推送
|
||||
- SessionData 使用 mpsc::channel 与 CancellationToken 管理连接,避免命令传递的额外开销
|
||||
- SessionWorker 使用 RingBuffer 缓冲消息,实时推送至当前连接,丢弃心跳消息以节省带宽
|
||||
- 通过 PROJECT_SESSION_MAP 确保 project_id 仅对应一个活跃 session,避免旧数据污染
|
||||
- 取消与断开
|
||||
- CancellationToken 与显式 drop Sender 实现快速断开,减少资源占用
|
||||
- 取消超时保护(默认 10 秒),避免阻塞
|
||||
- 并发控制
|
||||
- chat_handler 在 Agent Active 时拒绝并发请求,避免资源争用
|
||||
- 通过 oneshot 通道保证 ChatPromptResponse 的顺序性与一致性
|
||||
|
||||
[本节为通用性能讨论,不直接分析具体文件]
|
||||
|
||||
## 故障排查指南
|
||||
- 常见错误与状态码映射
|
||||
- 参数错误:chat_handler 对 prompt 校验失败返回 400(AppError::Generic -> INTERNAL_SERVER_ERROR),但 OpenAPI 注释中明确 400 场景
|
||||
- 并发请求:Agent Active 时返回 409(自定义错误码),提示“Agent正在执行任务,请等待当前任务完成后再发送新请求”
|
||||
- 内部错误:AppError::AnyhowError/IOError -> 500(IntoResponse 默认 INTERNAL_SERVER_ERROR)
|
||||
- SSE 连接异常:心跳丢失、连接断开、取消后清理不彻底
|
||||
- 排查步骤
|
||||
- chat_handler:确认 project_id 生成与工作目录创建、session 清理逻辑、LocalSetAgentRequest 发送与 oneshot 响应
|
||||
- agent_session_notification:检查 SessionData::new、create_new_connection、CancellationToken 与心跳定时器
|
||||
- agent_cancel_handler:确认 cancel_tx 发送、响应等待、SSE 连接关闭与 SESSION_CACHE 清理
|
||||
- proxy_agent:核对 PROJECT_AND_AGENT_INFO_MAP 更新、AcpAgentService 启动、session_notification 推送
|
||||
|
||||
章节来源
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L321)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L356-L484)
|
||||
- [agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs#L110-L258)
|
||||
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
|
||||
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L1-L103)
|
||||
|
||||
## 结论
|
||||
本文件梳理了 RCoder Agent Runner 的 HTTP API 请求处理全生命周期,明确了 chat_handler、agent_status_handler、agent_session_notification、agent_cancel_handler 的职责边界与协作关系。通过 SSE 实时推送与会话缓存机制,系统实现了低延迟、高可靠的状态反馈;通过代理层与通道工具的解耦设计,保障了并发安全与可扩展性。建议在生产环境中关注:
|
||||
- 参数校验与错误映射的一致性
|
||||
- SSE 连接的健壮性与自动重连策略
|
||||
- 取消超时与资源回收的可观测性
|
||||
- 代理启动失败的兜底处理与告警
|
||||
@@ -0,0 +1,312 @@
|
||||
# 路由配置
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs)
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [handler/mod.rs](file://crates/agent_runner/src/handler/mod.rs)
|
||||
- [middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs)
|
||||
- [health_handler.rs](file://crates/agent_runner/src/handler/health_handler.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)
|
||||
- [proxy_api.rs](file://crates/agent_runner/src/handler/proxy_api.rs)
|
||||
- [router.rs](file://crates/rcoder/src/router.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [项目结构](#项目结构)
|
||||
2. [核心路由注册机制](#核心路由注册机制)
|
||||
3. [模块化路由组织结构](#模块化路由组织结构)
|
||||
4. [全局中间件应用](#全局中间件应用)
|
||||
5. [路由层级划分逻辑](#路由层级划分逻辑)
|
||||
6. [动态路由参数处理](#动态路由参数处理)
|
||||
7. [错误传播模式](#错误传播模式)
|
||||
8. [API端点详细说明](#api端点详细说明)
|
||||
9. [OpenAPI文档集成](#openapi文档集成)
|
||||
|
||||
## 项目结构
|
||||
|
||||
本项目采用模块化设计,HTTP API路由配置主要分布在`crates/agent_runner`和`crates/rcoder`两个核心模块中。路由配置的核心文件位于`src/router.rs`,通过Axum框架实现路由注册。处理器函数分布在`src/handler`目录下,按功能模块组织。中间件定义在`src/middleware`目录中,用于处理全局请求拦截和日志追踪。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[HTTP API路由系统] --> B[路由注册]
|
||||
A --> C[处理器模块]
|
||||
A --> D[中间件]
|
||||
A --> E[应用状态]
|
||||
B --> F[router.rs]
|
||||
C --> G[handler/mod.rs]
|
||||
D --> H[middleware/tracing_middleware.rs]
|
||||
E --> I[AppState结构]
|
||||
F --> J[create_router函数]
|
||||
G --> K[health_handler]
|
||||
G --> L[chat_handler]
|
||||
G --> M[agent_session_notification]
|
||||
G --> N[proxy_api]
|
||||
H --> O[tracing_middleware_handler]
|
||||
I --> P[sessions]
|
||||
I --> Q[config]
|
||||
I --> R[local_task_sender]
|
||||
I --> S[pingora_service]
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs)
|
||||
- [handler/mod.rs](file://crates/agent_runner/src/handler/mod.rs)
|
||||
- [middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs)
|
||||
|
||||
**节源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs)
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
|
||||
## 核心路由注册机制
|
||||
|
||||
基于Axum框架的路由注册机制通过`create_router`函数实现,该函数接收应用状态并返回配置好的Router实例。路由注册采用链式调用方式,将不同功能的路由分组后合并到主路由中。
|
||||
|
||||
路由注册的核心流程如下:
|
||||
1. 创建API路由组,包含健康检查、聊天、代理会话通知等核心接口
|
||||
2. 创建代理API路由组,提供Pingora反向代理相关的状态查询接口
|
||||
3. 将各路由组合并到主路由中
|
||||
4. 集成Swagger UI路由,提供API文档界面
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant App as 应用启动
|
||||
participant Router as 路由创建
|
||||
participant API as API路由组
|
||||
participant Proxy as 代理API路由组
|
||||
participant Swagger as Swagger UI
|
||||
App->>Router : create_router(state)
|
||||
Router->>API : 创建API路由组
|
||||
API->>API : route("/health", get(health_check))
|
||||
API->>API : route("/chat", post(handle_chat))
|
||||
API->>API : route("/agent/progress/{session_id}", get(agent_session_notification))
|
||||
API->>Router : 返回API路由组
|
||||
Router->>Proxy : 创建代理API路由组
|
||||
Proxy->>Proxy : route("/proxy/status", get(proxy_status))
|
||||
Proxy->>Proxy : route("/proxy/stats", get(proxy_stats))
|
||||
Proxy->>Router : 返回代理API路由组
|
||||
Router->>Swagger : 创建Swagger UI路由
|
||||
Swagger->>Router : 返回Swagger路由
|
||||
Router->>App : 合并所有路由并返回
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L40-L70)
|
||||
|
||||
**节源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L40-L70)
|
||||
|
||||
## 模块化路由组织结构
|
||||
|
||||
路由处理器采用模块化组织结构,通过`handler/mod.rs`文件统一导出所有处理器模块。这种设计实现了关注点分离,使代码结构更加清晰和易于维护。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[handler/mod.rs] --> B[agent_cancel_handler]
|
||||
A --> C[agent_session_notification]
|
||||
A --> D[chat_handler]
|
||||
A --> E[agent_status_handler]
|
||||
A --> F[health_handler]
|
||||
A --> G[proxy_api]
|
||||
A --> H[proxy_handler_api]
|
||||
B --> I[agent_session_cancel]
|
||||
C --> J[agent_session_notification]
|
||||
D --> K[handle_chat]
|
||||
E --> L[agent_status]
|
||||
F --> M[health_check]
|
||||
G --> N[proxy_status]
|
||||
G --> O[proxy_stats]
|
||||
G --> P[proxy_config]
|
||||
G --> Q[proxy_to_port]
|
||||
G --> R[proxy_to_port_with_path]
|
||||
G --> S[proxy_with_query_params]
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [handler/mod.rs](file://crates/agent_runner/src/handler/mod.rs)
|
||||
|
||||
**节源**
|
||||
- [handler/mod.rs](file://crates/agent_runner/src/handler/mod.rs)
|
||||
|
||||
## 全局中间件应用
|
||||
|
||||
通过Layer堆叠机制应用全局中间件,实现请求的统一处理。主要中间件包括追踪中间件,用于记录请求日志和生成trace_id。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[HTTP请求] --> B[Tracing中间件]
|
||||
B --> C[提取或生成trace_id]
|
||||
C --> D[创建日志span]
|
||||
D --> E[记录请求开始]
|
||||
E --> F[执行后续处理器]
|
||||
F --> G[记录响应完成]
|
||||
G --> H[返回响应]
|
||||
subgraph 中间件处理流程
|
||||
C
|
||||
D
|
||||
E
|
||||
F
|
||||
G
|
||||
end
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs)
|
||||
|
||||
**节源**
|
||||
- [middleware/tracing_middleware.rs](file://crates/agent_runner/src/middleware/tracing_middleware.rs)
|
||||
|
||||
## 路由层级划分逻辑
|
||||
|
||||
路由系统采用清晰的层级划分逻辑,将公共接口与代理专用接口分离。这种设计提高了系统的可维护性和安全性。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[主路由] --> B[API路由组]
|
||||
A --> C[代理API路由组]
|
||||
A --> D[Swagger UI路由]
|
||||
B --> E[公共接口]
|
||||
E --> F[/health]
|
||||
E --> G[/chat]
|
||||
E --> H[/agent/progress/{session_id}]
|
||||
E --> I[/agent/session/cancel]
|
||||
E --> J[/agent/status/{project_id}]
|
||||
C --> K[代理专用接口]
|
||||
K --> L[/proxy/status]
|
||||
K --> M[/proxy/stats]
|
||||
K --> N[/proxy/config]
|
||||
K --> O[/proxy/{port}]
|
||||
K --> P[/proxy/{port}/{*path}]
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L42-L69)
|
||||
|
||||
**节源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L42-L69)
|
||||
|
||||
## 动态路由参数处理
|
||||
|
||||
动态路由参数通过Axum的路径参数机制处理,支持路径参数和通配符参数。系统能够正确解析和验证动态路由参数。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[接收到请求] --> B{路径匹配}
|
||||
B --> |/agent/progress/{session_id}| C[提取session_id]
|
||||
B --> |/proxy/{port}| D[提取port]
|
||||
B --> |/proxy/{port}/{*path}| E[提取port和path]
|
||||
B --> |其他路径| F[返回404]
|
||||
C --> G[验证session_id]
|
||||
G --> H[调用agent_session_notification]
|
||||
D --> I[验证port]
|
||||
I --> J[调用proxy_to_port]
|
||||
E --> K[验证port和path]
|
||||
K --> L[调用proxy_to_port_with_path]
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L46-L47)
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L59-L63)
|
||||
|
||||
**节源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L46-L63)
|
||||
|
||||
## 错误传播模式
|
||||
|
||||
系统采用统一的错误传播模式,通过Result类型传递错误信息。错误处理遵循以下原则:
|
||||
|
||||
1. 处理器函数返回Result类型,包含成功值或错误
|
||||
2. 使用AppError类型封装各种错误情况
|
||||
3. 错误信息包含错误代码和描述
|
||||
4. 通过HttpResult包装器提供一致的响应格式
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> 请求处理
|
||||
请求处理 --> 验证输入
|
||||
验证输入 --> |有效| 业务逻辑
|
||||
验证输入 --> |无效| 返回验证错误
|
||||
业务逻辑 --> |成功| 构建成功响应
|
||||
业务逻辑 --> |失败| 构建错误响应
|
||||
构建成功响应 --> 返回响应
|
||||
构建错误响应 --> 返回响应
|
||||
返回响应 --> [*]
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L179)
|
||||
- [model.rs](file://crates/agent_runner/src/model.rs)
|
||||
|
||||
**节源**
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L179)
|
||||
|
||||
## API端点详细说明
|
||||
|
||||
### 健康检查端点
|
||||
- 路径: `/health`
|
||||
- 方法: GET
|
||||
- 功能: 检查服务的健康状态
|
||||
- 响应: 返回服务状态、时间戳和服务名称
|
||||
|
||||
### 聊天端点
|
||||
- 路径: `/chat`
|
||||
- 方法: POST
|
||||
- 功能: 发送聊天消息并获取AI响应
|
||||
- 请求体: 包含prompt、project_id、session_id等信息
|
||||
- 响应: 返回项目ID和会话ID
|
||||
|
||||
### 代理会话通知端点
|
||||
- 路径: `/agent/progress/{session_id}`
|
||||
- 方法: GET
|
||||
- 功能: 通过SSE协议实时推送AI代理执行进度
|
||||
- 参数: session_id
|
||||
- 响应: SSE流,包含各种类型的消息事件
|
||||
|
||||
### 代理API端点
|
||||
- 路径: `/proxy/status`, `/proxy/stats`, `/proxy/config`等
|
||||
- 方法: GET
|
||||
- 功能: 提供Pingora反向代理的状态、统计和配置信息
|
||||
- 参数: port, path等动态参数
|
||||
|
||||
**节源**
|
||||
- [health_handler.rs](file://crates/agent_runner/src/handler/health_handler.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)
|
||||
- [proxy_api.rs](file://crates/agent_runner/src/handler/proxy_api.rs)
|
||||
|
||||
## OpenAPI文档集成
|
||||
|
||||
系统集成了OpenAPI文档功能,通过utoipa和utoipa_swagger_ui crate提供API文档界面。文档包含所有API端点的详细描述、请求参数、响应格式和示例。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[OpenAPI文档] --> B[API端点]
|
||||
A --> C[组件定义]
|
||||
A --> D[标签]
|
||||
A --> E[信息]
|
||||
B --> F[health_check]
|
||||
B --> G[handle_chat]
|
||||
B --> H[agent_session_notification]
|
||||
B --> I[proxy_status]
|
||||
B --> J[proxy_stats]
|
||||
B --> K[proxy_config]
|
||||
C --> L[请求体]
|
||||
C --> M[响应体]
|
||||
C --> N[参数]
|
||||
D --> O[system]
|
||||
D --> P[chat]
|
||||
D --> Q[agent]
|
||||
D --> R[proxy]
|
||||
E --> S[描述]
|
||||
E --> T[标题]
|
||||
E --> U[版本]
|
||||
E --> V[许可证]
|
||||
E --> W[联系人]
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L73-L208)
|
||||
|
||||
**节源**
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs#L73-L208)
|
||||
@@ -0,0 +1,345 @@
|
||||
# ACP代理集成
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [acp_adapter/src/lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
- [acp_adapter/src/types.rs](file://crates/acp_adapter/src/types.rs)
|
||||
- [agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
- [agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs)
|
||||
- [agent_runner/src/proxy_agent/claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs)
|
||||
- [agent_runner/src/proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs)
|
||||
- [agent_runner/src/handler/chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs)
|
||||
- [agent_runner/src/handler/agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs)
|
||||
- [agent_runner/src/handler/agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs)
|
||||
- [agent_runner/src/service/session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
- [agent_runner/src/model.rs](file://crates/agent_runner/src/model.rs)
|
||||
- [shared_types/src/model/agent_model.rs](file://crates/shared_types/src/model/agent_model.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概述](#架构概述)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
本文档详细阐述了ACP代理集成的技术实现,重点说明acp_agent模块如何通过acp_adapter crate实现与ACP协议适配器的通信。文档涵盖了请求转发、状态同步、错误传播机制,以及消息序列化/反序列化过程、连接管理策略和超时处理机制。同时,文档还解释了协议版本兼容性、异常处理和性能优化措施,并通过实际交互示例展示聊天请求的完整流程。
|
||||
|
||||
## 项目结构
|
||||
项目采用模块化设计,主要分为以下几个核心模块:
|
||||
- `acp_adapter`: 提供与ACP协议适配器通信的核心功能
|
||||
- `agent_runner`: 负责代理服务的运行和管理
|
||||
- `shared_types`: 共享的数据类型和模型定义
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "核心模块"
|
||||
A[acp_adapter] --> |提供| B[agent_runner]
|
||||
C[shared_types] --> |共享类型| A
|
||||
C --> |共享类型| B
|
||||
end
|
||||
subgraph "代理类型"
|
||||
B --> D[Claude Code Agent]
|
||||
B --> E[Codex Agent]
|
||||
end
|
||||
subgraph "通信协议"
|
||||
A --> F[ACP协议]
|
||||
F --> G[子进程通信]
|
||||
end
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [acp_adapter/src/lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
- [agent_runner/src/proxy_agent/claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs)
|
||||
|
||||
**本节源**
|
||||
- [acp_adapter/src/lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
- [agent_runner/src/proxy_agent/claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs)
|
||||
|
||||
## 核心组件
|
||||
系统的核心组件包括ACP适配器、代理服务管理器和会话状态管理器。ACP适配器负责处理与代理的底层通信,代理服务管理器负责启动和管理不同类型的代理服务,会话状态管理器则负责维护会话的生命周期和状态同步。
|
||||
|
||||
**本节源**
|
||||
- [acp_adapter/src/lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
- [agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [agent_runner/src/service/session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
|
||||
## 架构概述
|
||||
系统采用分层架构设计,通过抽象层实现不同AI代理的统一接入。核心架构包括协议抽象层、代理管理层和会话管理层。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[客户端] --> B[HTTP API]
|
||||
B --> C[代理管理层]
|
||||
C --> D[协议抽象层]
|
||||
D --> E[ACP适配器]
|
||||
E --> F[具体代理]
|
||||
F --> G[Claude Code]
|
||||
F --> H[Codex]
|
||||
style D fill:#f9f,stroke:#333,stroke-width:2px
|
||||
style C fill:#bbf,stroke:#333,stroke-width:2px
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [acp_adapter/src/lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
- [agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### ACP适配器分析
|
||||
ACP适配器模块提供了与ACP兼容的AI代理通信的核心功能,包括连接管理、会话生命周期、消息处理和MCP集成。
|
||||
|
||||
#### 类图
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AcpAdapter {
|
||||
+initialize()
|
||||
+new_session()
|
||||
+load_session()
|
||||
+prompt()
|
||||
+cancel()
|
||||
}
|
||||
class SessionState {
|
||||
+Initializing
|
||||
+Connected
|
||||
+Prompting
|
||||
+Paused
|
||||
+Closed
|
||||
+Error
|
||||
}
|
||||
class StreamUpdate {
|
||||
+UserMessageChunk
|
||||
+AgentMessageChunk
|
||||
+AgentThoughtChunk
|
||||
+ToolCall
|
||||
+SessionStateChanged
|
||||
+PromptStarted
|
||||
+PromptCompleted
|
||||
+Error
|
||||
}
|
||||
AcpAdapter --> SessionState : "使用"
|
||||
AcpAdapter --> StreamUpdate : "生成"
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [acp_adapter/src/lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
- [acp_adapter/src/types.rs](file://crates/acp_adapter/src/types.rs)
|
||||
|
||||
#### 请求处理流程
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Handler as "Chat Handler"
|
||||
participant Agent as "ACP Agent"
|
||||
participant Adapter as "ACP Adapter"
|
||||
Client->>Handler : 发送聊天请求
|
||||
Handler->>Agent : 创建代理服务
|
||||
Agent->>Adapter : 初始化连接
|
||||
Adapter->>Agent : 返回连接信息
|
||||
Agent->>Adapter : 发送Prompt请求
|
||||
Adapter->>Client : 流式返回响应
|
||||
Client->>Handler : 接收响应
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [agent_runner/src/handler/chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs)
|
||||
- [agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
- [acp_adapter/src/lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
|
||||
**本节源**
|
||||
- [acp_adapter/src/lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
- [acp_adapter/src/types.rs](file://crates/acp_adapter/src/types.rs)
|
||||
- [agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
|
||||
### 代理服务管理分析
|
||||
代理服务管理器负责启动和管理不同类型的代理服务,通过统一的接口实现不同AI代理的接入。
|
||||
|
||||
#### 代理服务类图
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AcpAgentService {
|
||||
<<trait>>
|
||||
+start_agent_service()
|
||||
+agent_type_name()
|
||||
}
|
||||
class ClaudeCodeAgent {
|
||||
+start_claude_code_acp_agent_service()
|
||||
}
|
||||
class CodexAgent {
|
||||
+start_codex_acp_agent_service()
|
||||
}
|
||||
AcpAgentService <|-- ClaudeCodeAgent
|
||||
AcpAgentService <|-- CodexAgent
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [agent_runner/src/proxy_agent/claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs)
|
||||
|
||||
#### 代理启动流程
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([启动代理服务]) --> CheckExistence["检查代理是否存在"]
|
||||
CheckExistence --> |存在| Reuse["复用现有代理"]
|
||||
CheckExistence --> |不存在| Create["创建新代理"]
|
||||
Create --> StartProcess["启动子进程"]
|
||||
StartProcess --> Initialize["初始化ACP连接"]
|
||||
Initialize --> CreateSession["创建会话"]
|
||||
CreateSession --> SetupChannels["设置通信通道"]
|
||||
SetupChannels --> Monitor["监控代理状态"]
|
||||
Monitor --> End([代理服务启动完成])
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [agent_runner/src/proxy_agent/claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs)
|
||||
|
||||
**本节源**
|
||||
- [agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [agent_runner/src/proxy_agent/claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs)
|
||||
|
||||
### 会话状态管理分析
|
||||
会话状态管理器负责维护会话的生命周期和状态同步,确保消息的正确传递和状态的一致性。
|
||||
|
||||
#### 会话缓存流程
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[客户端建立SSE连接] --> B[创建SessionData]
|
||||
B --> C[插入SESSION_CACHE]
|
||||
C --> D[创建消息通道]
|
||||
D --> E[监听消息队列]
|
||||
E --> F[推送消息到客户端]
|
||||
F --> G{连接是否活跃?}
|
||||
G --> |是| E
|
||||
G --> |否| H[清理资源]
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [agent_runner/src/service/session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
- [agent_runner/src/handler/agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs)
|
||||
|
||||
#### 消息处理流程
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Handler as "Handler"
|
||||
participant Cache as "SessionCache"
|
||||
participant Agent as "Agent"
|
||||
Client->>Handler : 建立SSE连接
|
||||
Handler->>Cache : 创建SessionData
|
||||
Cache->>Handler : 返回消息通道
|
||||
loop 消息处理
|
||||
Agent->>Cache : 发送消息
|
||||
Cache->>Handler : 推送消息
|
||||
Handler->>Client : 发送SSE事件
|
||||
end
|
||||
Client->>Handler : 断开连接
|
||||
Handler->>Cache : 清理资源
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [agent_runner/src/service/session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
- [agent_runner/src/handler/agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs)
|
||||
- [agent_runner/src/proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs)
|
||||
|
||||
**本节源**
|
||||
- [agent_runner/src/service/session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
- [agent_runner/src/handler/agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs)
|
||||
- [agent_runner/src/proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs)
|
||||
|
||||
## 依赖分析
|
||||
系统依赖关系清晰,各模块之间通过定义良好的接口进行通信,降低了耦合度。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[agent_runner] --> B[acp_adapter]
|
||||
A --> C[shared_types]
|
||||
B --> D[agent_client_protocol]
|
||||
C --> E[protobuf]
|
||||
style A fill:#f96,stroke:#333
|
||||
style B fill:#6f9,stroke:#333
|
||||
style C fill:#96f,stroke:#333
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [Cargo.toml](file://Cargo.toml)
|
||||
- [crates/agent_runner/Cargo.toml](file://crates/agent_runner/Cargo.toml)
|
||||
- [crates/acp_adapter/Cargo.toml](file://crates/acp_adapter/Cargo.toml)
|
||||
|
||||
**本节源**
|
||||
- [Cargo.toml](file://Cargo.toml)
|
||||
- [crates/agent_runner/Cargo.toml](file://crates/agent_runner/Cargo.toml)
|
||||
- [crates/acp_adapter/Cargo.toml](file://crates/acp_adapter/Cargo.toml)
|
||||
|
||||
## 性能考虑
|
||||
系统在设计时充分考虑了性能优化,主要体现在以下几个方面:
|
||||
|
||||
1. **连接复用**: 通过PROJECT_AND_AGENT_INFO_MAP静态映射,实现项目与代理服务的一对一复用,避免频繁创建和销毁代理服务。
|
||||
2. **异步处理**: 使用Tokio异步运行时,通过LocalSet管理非Send的ACP连接,确保高性能的异步I/O操作。
|
||||
3. **通道优化**: 采用无界通道(unbounded_channel)进行消息传递,避免阻塞,同时通过环形缓冲区(HeapRb)管理消息队列,提高内存使用效率。
|
||||
4. **锁优化**: 使用DashMap替代传统HashMap,提供高性能的并发访问,减少锁竞争。
|
||||
5. **资源管理**: 通过CancellationToken实现优雅的资源清理,确保代理服务在取消时能够正确释放资源。
|
||||
|
||||
**本节源**
|
||||
- [agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
- [agent_runner/src/service/session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
- [agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs)
|
||||
|
||||
## 故障排除指南
|
||||
### 常见问题及解决方案
|
||||
|
||||
#### 代理启动失败
|
||||
**症状**: 启动代理服务时返回"启动ACP Agent服务失败"错误。
|
||||
|
||||
**可能原因**:
|
||||
1. 环境变量配置不正确
|
||||
2. 代理可执行文件未找到
|
||||
3. 项目目录权限问题
|
||||
|
||||
**解决方案**:
|
||||
1. 检查相关环境变量(如ANTHROPIC_API_KEY)是否正确设置
|
||||
2. 确认`claude-code-acp`或`codex-acp-agent`命令是否在PATH中
|
||||
3. 检查项目目录的读写权限
|
||||
|
||||
#### 消息推送中断
|
||||
**症状**: SSE连接建立后,消息推送突然中断。
|
||||
|
||||
**可能原因**:
|
||||
1. 代理服务异常退出
|
||||
2. 网络连接问题
|
||||
3. 超时设置过短
|
||||
|
||||
**解决方案**:
|
||||
1. 检查代理服务的日志输出
|
||||
2. 增加连接超时时间
|
||||
3. 实现客户端重连机制
|
||||
|
||||
#### 并发请求被拒绝
|
||||
**症状**: 连续发送多个请求时,后续请求返回"Agent正在执行任务"错误。
|
||||
|
||||
**原因**: 系统设计为每个项目ID对应一个代理服务,禁止并发请求以避免状态混乱。
|
||||
|
||||
**解决方案**:
|
||||
1. 等待当前任务完成后发送新请求
|
||||
2. 为不同任务使用不同的项目ID
|
||||
3. 实现请求队列机制
|
||||
|
||||
**本节源**
|
||||
- [agent_runner/src/handler/chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs)
|
||||
- [agent_runner/src/handler/agent_cancel_handler.rs](file://crates/agent_runner/src/handler/agent_cancel_handler.rs)
|
||||
- [agent_runner/src/proxy_agent/claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
|
||||
## 结论
|
||||
ACP代理集成系统通过清晰的分层架构和模块化设计,实现了与不同AI代理的统一接入。系统通过acp_adapter crate提供了协议抽象层,使得上层应用可以无缝切换不同的代理实现。通过高效的连接管理、状态同步和错误处理机制,系统确保了稳定可靠的通信。未来可以考虑增加更多类型的代理支持,以及优化资源利用率和响应性能。
|
||||
@@ -0,0 +1,333 @@
|
||||
# Claude Code代理实现
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs)
|
||||
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs)
|
||||
- [mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs)
|
||||
- [util.rs](file://crates/claude-code-agent/src/util.rs)
|
||||
- [lib.rs](file://crates/claude-code-agent/src/lib.rs)
|
||||
- [agent-abstraction-layer-design.md](file://specs/agent-abstraction-layer-design.md)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向系统集成者与开发者,全面阐述Claude Code代理在rcoder中的实现细节与使用方式。重点覆盖以下方面:
|
||||
- 如何封装Claude Code代理的特定行为(子进程启动、ACPI/O协议交互、MCP服务器配置、会话管理等)
|
||||
- 初始化参数、运行时配置与自定义通信模式
|
||||
- 与通用代理框架的集成方式(AcpAgentService、AgentType、生命周期管理)
|
||||
- 特殊错误处理逻辑与异常传播机制
|
||||
- 性能特征、资源消耗模式与与其他代理的差异点
|
||||
- 配置示例与调用流程说明,帮助在系统中启用与使用Claude Code代理
|
||||
|
||||
## 项目结构
|
||||
Claude Code代理位于agent_runner的代理层,围绕“子进程+ACPI/O协议”的模式实现,配合通用代理框架与生命周期管理,形成稳定的运行时闭环。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "代理运行器"
|
||||
AR["agent_runner<br/>代理运行与调度"]
|
||||
ACP["ACPI/O客户端<br/>AcpAgentClient"]
|
||||
SVC["AcpAgentService<br/>统一启动接口"]
|
||||
CHU["通道工具<br/>channel_utils"]
|
||||
LIFECYCLE["生命周期守卫<br/>AgentLifecycleGuard"]
|
||||
end
|
||||
subgraph "Claude Code库"
|
||||
LIB["claude-code-agent<br/>lib.rs"]
|
||||
UTIL["util.rs<br/>安装/命令/状态管理"]
|
||||
end
|
||||
subgraph "共享类型"
|
||||
AT["AgentType<br/>代理类型"]
|
||||
AM["Agent模型<br/>AgentStatus/ProjectAndAgentInfo"]
|
||||
ERR["AppError<br/>应用错误"]
|
||||
MCP["MCP配置<br/>create_default_mcp_servers"]
|
||||
end
|
||||
AR --> SVC
|
||||
SVC --> |"Claude"| AR
|
||||
AR --> |"启动子进程"| LIB
|
||||
LIB --> UTIL
|
||||
AR --> |"会话/通道"| CHU
|
||||
AR --> |"生命周期管理"| LIFECYCLE
|
||||
AR --> |"模型/环境变量"| AT
|
||||
AR --> |"会话状态/错误"| AM
|
||||
AR --> |"错误处理"| ERR
|
||||
AR --> |"MCP服务器"| MCP
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
|
||||
- [mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
- [util.rs](file://crates/claude-code-agent/src/util.rs#L1-L758)
|
||||
- [lib.rs](file://crates/claude-code-agent/src/lib.rs#L1-L9)
|
||||
|
||||
章节来源
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
|
||||
- [mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
- [util.rs](file://crates/claude-code-agent/src/util.rs#L1-L758)
|
||||
- [lib.rs](file://crates/claude-code-agent/src/lib.rs#L1-L9)
|
||||
|
||||
## 核心组件
|
||||
- Claude Code代理启动器:负责启动子进程、建立ACPI/O连接、创建会话、配置MCP服务器、管理通道与生命周期。
|
||||
- 通用代理服务接口:AcpAgentService为不同代理类型提供统一启动入口,Claude分支委托给claude_code_agent.rs。
|
||||
- 通道工具:统一处理取消与Prompt请求的发送、超时保护、状态更新与错误上报。
|
||||
- 生命周期管理:AgentLifecycleGuard封装子进程、stderr任务与取消令牌,支持优雅停止与强制清理。
|
||||
- 模型/环境变量映射:AgentType提供Claude所需的环境变量映射,支持从配置覆盖与环境变量注入。
|
||||
- MCP服务器配置:默认启用context7与fetch等MCP服务器,便于增强能力。
|
||||
- Claude Code库:提供安装、命令选择、状态检查与登录命令生成等辅助能力。
|
||||
|
||||
章节来源
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
- [mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
- [util.rs](file://crates/claude-code-agent/src/util.rs#L1-L758)
|
||||
|
||||
## 架构总览
|
||||
Claude Code代理采用“子进程+ACPI/O协议”的架构,通过AgentType与AcpAgentService抽象,实现与通用代理框架的无缝集成;同时利用生命周期守卫与通道工具,保障运行时稳定性与可观测性。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Caller as "调用方"
|
||||
participant AcpSvc as "AcpAgentService"
|
||||
participant Runner as "Claude启动器"
|
||||
participant Proc as "子进程(claude-code-acp)"
|
||||
participant AcpCli as "ACPI/O客户端"
|
||||
participant Utils as "通道工具"
|
||||
participant Life as "生命周期守卫"
|
||||
Caller->>AcpSvc : "start_agent_service(chat_prompt, model_provider)"
|
||||
AcpSvc->>Runner : "start_claude_code_acp_agent_service(...)"
|
||||
Runner->>Proc : "spawn子进程(工作目录/环境变量)"
|
||||
Runner->>AcpCli : "ClientSideConnection.new(...)"
|
||||
Runner->>AcpCli : "initialize(...)"
|
||||
Runner->>AcpCli : "new_session/load_session(...)"
|
||||
Runner->>Utils : "spawn_cancel_handler_for_agent(...)"
|
||||
Runner->>Utils : "spawn_prompt_handler_for_agent(...)"
|
||||
Runner->>Life : "new_claude(...)"
|
||||
Runner-->>Caller : "返回AcpConnectionInfo(会话ID/通道/停止句柄)"
|
||||
Note over Runner,AcpCli : "stderr读取任务独立运行"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### Claude Code代理启动器(claude_code_agent.rs)
|
||||
- 启动子进程:以claude-code-acp为命令,合并模型提供商配置生成环境变量,设置工作目录,捕获stdin/stdout/stderr。
|
||||
- ACPI/O连接:使用ClientSideConnection建立双向通信,LocalSet保证非Send任务在本地线程运行。
|
||||
- 初始化与会话:initialize后尝试load_session(兼容未来SDK),失败则回退new_session;会话ID通过oneshot通道返回。
|
||||
- MCP服务器:通过create_default_mcp_servers创建context7与fetch等服务器,注入会话请求。
|
||||
- 通道与任务:spawn_cancel_handler_for_agent与spawn_prompt_handler_for_agent分别处理取消与Prompt;stderr独立任务读取并记录。
|
||||
- 生命周期:new_claude创建AgentLifecycleGuard,结合CancellationToken与子进程/stderr任务,支持优雅停止与强制清理。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["启动Claude代理"]) --> Spawn["启动子进程<br/>合并环境变量/工作目录"]
|
||||
Spawn --> IO["创建ACPI/O连接<br/>ClientSideConnection"]
|
||||
IO --> Init["initialize()"]
|
||||
Init --> Session{"load_session成功?"}
|
||||
Session --> |是| GotSession["使用已有会话ID"]
|
||||
Session --> |否| NewSession["new_session()"]
|
||||
GotSession --> Ready["会话就绪"]
|
||||
NewSession --> Ready
|
||||
Ready --> MCP["配置MCP服务器(context7/ fetch)"]
|
||||
MCP --> Channels["启动取消/Prompt通道任务"]
|
||||
Channels --> Stderr["启动stderr读取任务"]
|
||||
Stderr --> Guard["创建生命周期守卫"]
|
||||
Guard --> Done(["返回AcpConnectionInfo"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
|
||||
章节来源
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
|
||||
### 通用代理服务接口(agent_service.rs)
|
||||
- AcpAgentService为不同代理类型提供统一启动入口,Claude分支委托给claude_code_agent.rs。
|
||||
- AgentType::Claude实现agent_type_name返回“Claude”,便于日志与监控识别。
|
||||
|
||||
章节来源
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
|
||||
### 通道工具(channel_utils.rs)
|
||||
- 取消处理:超时保护(默认10秒),发送CancelNotification,返回成功/失败响应,并将Agent状态恢复为Idle。
|
||||
- Prompt处理:校验session_id一致性,提取request_id写入会话上下文MAP,发送SessionPromptStart;成功发送SessionPromptEnd,失败发送SessionPromptError与SessionPromptEnd。
|
||||
- 状态管理:通过PROJECT_AND_AGENT_INFO_MAP更新Agent状态与最后活动时间。
|
||||
|
||||
章节来源
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
|
||||
### 生命周期管理(agent_model.rs)
|
||||
- AgentLifecycleGuard封装Claude资源(子进程、stderr任务、取消令牌),支持graceful_stop与force_cleanup。
|
||||
- 提供cancel、is_stopped、cancellation_token、agent_type等统一接口,实现AgentLifecycle trait。
|
||||
- Drop时自动清理,确保资源不泄漏。
|
||||
|
||||
章节来源
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
|
||||
### 模型/环境变量映射(agent_type.rs)
|
||||
- Claude环境变量映射:从进程环境变量聚合ANTHROPIC_*键,固定开启“跳过权限”参数,支持从ModelProviderConfig覆盖。
|
||||
- 从ModelProviderConfig推断Agent类型:anthropic->Claude,默认Claude。
|
||||
|
||||
章节来源
|
||||
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
|
||||
### MCP服务器配置(mcp_config.rs)
|
||||
- 默认启用context7与fetch MCP服务器,不使用API密钥,提供基础能力。
|
||||
- 提供创建默认MCP服务器列表的函数,便于在会话创建时注入。
|
||||
|
||||
章节来源
|
||||
- [mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
|
||||
### Claude Code库(util.rs/lib.rs)
|
||||
- ClaudeCodeAcpManager:安装/更新、状态检查、命令获取、登录命令生成、清理旧版本等。
|
||||
- ClaudeCodeAcpConfig:最小版本、包名、入口路径、二进制名、自定义命令、忽略系统版本等。
|
||||
- lib.rs:导出util模块,提供安装与命令相关便捷函数。
|
||||
|
||||
章节来源
|
||||
- [util.rs](file://crates/claude-code-agent/src/util.rs#L1-L758)
|
||||
- [lib.rs](file://crates/claude-code-agent/src/lib.rs#L1-L9)
|
||||
|
||||
### 与通用代理框架的集成(acp_agent.rs)
|
||||
- 通过AgentType::start_agent_service分派到Claude实现,创建ProjectAndAgentInfo并插入全局映射。
|
||||
- 若模型配置变化,触发Agent重启;否则复用现有Agent服务,直接发送Prompt请求。
|
||||
- 构建PromptRequest时将request_id放入meta,便于通道工具提取与上下文关联。
|
||||
|
||||
章节来源
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L392)
|
||||
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
|
||||
## 依赖关系分析
|
||||
- Claude启动器依赖:
|
||||
- AgentType(环境变量映射、代理类型)
|
||||
- AcpAgentClient/AcpConnectionInfo(ACPI/O连接信息)
|
||||
- create_default_mcp_servers(MCP服务器)
|
||||
- channel_utils(取消/Prompt通道)
|
||||
- AgentLifecycleGuard(生命周期)
|
||||
- 通用代理服务:
|
||||
- AcpAgentService为AgentType实现具体代理启动逻辑
|
||||
- Claude Code库:
|
||||
- util.rs提供安装与命令管理能力,lib.rs导出
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
AT["AgentType"] --> SVC["AcpAgentService"]
|
||||
SVC --> CC["Claude启动器"]
|
||||
CC --> CHU["通道工具"]
|
||||
CC --> LIFECYCLE["生命周期守卫"]
|
||||
CC --> MCP["MCP配置"]
|
||||
CC --> LIB["claude-code-agent(lib)"]
|
||||
LIB --> UTIL["util.rs"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
- [mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
- [lib.rs](file://crates/claude-code-agent/src/lib.rs#L1-L9)
|
||||
- [util.rs](file://crates/claude-code-agent/src/util.rs#L1-L758)
|
||||
|
||||
章节来源
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
- [mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
- [lib.rs](file://crates/claude-code-agent/src/lib.rs#L1-L9)
|
||||
- [util.rs](file://crates/claude-code-agent/src/util.rs#L1-L758)
|
||||
|
||||
## 性能考量
|
||||
- 子进程与I/O:
|
||||
- 子进程stdin/stdout/stderr通过tokio::process与tokio-util compat封装,避免阻塞。
|
||||
- ACPI/O连接在LocalSet中运行,避免跨线程Send限制。
|
||||
- 通道与任务:
|
||||
- 取消/Prompt通道均为无缓冲或有限缓冲,避免内存膨胀;stderr独立任务降低主循环压力。
|
||||
- 取消超时保护(默认10秒),防止阻塞导致的资源占用。
|
||||
- 会话与复用:
|
||||
- 以project_id为维度复用Agent服务,减少重复启动成本;模型配置变更时触发重启,避免状态污染。
|
||||
- MCP服务器:
|
||||
- 默认启用context7/ fetch,按需扩展,避免不必要的依赖。
|
||||
- 资源清理:
|
||||
- 生命周期守卫支持优雅停止与强制清理,避免僵尸进程与资源泄漏。
|
||||
|
||||
[本节为通用性能讨论,不直接分析具体文件]
|
||||
|
||||
## 故障排查指南
|
||||
- 启动失败:
|
||||
- 子进程无法启动:检查claude-code-acp命令是否存在、工作目录权限、环境变量是否正确注入。
|
||||
- ACPI/O初始化失败:查看initialize返回错误,确认协议版本与客户端信息。
|
||||
- 会话创建失败:回退load_session失败时自动new_session,若仍失败,检查MCP服务器配置与网络访问。
|
||||
- 运行时错误:
|
||||
- 取消超时:通道工具默认10秒超时,适当调整或检查远端Agent处理能力。
|
||||
- 通道发送失败:检查接收端是否关闭,或上游是否频繁重启。
|
||||
- stderr异常:stderr任务独立运行,注意日志中警告与错误行。
|
||||
- 生命周期问题:
|
||||
- 优雅停止无效:确认CancellationToken是否被正确取消,子进程与stderr任务是否被清理。
|
||||
- 资源泄漏:检查Drop逻辑是否触发,必要时强制清理。
|
||||
|
||||
章节来源
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
|
||||
## 结论
|
||||
Claude Code代理通过“子进程+ACPI/O协议”的稳定架构,结合通用代理框架与生命周期管理,提供了可复用、可观测、可扩展的代理实现。其特性包括:
|
||||
- 明确的初始化与会话管理流程
|
||||
- 可配置的MCP服务器与环境变量映射
|
||||
- 统一的取消/Prompt通道与状态管理
|
||||
- 完备的生命周期与资源清理
|
||||
- 与通用代理框架的无缝集成
|
||||
|
||||
[本节为总结性内容,不直接分析具体文件]
|
||||
|
||||
## 附录
|
||||
|
||||
### 配置示例与调用流程
|
||||
- 启用Claude Code代理:
|
||||
- 在配置中将default_agent设为Claude,或通过AgentType::Claude显式指定。
|
||||
- 确保环境变量包含ANTHROPIC_*(如ANTHROPIC_AUTH_TOKEN、ANTHROPIC_MODEL等),或通过ModelProviderConfig注入。
|
||||
- 启动时会自动尝试加载或安装claude-code-acp,必要时可使用登录命令生成凭据。
|
||||
- 调用流程:
|
||||
- 调用AcpAgentService::start_agent_service(chat_prompt, model_provider)
|
||||
- 返回AcpConnectionInfo,包含session_id、prompt_tx、cancel_tx与stop_handle
|
||||
- 通过prompt_tx发送PromptRequest,通过cancel_tx发送CancelNotification
|
||||
- 使用stop_handle进行优雅停止或强制清理
|
||||
|
||||
章节来源
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
- [util.rs](file://crates/claude-code-agent/src/util.rs#L1-L758)
|
||||
- [agent-abstraction-layer-design.md](file://specs/agent-abstraction-layer-design.md#L308-L375)
|
||||
@@ -0,0 +1,364 @@
|
||||
# Codex代理实现
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs)
|
||||
- [crates/agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
- [crates/agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs)
|
||||
- [crates/agent_runner/src/utils/mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs)
|
||||
- [crates/agent_runner/src/config.rs](file://crates/agent_runner/src/config.rs)
|
||||
- [crates/shared_types/src/model/agent_model.rs](file://crates/shared_types/src/model/agent_model.rs)
|
||||
- [crates/shared_types/src/model/agent_type.rs](file://crates/shared_types/src/model/agent_type.rs)
|
||||
- [crates/shared_types/src/model/model_provider.rs](file://crates/shared_types/src/model/model_provider.rs)
|
||||
- [crates/codex-acp-agent/src/lib.rs](file://crates/codex-acp-agent/src/lib.rs)
|
||||
- [crates/codex-acp-agent/src/bin/codex-acp-agent.rs](file://crates/codex-acp-agent/src/bin/codex-acp-agent.rs)
|
||||
- [README.md](file://README.md)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向“Codex代理实现”的技术文档,聚焦于rcoder工程中codex_agent模块的设计与实现,阐述其与Codex ACP代理的交互方式、启动流程、命令执行与结果解析,以及特定于Codex代理的配置选项、性能特征与限制条件。同时记录与通用代理运行时环境的集成细节,以及与其他AI代理的兼容性处理,并提供实际使用示例与最佳实践建议。
|
||||
|
||||
## 项目结构
|
||||
- 代码组织采用多crate工作区,核心运行时位于agent_runner,Codex ACP代理以独立二进制形式存在,通过子进程方式启动并与主服务建立ACP连接。
|
||||
- 关键模块:
|
||||
- codex_agent:负责启动Codex ACP子进程、建立ACP连接、会话管理、Prompt与取消处理。
|
||||
- acp_agent:通用代理服务调度与复用逻辑,按项目维度管理Agent生命周期。
|
||||
- channel_utils:统一的Prompt与Cancel通道处理,封装会话通知与状态更新。
|
||||
- agent_service:ACP代理服务抽象与实现选择(Codex/Claude)。
|
||||
- agent_stop_handle:生命周期守卫,统一优雅停止与资源回收。
|
||||
- mcp_config:默认MCP服务器配置,增强代理能力。
|
||||
- shared_types:跨crate共享的数据结构与生命周期接口。
|
||||
- codex-acp-agent:Codex ACP代理二进制入口与库导出。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "运行时"
|
||||
AR["agent_runner<br/>代理运行时"]
|
||||
CFG["配置系统<br/>config.rs"]
|
||||
ST["共享类型<br/>shared_types"]
|
||||
end
|
||||
subgraph "Codex ACP"
|
||||
BIN["codex-acp-agent 二进制<br/>bin/codex-acp-agent.rs"]
|
||||
LIB["codex-acp-agent 库<br/>lib.rs"]
|
||||
end
|
||||
subgraph "协议与工具"
|
||||
ACP["Agent Client Protocol<br/>外部协议"]
|
||||
MCP["MCP 服务器配置<br/>mcp_config.rs"]
|
||||
end
|
||||
AR --> BIN
|
||||
AR --> ST
|
||||
AR --> CFG
|
||||
AR --> MCP
|
||||
BIN --> ACP
|
||||
LIB --> ACP
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L1-L398)
|
||||
- [crates/agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L392)
|
||||
- [crates/agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [crates/agent_runner/src/utils/mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
- [crates/codex-acp-agent/src/bin/codex-acp-agent.rs](file://crates/codex-acp-agent/src/bin/codex-acp-agent.rs#L1-L46)
|
||||
- [crates/codex-acp-agent/src/lib.rs](file://crates/codex-acp-agent/src/lib.rs#L1-L18)
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L1-L398)
|
||||
- [crates/agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L392)
|
||||
- [crates/agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [crates/agent_runner/src/utils/mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
- [crates/codex-acp-agent/src/bin/codex-acp-agent.rs](file://crates/codex-acp-agent/src/bin/codex-acp-agent.rs#L1-L46)
|
||||
- [crates/codex-acp-agent/src/lib.rs](file://crates/codex-acp-agent/src/lib.rs#L1-L18)
|
||||
|
||||
## 核心组件
|
||||
- Codex ACP子进程启动与连接管理:负责启动codex-acp-agent二进制、准备环境变量与CLI覆盖参数、建立ClientSideConnection、初始化ACP、创建/加载会话、管理stderr输出与生命周期。
|
||||
- 代理服务调度与复用:按项目维度缓存Agent信息,支持模型配置变化时的重启,复用现有Agent减少启动开销。
|
||||
- 通道处理工具:统一处理Prompt与Cancel请求,发送会话开始/结束/错误通知,更新Agent状态。
|
||||
- 生命周期守卫:统一管理子进程与stderr任务,支持优雅停止与强制清理。
|
||||
- MCP服务器配置:默认启用context7与fetch等MCP服务器,增强代理能力。
|
||||
- 配置系统:命令行、环境变量、配置文件与默认配置的多层优先级。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L1-L398)
|
||||
- [crates/agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L392)
|
||||
- [crates/agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L82-L126)
|
||||
- [crates/agent_runner/src/utils/mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
- [crates/agent_runner/src/config.rs](file://crates/agent_runner/src/config.rs#L1-L270)
|
||||
|
||||
## 架构总览
|
||||
Codex代理通过子进程方式与主服务交互,主服务负责:
|
||||
- 选择Agent类型(Codex/Claude),并调用相应启动函数。
|
||||
- 为Codex准备模型提供商配置与环境变量,构建CLI覆盖参数。
|
||||
- 启动codex-acp-agent二进制,建立ACP连接,初始化会话。
|
||||
- 通过通道将用户Prompt发送到代理,接收结果并通过SSE通知前端。
|
||||
- 管理生命周期,支持取消与优雅停止。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Runner as "代理运行时<br/>acp_agent.rs"
|
||||
participant Codex as "Codex ACP 启动器<br/>codex_agent.rs"
|
||||
participant Proc as "子进程<br/>codex-acp-agent"
|
||||
participant Conn as "ACP 连接"
|
||||
participant Chan as "通道处理<br/>channel_utils.rs"
|
||||
Client->>Runner : "提交聊天请求"
|
||||
Runner->>Codex : "start_codex_acp_agent_service(...)"
|
||||
Codex->>Proc : "spawn 子进程并传入CLI覆盖参数"
|
||||
Proc-->>Conn : "建立ClientSideConnection"
|
||||
Codex->>Conn : "initialize / new_session"
|
||||
Conn-->>Codex : "返回SessionId"
|
||||
Runner->>Chan : "发送PromptRequest"
|
||||
Chan->>Conn : "prompt(...)"
|
||||
Conn-->>Chan : "返回结果/错误"
|
||||
Chan-->>Runner : "推送Session通知"
|
||||
Runner-->>Client : "SSE 实时进度/结果"
|
||||
Client->>Runner : "取消请求"
|
||||
Runner->>Chan : "发送Cancel通知"
|
||||
Chan->>Conn : "cancel(...)"
|
||||
Conn-->>Chan : "取消结果"
|
||||
Chan-->>Runner : "推送Session结束"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L392)
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L1-L398)
|
||||
- [crates/agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [crates/codex-acp-agent/src/bin/codex-acp-agent.rs](file://crates/codex-acp-agent/src/bin/codex-acp-agent.rs#L1-L46)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### Codex ACP启动与会话管理
|
||||
- 启动流程
|
||||
- 依据ModelProviderConfig生成环境变量与CLI覆盖参数,固定使用“custom”模型提供商名称,确保与后续配置一致。
|
||||
- 通过tokio::process::Command启动codex-acp-agent二进制,设置stdin/stdout/stderr管道与工作目录。
|
||||
- 建立ClientSideConnection并初始化ACP,随后创建或加载会话,返回会话ID与Prompt/Cancel通道。
|
||||
- 启动stderr读取任务,将子进程输出转发到日志。
|
||||
- 创建生命周期守卫,绑定项目ID、会话ID、子进程与取消令牌,支持优雅停止。
|
||||
- 命令执行与结果解析
|
||||
- 通过通道将PromptRequest发送到代理,代理执行后返回stop_reason等信息。
|
||||
- 通道处理工具负责将开始、结束、错误等会话通知推送给前端。
|
||||
- 取消与错误处理
|
||||
- 通过CancelNotification在超时时间内调用代理cancel,超时则返回超时响应。
|
||||
- 后台任务失败时,通过Prompt通道发送错误内容块,触发错误通知与结束事件。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["启动Codex ACP子进程"]) --> Env["准备环境变量与CLI覆盖参数"]
|
||||
Env --> Spawn["spawn 子进程"]
|
||||
Spawn --> IO["建立ClientSideConnection"]
|
||||
IO --> Init["initialize / new_session"]
|
||||
Init --> Session["获得SessionId"]
|
||||
Session --> Prompt["发送PromptRequest"]
|
||||
Prompt --> Result{"执行结果"}
|
||||
Result --> |成功| NotifyOK["推送SessionPromptEnd"]
|
||||
Result --> |失败| NotifyErr["推送SessionPromptError<br/>再推送SessionPromptEnd"]
|
||||
NotifyOK --> Stop["优雅停止/取消"]
|
||||
NotifyErr --> Stop
|
||||
Stop --> End(["结束"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L1-L398)
|
||||
- [crates/agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L1-L398)
|
||||
- [crates/agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
|
||||
### 代理服务调度与复用
|
||||
- 项目维度的Agent复用:以DashMap存储ProjectAndAgentInfo,按project_id映射到Agent服务,避免重复启动。
|
||||
- 模型配置变化检测:当ModelProviderConfig变化时,删除旧Agent并重建新Agent,保证配置一致性。
|
||||
- Prompt构建:将系统提示词、用户输入与附件合并为ContentBlocks,注入request_id到meta,便于会话上下文追踪。
|
||||
- 会话通知:通过push_session_update_with_project推送SessionPromptStart/End/Error事件。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AcpAgentService {
|
||||
+start_agent_service(chat_prompt, model_provider) AcpConnectionInfo
|
||||
+agent_type_name() str
|
||||
}
|
||||
class AgentType {
|
||||
+from_model_provider(model_provider) AgentType
|
||||
+codex_model_provider(model_provider) (ConfigToml, envs)
|
||||
}
|
||||
class AcpAgentWorker {
|
||||
+agent_worker(request_rx)
|
||||
+build_prompt_to_acp_agent(prompt, session_id) PromptRequest
|
||||
}
|
||||
class ProjectAndAgentInfo {
|
||||
+project_id : string
|
||||
+session_id : SessionId
|
||||
+prompt_tx : mpsc
|
||||
+cancel_tx : mpsc
|
||||
+model_provider : Option<ModelProviderConfig>
|
||||
+status : AgentStatus
|
||||
+last_activity : DateTime
|
||||
+created_at : DateTime
|
||||
+stop_handle : Option<AgentLifecycle>
|
||||
}
|
||||
AcpAgentService <|.. AgentType : "实现"
|
||||
AcpAgentWorker --> AcpAgentService : "调用"
|
||||
AcpAgentWorker --> ProjectAndAgentInfo : "读写"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [crates/shared_types/src/model/agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
- [crates/agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L392)
|
||||
- [crates/shared_types/src/model/agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L392)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [crates/shared_types/src/model/agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
- [crates/shared_types/src/model/agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
|
||||
### 生命周期与资源管理
|
||||
- 生命周期守卫:统一管理子进程与stderr任务,支持graceful_stop、cancel、force_cleanup等操作。
|
||||
- 资源类型:CodexSubProcess与Claude类似,均包含child_process与stderr_task。
|
||||
- 取消令牌:通过CancellationToken协调取消信号,确保任务自然退出后再强制清理。
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> 启动
|
||||
启动 --> 运行中 : "子进程启动/会话创建"
|
||||
运行中 --> 取消中 : "收到取消信号"
|
||||
取消中 --> 停止中 : "超时/取消完成"
|
||||
停止中 --> 已停止 : "优雅停止/强制清理"
|
||||
已停止 --> [*]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/shared_types/src/model/agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L82-L126)
|
||||
|
||||
章节来源
|
||||
- [crates/shared_types/src/model/agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L82-L126)
|
||||
|
||||
### MCP服务器与能力增强
|
||||
- 默认MCP服务器:context7与fetch,用于扩展代理能力(如网络访问、前端模板等)。
|
||||
- 配置生成:create_default_mcp_servers返回MCP服务器列表,可在会话创建时传入。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/utils/mcp_config.rs](file://crates/agent_runner/src/utils/mcp_config.rs#L1-L225)
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L228-L246)
|
||||
|
||||
### 配置与兼容性
|
||||
- 模型提供商配置:ModelProviderConfig包含id/name/base_url/api_key/requires_openai_auth/default_model/api_protocol等字段。
|
||||
- Agent类型映射:AgentType::from_model_provider根据provider.name映射到Codex/Claude。
|
||||
- 环境变量与CLI覆盖:Codex通过codex_model_provider生成环境变量与CLI覆盖参数,固定使用“custom”模型提供商名称。
|
||||
- 兼容性:AgentType实现AcpAgentService,支持按AgentType选择启动函数;README提供多代理配置示例。
|
||||
|
||||
章节来源
|
||||
- [crates/shared_types/src/model/model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L1-L132)
|
||||
- [crates/shared_types/src/model/agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L1-L257)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [README.md](file://README.md#L107-L130)
|
||||
|
||||
## 依赖关系分析
|
||||
- 运行时依赖
|
||||
- agent_client_protocol:ACP协议类型与ClientSideConnection。
|
||||
- tokio/tokio-util:异步运行时与流适配。
|
||||
- tracing/dashmap:日志与并发Map。
|
||||
- 外部二进制
|
||||
- codex-acp-agent:通过子进程方式运行,支持-cli覆盖配置。
|
||||
- 共享类型
|
||||
- AgentType、ModelProviderConfig、AgentLifecycle等跨crate共享。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
codex_agent["codex_agent.rs"] --> acp_proto["agent_client_protocol"]
|
||||
codex_agent --> tokio["tokio/tokio_util"]
|
||||
codex_agent --> tracing_dash["tracing/dashmap"]
|
||||
acp_agent["acp_agent.rs"] --> shared_types["shared_types"]
|
||||
channel_utils["channel_utils.rs"] --> shared_types
|
||||
agent_service["agent_service.rs"] --> shared_types
|
||||
codex_bin["codex-acp-agent 二进制"] --> codex_lib["codex-acp-agent 库"]
|
||||
codex_lib --> acp_proto
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L1-L398)
|
||||
- [crates/agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L392)
|
||||
- [crates/agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [crates/codex-acp-agent/src/lib.rs](file://crates/codex-acp-agent/src/lib.rs#L1-L18)
|
||||
- [crates/codex-acp-agent/src/bin/codex-acp-agent.rs](file://crates/codex-acp-agent/src/bin/codex-acp-agent.rs#L1-L46)
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L1-L398)
|
||||
- [crates/agent_runner/src/proxy_agent/acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L1-L392)
|
||||
- [crates/agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [crates/codex-acp-agent/src/lib.rs](file://crates/codex-acp-agent/src/lib.rs#L1-L18)
|
||||
- [crates/codex-acp-agent/src/bin/codex-acp-agent.rs](file://crates/codex-acp-agent/src/bin/codex-acp-agent.rs#L1-L46)
|
||||
|
||||
## 性能考量
|
||||
- 启动开销
|
||||
- 子进程启动与ACP初始化带来额外开销;通过项目维度复用Agent可显著降低重复启动成本。
|
||||
- 模型配置变化触发Agent重启,应在配置稳定时减少频繁变更。
|
||||
- I/O与通道
|
||||
- Prompt与Cancel通过无阻塞通道传输,避免阻塞主循环;通道处理工具对取消调用设置超时,防止阻塞。
|
||||
- MCP服务器
|
||||
- 默认启用context7与fetch等MCP服务器,可能增加额外I/O与资源消耗;可根据需求裁剪。
|
||||
- 日志与stderr
|
||||
- 后台stderr读取任务在取消时会退出,避免长时间占用;建议在生产环境合理设置日志级别。
|
||||
|
||||
[本节为通用性能讨论,不直接分析具体文件]
|
||||
|
||||
## 故障排查指南
|
||||
- 启动失败
|
||||
- 检查codex-acp-agent二进制是否可执行、CLI覆盖参数是否正确、环境变量是否包含API密钥。
|
||||
- 查看stderr任务输出,定位初始化失败原因(如base_url/api_key/model_provider配置错误)。
|
||||
- 取消超时
|
||||
- 通道处理工具对cancel调用设置了超时保护,超时会返回超时响应;适当调整代理侧处理能力或网络状况。
|
||||
- 会话不一致
|
||||
- 通道处理工具会在收到Prompt时强制覆盖session_id为当前会话,确保一致性;若出现异常,检查会话ID传递与Meta字段。
|
||||
- 生命周期清理
|
||||
- 优雅停止会先发送取消信号,再强制清理子进程与stderr任务;若出现僵尸进程,检查取消令牌与Drop逻辑。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/proxy_agent/codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L313-L335)
|
||||
- [crates/agent_runner/src/proxy_agent/channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [crates/shared_types/src/model/agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
|
||||
## 结论
|
||||
Codex代理通过子进程与ACP协议实现与主服务的解耦集成,具备良好的可配置性与可扩展性。通过项目维度的Agent复用、统一的通道处理与生命周期管理,系统在稳定性与性能之间取得平衡。结合MCP服务器与模型提供商配置,可灵活适配多种场景。建议在生产环境中关注stderr日志、取消超时与模型配置变更策略,以提升整体可靠性。
|
||||
|
||||
[本节为总结性内容,不直接分析具体文件]
|
||||
|
||||
## 附录
|
||||
|
||||
### 使用示例与最佳实践
|
||||
- 启动与配置
|
||||
- 使用命令行参数或环境变量设置端口与项目目录;首次运行会自动生成默认配置文件。
|
||||
- Codex代理需要正确的API密钥与base_url;可通过ModelProviderConfig或环境变量注入。
|
||||
- 交互流程
|
||||
- 提交聊天请求后,系统会按项目维度复用Agent;若模型配置变化则自动重启Agent。
|
||||
- 通过SSE实时接收会话开始、结束与错误通知;支持取消正在执行的任务。
|
||||
- 最佳实践
|
||||
- 将模型配置与API密钥集中管理,避免频繁变更导致Agent重启。
|
||||
- 合理裁剪MCP服务器,减少不必要的I/O与资源消耗。
|
||||
- 在生产环境开启适当的日志级别,便于快速定位问题。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/config.rs](file://crates/agent_runner/src/config.rs#L1-L270)
|
||||
- [crates/shared_types/src/model/model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L1-L132)
|
||||
- [README.md](file://README.md#L440-L527)
|
||||
249
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/代理运行器架构/代理服务.md
Normal file
249
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/代理运行器架构/代理服务.md
Normal file
@@ -0,0 +1,249 @@
|
||||
# 代理服务
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs)
|
||||
- [agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
- [docker_manager.rs](file://crates/docker_manager/src/manager.rs)
|
||||
- [docker_container_agent.rs](file://crates/rcoder/src/proxy_agent/docker_container_agent.rs)
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [agent-abstraction-layer-design.md](file://specs/agent-abstraction-layer-design.md)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [介绍](#介绍)
|
||||
2. [核心组件](#核心组件)
|
||||
3. [代理服务设计与实现](#代理服务设计与实现)
|
||||
4. [与Docker管理器的集成](#与docker管理器的集成)
|
||||
5. [异步任务调度与会话管理](#异步任务调度与会话管理)
|
||||
6. [错误恢复与生命周期管理](#错误恢复与生命周期管理)
|
||||
7. [与ACP适配器的交互模式](#与acp适配器的交互模式)
|
||||
8. [多代理类型支持](#多代理类型支持)
|
||||
9. [服务初始化与关闭逻辑](#服务初始化与关闭逻辑)
|
||||
10. [结论](#结论)
|
||||
|
||||
## 介绍
|
||||
代理服务是AI开发平台的核心组件,负责管理AI代理的整个生命周期。该服务通过统一的接口抽象,支持多种AI代理类型(如Codex、Claude Code),并利用容器化技术实现资源隔离和高效管理。本文档详细阐述了代理服务的设计与实现,重点分析了AgentService结构体的核心作用、与Docker管理器的集成方式、异步任务调度机制以及错误恢复策略。
|
||||
|
||||
## 核心组件
|
||||
代理服务的核心组件包括AgentService结构体、Docker管理器、会话缓存和清理任务。这些组件协同工作,确保AI代理的高效、稳定运行。AgentService结构体作为统一接口,封装了不同代理类型的启动和管理逻辑。Docker管理器负责容器的创建、启动和销毁,实现资源的动态分配和隔离。会话缓存用于存储和管理会话状态,支持SSE(Server-Sent Events)实时消息推送。清理任务则定期检查并清理闲置的代理实例,优化资源利用率。
|
||||
|
||||
## 代理服务设计与实现
|
||||
代理服务的设计遵循模块化和可扩展的原则,通过定义清晰的接口和抽象,实现了不同代理类型的统一管理。核心是`AcpAgentService` trait,它定义了启动和管理ACP代理服务的统一接口。该trait的实现通过为`AgentType`枚举类型提供`async_trait`,实现了对不同代理类型的统一处理。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AcpAgentService {
|
||||
<<trait>>
|
||||
+start_agent_service(chat_prompt : ChatPrompt, model_provider : Option~ModelProviderConfig~) Result~AcpConnectionInfo~
|
||||
+agent_type_name() &'static str
|
||||
}
|
||||
class AgentType {
|
||||
+Claude
|
||||
+Codex
|
||||
}
|
||||
AcpAgentService <|-- AgentType
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L7-L61)
|
||||
|
||||
`AcpConnectionInfo`结构体封装了与代理通信所需的关键信息,包括会话ID、用于发送提示的通道、用于发送取消通知的通道以及代理停止句柄。这种设计使得外部组件可以通过这些通道与代理进行异步通信,实现了非阻塞的消息传递。
|
||||
|
||||
**本节源码**
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L31-L41)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L31-L41)
|
||||
|
||||
## 与Docker管理器的集成
|
||||
代理服务通过`docker_manager` crate与Docker守护进程进行交互,实现了AI代理的容器化运行。`DockerManager`结构体作为核心管理器,封装了Docker客户端和配置信息,提供了创建、启动、停止和清理容器的高级接口。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant 代理服务
|
||||
participant Docker管理器
|
||||
participant Docker守护进程
|
||||
代理服务->>Docker管理器 : create_container(config)
|
||||
Docker管理器->>Docker守护进程 : 检查镜像是否存在
|
||||
alt 镜像不存在
|
||||
Docker守护进程-->>Docker管理器 : 返回不存在
|
||||
Docker管理器->>Docker守护进程 : pull_image(image)
|
||||
end
|
||||
Docker管理器->>Docker守护进程 : create_container(options, config)
|
||||
Docker守护进程-->>Docker管理器 : container_id
|
||||
Docker管理器->>Docker守护进程 : start_container(container_id)
|
||||
Docker守护进程-->>Docker管理器 : 启动成功
|
||||
Docker管理器-->>代理服务 : DockerContainerInfo
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [docker_manager.rs](file://crates/docker_manager/src/manager.rs#L81-L294)
|
||||
- [docker_container_agent.rs](file://crates/rcoder/src/proxy_agent/docker_container_agent.rs#L21-L129)
|
||||
|
||||
`DockerManager`的`create_container`方法是容器化运行AI代理实例的关键。该方法首先检查指定的镜像是否存在于本地,如果不存在则从远程仓库拉取。然后,它使用提供的配置创建容器,包括挂载点、环境变量、端口映射和资源限制。最后,启动容器并返回包含容器信息的`DockerContainerInfo`结构体。这种设计确保了每个AI代理实例都在独立的容器环境中运行,实现了资源隔离和安全防护。
|
||||
|
||||
**本节源码**
|
||||
- [docker_manager.rs](file://crates/docker_manager/src/manager.rs#L81-L294)
|
||||
- [docker_container_agent.rs](file://crates/rcoder/src/proxy_agent/docker_container_agent.rs#L21-L129)
|
||||
|
||||
## 异步任务调度与会话管理
|
||||
代理服务采用异步任务调度机制,通过`tokio`运行时和`mpsc`通道实现高效的并发处理。`AcpAgentClient`结构体实现了`agent_client_protocol::Client` trait,处理来自代理的会话通知。当收到`session_notification`时,它会解析通知内容,提取`request_id`,并将其与`session_id`关联,然后将更新推送到全局会话缓存。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([收到session_notification]) --> ExtractSessionId["提取session_id"]
|
||||
ExtractSessionId --> CheckMeta["检查meta中是否有request_id"]
|
||||
CheckMeta --> |有| UseMetaId["使用meta中的request_id"]
|
||||
CheckMeta --> |无| FindProjectId["通过session_id查找project_id"]
|
||||
FindProjectId --> GetRequestId["从SESSION_REQUEST_CONTEXT获取request_id"]
|
||||
GetRequestId --> |获取成功| UseContextId["使用context中的request_id"]
|
||||
GetRequestId --> |获取失败| NoRequestId["未找到request_id"]
|
||||
UseMetaId --> PushUpdate["推送AgentSessionUpdate"]
|
||||
UseContextId --> PushUpdate
|
||||
NoRequestId --> PushUpdate
|
||||
PushUpdate --> End([完成])
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L232-L257)
|
||||
|
||||
会话管理通过`SESSION_CACHE`和`PROJECT_SESSION_MAP`两个全局`DashMap`实现。`SESSION_CACHE`以`session_id`为键,存储`SessionData`,后者包含用于SSE消息推送的通道和取消令牌。`PROJECT_SESSION_MAP`则维护`project_id`到`session_id`的映射,确保一个项目只对应一个活跃的会话。`push_session_update_with_project`函数在推送消息时,会自动检查并清理旧的会话数据,保证了会话状态的一致性。
|
||||
|
||||
**本节源码**
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L16-L355)
|
||||
|
||||
## 错误恢复与生命周期管理
|
||||
代理服务通过`AgentLifecycleGuard`结构体实现基于RAII(Resource Acquisition Is Initialization)原则的生命周期管理。当`AgentLifecycleGuard`被`drop`时,其内部的`Drop`实现会自动清理代理资源,如停止子进程和取消异步任务。这种设计简化了资源管理,避免了资源泄漏。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AgentLifecycleGuard {
|
||||
+new_claude(...) AgentLifecycleGuard
|
||||
+new_codex(...) AgentLifecycleGuard
|
||||
+graceful_stop() Result~()~
|
||||
+cancel()
|
||||
+is_stopped() bool
|
||||
}
|
||||
class AgentResources {
|
||||
<<enumeration>>
|
||||
+Claude
|
||||
+CodexSubProcess
|
||||
+CodexEmbedded
|
||||
}
|
||||
AgentLifecycleGuard --> AgentLifecycleInner : 包含
|
||||
AgentLifecycleInner --> AgentResources : 包含
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L21-L326)
|
||||
|
||||
`AgentLifecycleGuard`的`graceful_stop`方法实现了优雅停止代理的逻辑。它首先发送取消信号,然后根据代理类型执行相应的清理操作,如等待子进程退出或取消异步任务。`cancel`方法则用于非阻塞地发送取消信号。`is_stopped`方法检查代理是否已停止。这些方法共同构成了一个健壮的错误恢复机制,确保在各种异常情况下都能正确清理资源。
|
||||
|
||||
**本节源码**
|
||||
- [agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L140-L204)
|
||||
|
||||
## 与ACP适配器的交互模式
|
||||
代理服务通过`AcpAgentClient`与ACP(Agent Client Protocol)适配器进行交互。`AcpAgentClient`实现了`agent_client_protocol::Client` trait,处理来自代理的各种请求,如权限请求、文件读写和会话通知。当代理需要执行文件操作时,`AcpAgentClient`会调用相应的`tokio::fs`函数,并将结果返回给代理。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant 代理
|
||||
participant AcpAgentClient
|
||||
participant 文件系统
|
||||
代理->>AcpAgentClient : write_text_file(args)
|
||||
AcpAgentClient->>文件系统 : create_dir_all(parent)
|
||||
文件系统-->>AcpAgentClient : 创建成功
|
||||
AcpAgentClient->>文件系统 : create_file(path)
|
||||
文件系统-->>AcpAgentClient : 文件句柄
|
||||
AcpAgentClient->>文件系统 : write_all(content)
|
||||
文件系统-->>AcpAgentClient : 写入成功
|
||||
AcpAgentClient-->>代理 : WriteTextFileResponse
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L78-L98)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L100-L110)
|
||||
|
||||
`AcpAgentClient`还负责处理会话通知,如`AgentMessageChunk`和`AgentMessageComplete`。它将这些通知转换为`UnifiedSessionMessage`,并通过`push_session_update`函数推送到会话缓存,最终通过SSE推送给前端客户端。这种交互模式实现了代理与外部系统的松耦合,提高了系统的可维护性和可扩展性。
|
||||
|
||||
**本节源码**
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L232-L257)
|
||||
|
||||
## 多代理类型支持
|
||||
代理服务通过`AgentType`枚举和`AcpAgentService` trait的实现,支持多种代理类型,如Codex和Claude Code。`AgentType`枚举定义了不同的代理类型,而`AcpAgentService` trait的实现则为每种类型提供了具体的启动逻辑。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AcpAgentService {
|
||||
<<trait>>
|
||||
+start_agent_service(...) Result~AcpConnectionInfo~
|
||||
}
|
||||
class AgentType {
|
||||
+Claude
|
||||
+Codex
|
||||
}
|
||||
AcpAgentService <|-- AgentType
|
||||
class start_claude_code_acp_agent_service {
|
||||
+command_path : &str
|
||||
+command_args : Vec~String~
|
||||
+spawn_args : Vec~String~
|
||||
+merged_envs : HashMap~String, String~
|
||||
}
|
||||
class start_codex_acp_agent_service {
|
||||
+command_path : &str
|
||||
+cli_args : Vec~String~
|
||||
+merged_envs : HashMap~String, String~
|
||||
}
|
||||
AgentType --> start_claude_code_acp_agent_service : 启动
|
||||
AgentType --> start_codex_acp_agent_service : 启动
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L30-L59)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L28-L310)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L25-L397)
|
||||
|
||||
`start_claude_code_acp_agent_service`和`start_codex_acp_agent_service`函数分别负责启动Claude Code和Codex代理。它们通过`tokio::process::Command`启动子进程,并建立`ClientSideConnection`进行通信。这些函数还处理环境变量和CLI参数的配置,确保代理能够正确初始化。这种设计实现了多代理类型的统一接口抽象,使得添加新的代理类型变得简单而直观。
|
||||
|
||||
**本节源码**
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L28-L310)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L25-L397)
|
||||
|
||||
## 服务初始化与关闭逻辑
|
||||
代理服务的初始化在`main.rs`文件的`main`函数中完成。它首先初始化遥测系统,然后解析命令行参数和配置文件。接着,它创建项目工作目录,并启动清理任务。最后,它创建HTTP服务器并监听指定端口。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([main函数开始]) --> InitTelemetry["初始化遥测系统"]
|
||||
InitTelemetry --> ParseArgs["解析命令行参数"]
|
||||
ParseArgs --> LoadConfig["加载配置文件"]
|
||||
LoadConfig --> CreateDir["创建项目工作目录"]
|
||||
CreateDir --> StartCleanup["启动清理任务"]
|
||||
StartCleanup --> SpawnWorker["启动agent_worker线程"]
|
||||
SpawnWorker --> StartProxy["启动Pingora代理服务"]
|
||||
StartProxy --> CreateRouter["创建HTTP路由"]
|
||||
CreateRouter --> BindListener["绑定TCP监听器"]
|
||||
BindListener --> Serve["启动HTTP服务器"]
|
||||
Serve --> AwaitProxy["等待代理服务完成"]
|
||||
AwaitProxy --> End([main函数结束])
|
||||
```
|
||||
|
||||
**图源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L29-L178)
|
||||
|
||||
服务的关闭逻辑由`tokio`运行时的正常退出机制处理。当HTTP服务器停止时,`main`函数会等待代理服务完成,然后正常退出。清理任务和`agent_worker`线程也会随之停止。`init_telemetry`函数设置了全局的文本传播器,确保了`trace_id`的生成和传播,便于后续的性能分析和故障排查。
|
||||
|
||||
**本节源码**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L29-L178)
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L181-L231)
|
||||
|
||||
## 结论
|
||||
代理服务通过精心设计的架构和实现,成功地管理了AI代理的整个生命周期。它利用Rust的异步特性和类型系统,实现了高效、安全和可扩展的代理管理。与Docker管理器的集成确保了资源的隔离和安全,而异步任务调度和会话管理机制则保证了系统的高性能和实时性。错误恢复和生命周期管理策略进一步增强了系统的健壮性。通过统一的接口抽象,代理服务支持多种代理类型,为未来的扩展奠定了坚实的基础。整体而言,该服务是AI开发平台中不可或缺的核心组件,为用户提供了一个稳定、高效的AI代理运行环境。
|
||||
@@ -0,0 +1,536 @@
|
||||
# 代理运行器架构
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [lib.rs](file://crates/agent_runner/src/lib.rs)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs)
|
||||
- [model.rs](file://crates/agent_runner/src/model.rs)
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml)
|
||||
- [lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
- [lib.rs](file://crates/docker_manager/src/lib.rs)
|
||||
- [lib.rs](file://crates/pingora-proxy/src/lib.rs)
|
||||
- [lib.rs](file://crates/shared_types/src/lib.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概述](#架构概述)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
代理运行器是一个基于Rust的高性能AI代理管理平台,旨在为AI驱动的开发提供完整的代理集成解决方案。该系统通过ACP(Agent Client Protocol)协议与不同的AI代理(如Codex、Claude Code)进行通信,实现了代理生命周期管理、会话状态维护和异步任务调度等核心功能。系统采用模块化设计,通过Pingora反向代理实现高性能的请求路由,并通过Docker管理器实现资源隔离和容器化部署。代理运行器支持多代理架构,通过抽象层设计实现了不同AI代理的无缝集成。
|
||||
|
||||
## 项目结构
|
||||
代理运行器采用Rust工作区(workspace)结构,包含多个独立的crates,每个crate负责特定的功能模块。这种模块化设计提高了代码的可维护性和可扩展性。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[代理运行器] --> B[agent_runner]
|
||||
A --> C[acp_adapter]
|
||||
A --> D[claude-code-agent]
|
||||
A --> E[codex-acp-agent]
|
||||
A --> F[docker_manager]
|
||||
A --> G[pingora-proxy]
|
||||
A --> H[rcoder]
|
||||
A --> I[shared_types]
|
||||
B --> J[HTTP服务器]
|
||||
B --> K[代理服务]
|
||||
B --> L[会话管理]
|
||||
C --> M[ACP协议适配]
|
||||
F --> N[Docker容器管理]
|
||||
G --> O[反向代理]
|
||||
I --> P[共享数据类型]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [lib.rs](file://crates/agent_runner/src/lib.rs)
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml)
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml)
|
||||
|
||||
## 核心组件
|
||||
代理运行器的核心组件包括代理服务管理、会话状态维护、ACP协议适配和Docker资源管理。这些组件协同工作,实现了AI代理的全生命周期管理。
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [lib.rs](file://crates/agent_runner/src/lib.rs)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs)
|
||||
|
||||
## 架构概述
|
||||
代理运行器采用分层架构设计,从上到下分为HTTP接口层、业务逻辑层、代理服务层和基础设施层。这种分层设计确保了系统的高内聚、低耦合特性。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[HTTP接口层] --> B[业务逻辑层]
|
||||
B --> C[代理服务层]
|
||||
C --> D[基础设施层]
|
||||
A --> E[API路由]
|
||||
A --> F[请求处理]
|
||||
B --> G[会话管理]
|
||||
B --> H[状态维护]
|
||||
C --> I[ACP适配]
|
||||
C --> J[代理通信]
|
||||
D --> K[Docker管理]
|
||||
D --> L[资源隔离]
|
||||
E --> M[chat_handler]
|
||||
F --> N[agent_service]
|
||||
G --> O[session_cache]
|
||||
H --> P[AgentStatus]
|
||||
I --> Q[acp_adapter]
|
||||
J --> R[claude_code_agent]
|
||||
K --> S[docker_manager]
|
||||
L --> T[container隔离]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
- [docker_manager/src/lib.rs](file://crates/docker_manager/src/lib.rs)
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [router.rs](file://crates/agent_runner/src/router.rs)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 代理生命周期管理
|
||||
代理运行器通过`agent_worker`任务管理所有AI代理的生命周期。每个代理服务与一个项目ID关联,实现了代理的复用和资源优化。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Handler as "chat_handler"
|
||||
participant AgentWorker as "agent_worker"
|
||||
participant AgentService as "代理服务"
|
||||
Client->>Handler : POST /chat
|
||||
Handler->>AgentWorker : 发送LocalSetAgentRequest
|
||||
AgentWorker->>AgentWorker : 检查现有代理
|
||||
alt 代理存在
|
||||
AgentWorker->>AgentService : 复用现有代理
|
||||
AgentService-->>AgentWorker : 返回会话ID
|
||||
else 代理不存在
|
||||
AgentWorker->>AgentService : 创建新代理
|
||||
AgentService-->>AgentWorker : 返回会话ID
|
||||
end
|
||||
AgentWorker->>Handler : 发送ChatPromptResponse
|
||||
Handler-->>Client : 返回响应
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L58-L76)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L196-L341)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs)
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
|
||||
### 会话状态维护
|
||||
会话状态维护是代理运行器的核心功能之一,通过`SESSION_CACHE`和`PROJECT_SESSION_MAP`两个全局数据结构实现。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class SessionData {
|
||||
+command_tx : UnboundedSender~SessionCommand~
|
||||
+current_sender : Arc~Mutex~Option~Sender~UnifiedSessionMessage~~~~
|
||||
+current_cancel : Arc~Mutex~Option~CancellationToken~~~
|
||||
+new(max_size : usize) Arc~Self~
|
||||
+message_count() usize
|
||||
+create_new_connection(buffer_size : usize) Result~(Receiver~UnifiedSessionMessage~, CancellationToken)~
|
||||
+push_message(message : UnifiedSessionMessage)
|
||||
+close_current_connection()
|
||||
}
|
||||
class SessionWorker {
|
||||
-max_size : usize
|
||||
-command_rx : UnboundedReceiver~SessionCommand~
|
||||
-current_sender : Arc~Mutex~Option~Sender~UnifiedSessionMessage~~~~
|
||||
-current_cancel : Arc~Mutex~Option~CancellationToken~~~
|
||||
+spawn(max_size : usize, command_rx : UnboundedReceiver~SessionCommand~, current_sender : Arc~Mutex~Option~Sender~UnifiedSessionMessage~~~~, current_cancel : Arc~Mutex~Option~CancellationToken~~~)
|
||||
+run()
|
||||
}
|
||||
class SessionCommand {
|
||||
+Push{message : UnifiedSessionMessage}
|
||||
+Clear{ack : oneshot : : Sender~usize~}
|
||||
+MessageCount{ack : oneshot : : Sender~usize~}
|
||||
}
|
||||
SessionData --> SessionWorker : "spawn"
|
||||
SessionWorker --> SessionCommand : "处理"
|
||||
SessionData --> SessionCommand : "发送命令"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L25-L222)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L142-L171)
|
||||
|
||||
**章节来源**
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
|
||||
### ACP协议适配器
|
||||
ACP协议适配器是代理运行器与AI代理通信的核心组件,实现了ACP协议的客户端功能。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AcpAgentClient {
|
||||
+request_permission(args : RequestPermissionRequest) Result~RequestPermissionResponse, Error~
|
||||
+write_text_file(args : WriteTextFileRequest) Result~WriteTextFileResponse, Error~
|
||||
+read_text_file(args : ReadTextFileRequest) Result~ReadTextFileResponse, Error~
|
||||
+session_notification(args : SessionNotification) Result~(), Error~
|
||||
+ext_method(request : ExtRequest) Result~ExtResponse, Error~
|
||||
+ext_notification(notification : ExtNotification) Result~(), Error~
|
||||
}
|
||||
class Client {
|
||||
<<trait>>
|
||||
+request_permission(args : RequestPermissionRequest) Result~RequestPermissionResponse, Error~
|
||||
+write_text_file(args : WriteTextFileRequest) Result~WriteTextFileResponse, Error~
|
||||
+read_text_file(args : ReadTextFileRequest) Result~ReadTextFileResponse, Error~
|
||||
+session_notification(args : SessionNotification) Result~(), Error~
|
||||
+ext_method(request : ExtRequest) Result~ExtResponse, Error~
|
||||
+ext_notification(notification : ExtNotification) Result~(), Error~
|
||||
}
|
||||
AcpAgentClient --|> Client : "实现"
|
||||
class AcpConnectionInfo {
|
||||
+session_id : SessionId
|
||||
+prompt_tx : UnboundedSender~PromptRequest~
|
||||
+cancel_tx : UnboundedSender~CancelNotificationRequest~
|
||||
+stop_handle : Option~AgentStopHandleArc~
|
||||
}
|
||||
class AcpAgentService {
|
||||
<<trait>>
|
||||
+start_agent_service(chat_prompt : ChatPrompt, model_provider : Option~ModelProviderConfig~) Result~AcpConnectionInfo~
|
||||
+agent_type_name() &'static str
|
||||
}
|
||||
AcpAgentService <-- AcpConnectionInfo : "返回"
|
||||
AcpAgentClient <-- AcpConnectionInfo : "使用"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [acp_adapter/src/lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L43-L255)
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
|
||||
**章节来源**
|
||||
- [acp_adapter/src/lib.rs](file://crates/acp_adapter/src/lib.rs)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs)
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
|
||||
### 多代理支持实现
|
||||
代理运行器通过`AgentType`枚举和特征对象实现了对多种AI代理的支持,包括Claude和Codex。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AgentType {
|
||||
<<enum>>
|
||||
+Claude
|
||||
+Codex
|
||||
}
|
||||
class AcpAgentService {
|
||||
<<trait>>
|
||||
+start_agent_service(chat_prompt : ChatPrompt, model_provider : Option~ModelProviderConfig~) Result~AcpConnectionInfo~
|
||||
+agent_type_name() &'static str
|
||||
}
|
||||
AgentType --|> AcpAgentService : "实现"
|
||||
class ClaudeCodeAgent {
|
||||
+start_claude_code_acp_agent_service(chat_prompt : ChatPrompt, model_provider : Option~ModelProviderConfig~) Result~AcpConnectionInfo~
|
||||
}
|
||||
class CodexAgent {
|
||||
+start_codex_acp_agent_service(chat_prompt : ChatPrompt, model_provider : Option~ModelProviderConfig~) Result~AcpConnectionInfo~
|
||||
}
|
||||
AcpAgentService <|-- ClaudeCodeAgent : "具体实现"
|
||||
AcpAgentService <|-- CodexAgent : "具体实现"
|
||||
AgentType --> ClaudeCodeAgent : "调用"
|
||||
AgentType --> CodexAgent : "调用"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs)
|
||||
|
||||
**章节来源**
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
|
||||
### 异步任务调度
|
||||
代理运行器采用Rust的异步运行时模型,通过Tokio运行时和LocalSet实现了高效的异步任务调度。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[主异步运行时] --> B[HTTP服务器]
|
||||
A --> C[清理任务]
|
||||
A --> D[代理服务]
|
||||
D --> E[独立OS线程]
|
||||
E --> F[单线程Tokio运行时]
|
||||
F --> G[LocalSet]
|
||||
G --> H[agent_worker]
|
||||
H --> I[ACP连接]
|
||||
H --> J[通道处理器]
|
||||
B --> K[请求处理]
|
||||
K --> L[发送LocalSetAgentRequest]
|
||||
L --> H
|
||||
C --> M[定期清理]
|
||||
M --> N[清理空闲会话]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L58-L76)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L196-L341)
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
|
||||
### 资源隔离策略
|
||||
代理运行器通过Docker管理器实现了严格的资源隔离,确保每个AI代理在独立的容器环境中运行。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class DockerManager {
|
||||
+new(config : DockerManagerConfig) DockerResult~Self~
|
||||
+create_container(config : ContainerConfig) DockerResult~Container~
|
||||
+start_container(container_id : &str) DockerResult~()
|
||||
+stop_container(container_id : &str) DockerResult~()
|
||||
+remove_container(container_id : &str) DockerResult~()
|
||||
+list_containers() DockerResult~Vec~ContainerInfo~~
|
||||
}
|
||||
class ContainerConfig {
|
||||
+image : String
|
||||
+name : String
|
||||
+ports : Vec~PortMapping~
|
||||
+volumes : Vec~VolumeMapping~
|
||||
+env_vars : Vec~EnvVar~
|
||||
+network_mode : String
|
||||
}
|
||||
class PortMapping {
|
||||
+host_port : u16
|
||||
+container_port : u16
|
||||
}
|
||||
class VolumeMapping {
|
||||
+host_path : String
|
||||
+container_path : String
|
||||
}
|
||||
class EnvVar {
|
||||
+name : String
|
||||
+value : String
|
||||
}
|
||||
DockerManager --> ContainerConfig : "使用"
|
||||
ContainerConfig --> PortMapping : "包含"
|
||||
ContainerConfig --> VolumeMapping : "包含"
|
||||
ContainerConfig --> EnvVar : "包含"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [docker_manager/src/lib.rs](file://crates/docker_manager/src/lib.rs)
|
||||
- [docker_manager/src/manager.rs](file://crates/docker_manager/src/manager.rs)
|
||||
|
||||
**章节来源**
|
||||
- [docker_manager/src/lib.rs](file://crates/docker_manager/src/lib.rs)
|
||||
|
||||
### 错误恢复机制
|
||||
代理运行器实现了多层次的错误恢复机制,确保系统的稳定性和可靠性。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[错误发生] --> B{错误类型}
|
||||
B --> C[可恢复错误]
|
||||
B --> D[不可恢复错误]
|
||||
C --> E[重试机制]
|
||||
E --> F[指数退避]
|
||||
F --> G[最大重试次数]
|
||||
G --> H{重试成功?}
|
||||
H --> |是| I[继续执行]
|
||||
H --> |否| J[降级处理]
|
||||
D --> K[优雅降级]
|
||||
K --> L[返回默认值]
|
||||
L --> M[记录错误日志]
|
||||
M --> N[发送告警]
|
||||
I --> O[正常流程]
|
||||
J --> O
|
||||
N --> O
|
||||
P[监控系统] --> Q[错误指标]
|
||||
Q --> R[告警系统]
|
||||
R --> S[运维人员]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L31-L232)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs#L142-L161)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L235-L247)
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
|
||||
### 可扩展性考虑
|
||||
代理运行器的设计充分考虑了可扩展性,通过模块化架构和配置驱动的方式支持未来的功能扩展。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[核心框架] --> B[插件系统]
|
||||
A --> C[配置管理]
|
||||
A --> D[服务发现]
|
||||
B --> E[新代理类型]
|
||||
B --> F[新协议适配]
|
||||
B --> G[新存储后端]
|
||||
C --> H[动态配置]
|
||||
C --> I[热更新]
|
||||
C --> J[配置验证]
|
||||
D --> K[服务注册]
|
||||
D --> L[健康检查]
|
||||
D --> M[负载均衡]
|
||||
A --> N[监控系统]
|
||||
N --> O[指标收集]
|
||||
N --> P[日志聚合]
|
||||
N --> Q[分布式追踪]
|
||||
O --> R[Prometheus]
|
||||
P --> S[ELK]
|
||||
Q --> T[OpenTelemetry]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml)
|
||||
- [config.rs](file://crates/agent_runner/src/config.rs)
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
|
||||
**章节来源**
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml)
|
||||
- [config.rs](file://crates/agent_runner/src/config.rs)
|
||||
|
||||
### 性能监控
|
||||
代理运行器集成了全面的性能监控系统,通过OpenTelemetry实现分布式追踪和指标收集。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[应用代码] --> B[Tracing]
|
||||
B --> C[OpenTelemetry]
|
||||
C --> D[Exporter]
|
||||
D --> E[Jaeger]
|
||||
D --> F[Prometheus]
|
||||
D --> G[Zipkin]
|
||||
A --> H[Metrics]
|
||||
H --> I[Counter]
|
||||
H --> J[Histogram]
|
||||
H --> K[Gauge]
|
||||
I --> L[请求计数]
|
||||
J --> M[响应时间]
|
||||
K --> N[并发数]
|
||||
A --> O[Logging]
|
||||
O --> P[JSON日志]
|
||||
P --> Q[ELK]
|
||||
C --> R[Trace Context]
|
||||
R --> S[跨服务追踪]
|
||||
T[监控面板] --> U[指标可视化]
|
||||
U --> V[告警规则]
|
||||
V --> W[通知系统]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs#L181-L231)
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml#L65-L69)
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml)
|
||||
|
||||
### 与docker_manager的集成
|
||||
代理运行器与Docker管理器深度集成,实现了容器化部署和资源管理。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant AgentRunner as "代理运行器"
|
||||
participant DockerManager as "Docker管理器"
|
||||
participant DockerDaemon as "Docker守护进程"
|
||||
AgentRunner->>DockerManager : 创建容器请求
|
||||
DockerManager->>DockerDaemon : 创建容器
|
||||
DockerDaemon-->>DockerManager : 容器ID
|
||||
DockerManager->>DockerDaemon : 启动容器
|
||||
DockerDaemon-->>DockerManager : 启动成功
|
||||
DockerManager-->>AgentRunner : 容器准备就绪
|
||||
AgentRunner->>DockerManager : 发送命令
|
||||
DockerManager->>DockerDaemon : 执行命令
|
||||
DockerDaemon-->>DockerManager : 命令输出
|
||||
DockerManager-->>AgentRunner : 返回结果
|
||||
AgentRunner->>DockerManager : 停止容器
|
||||
DockerManager->>DockerDaemon : 停止容器
|
||||
DockerDaemon-->>DockerManager : 停止成功
|
||||
DockerManager-->>AgentRunner : 清理完成
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [docker_manager/src/lib.rs](file://crates/docker_manager/src/lib.rs)
|
||||
- [docker_manager/src/manager.rs](file://crates/docker_manager/src/manager.rs)
|
||||
|
||||
**章节来源**
|
||||
- [docker_manager/src/lib.rs](file://crates/docker_manager/src/lib.rs)
|
||||
|
||||
## 依赖分析
|
||||
代理运行器的依赖关系清晰,各模块之间的耦合度低,便于维护和扩展。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[agent_runner] --> B[acp_adapter]
|
||||
A --> C[shared_types]
|
||||
A --> D[pingora-proxy]
|
||||
A --> E[claude-code-agent]
|
||||
A --> F[codex-acp-agent]
|
||||
A --> G[docker_manager]
|
||||
B --> H[agent-client-protocol]
|
||||
C --> I[grpc]
|
||||
D --> J[axum]
|
||||
D --> K[reqwest]
|
||||
E --> L[agent-client-protocol]
|
||||
F --> M[agent-client-protocol]
|
||||
G --> N[bollard]
|
||||
A --> O[tokio]
|
||||
A --> P[axum]
|
||||
A --> Q[tracing]
|
||||
A --> R[serde]
|
||||
A --> S[dashmap]
|
||||
O --> T[异步运行时]
|
||||
P --> U[Web框架]
|
||||
Q --> V[日志追踪]
|
||||
R --> W[序列化]
|
||||
S --> X[并发映射]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml)
|
||||
- [Cargo.toml](file://crates/acp_adapter/Cargo.toml)
|
||||
- [Cargo.toml](file://crates/pingora-proxy/Cargo.toml)
|
||||
|
||||
**章节来源**
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml)
|
||||
|
||||
## 性能考虑
|
||||
代理运行器在设计时充分考虑了性能因素,采用了多种优化策略。
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
|
||||
## 故障排除指南
|
||||
当代理运行器出现问题时,可以按照以下步骤进行排查。
|
||||
|
||||
**章节来源**
|
||||
- [main.rs](file://crates/agent_runner/src/main.rs)
|
||||
- [acp_agent.rs](file://crates/agent_runner/src/proxy_agent/acp_agent.rs)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
|
||||
## 结论
|
||||
代理运行器通过精心设计的架构和实现,提供了一个高性能、可扩展的AI代理管理平台。系统采用模块化设计,各组件职责清晰,耦合度低。通过ACP协议适配器,实现了与不同AI代理的无缝集成。异步任务调度和资源隔离策略确保了系统的高效性和稳定性。全面的监控和错误恢复机制为系统的可靠运行提供了保障。整体架构具有良好的可扩展性,能够适应未来的需求变化。
|
||||
@@ -0,0 +1,356 @@
|
||||
# 会话缓存机制
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs)
|
||||
- [model.rs](file://crates/agent_runner/src/model.rs)
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件系统性阐述 session_cache 模块如何管理 AI 代理会话状态,涵盖缓存数据结构设计、生命周期管理策略、并发访问控制机制、缓存项的创建/更新/清理流程,以及与代理服务的交互模式。文档还记录内存使用特征、过期策略与性能优化措施,并提供聊天交互与进度查询的实际使用场景示例。
|
||||
|
||||
## 项目结构
|
||||
围绕会话缓存的关键文件组织如下:
|
||||
- 会话缓存核心:session_cache.rs
|
||||
- SSE 进度通知:agent_session_notification.rs
|
||||
- 聊天入口与会话清理:chat_handler.rs
|
||||
- 清理任务与资源回收:cleanup_task.rs
|
||||
- 统一消息模型与通知:agent_session_notify.rs、model.rs
|
||||
- 代理侧会话通知转发:proxy_agent/mod.rs
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "会话缓存层"
|
||||
SC["SessionData<br/>环形缓冲区+命令通道"]
|
||||
PC["PROJECT_SESSION_MAP<br/>项目-会话映射"]
|
||||
GC["全局缓存 SESSION_CACHE<br/>按session_id索引"]
|
||||
end
|
||||
subgraph "代理侧"
|
||||
AC["AcpAgentClient<br/>session_notification回调"]
|
||||
PRJ["PROJECT_AND_AGENT_INFO_MAP<br/>项目-代理状态"]
|
||||
end
|
||||
subgraph "HTTP处理层"
|
||||
SSE["SSE 进度接口<br/>agent_session_notification.rs"]
|
||||
CHAT["聊天接口<br/>chat_handler.rs"]
|
||||
end
|
||||
subgraph "清理与回收"
|
||||
CLEAN["清理任务<br/>cleanup_task.rs"]
|
||||
end
|
||||
AC --> |"推送通知"| SC
|
||||
SSE --> |"建立SSE并创建SessionData"| GC
|
||||
CHAT --> |"清理旧会话/新会话"| GC
|
||||
CLEAN --> |"定期扫描并清理"| GC
|
||||
CLEAN --> |"清理映射"| PC
|
||||
AC --> |"回填request_id上下文"| AC
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [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)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L211-L258)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
|
||||
章节来源
|
||||
- [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)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L211-L258)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
|
||||
## 核心组件
|
||||
- 全局会话缓存 SESSION_CACHE:以 session_id 为键,存储每个会话的 SessionData。
|
||||
- 项目-会话映射 PROJECT_SESSION_MAP:确保同一项目仅有一个活跃会话,变更时自动清理旧会话。
|
||||
- SessionData:封装环形缓冲区、命令通道、当前发送器与取消令牌,负责消息入队、实时推送与连接关闭。
|
||||
- SessionWorker:后台工作者,消费命令通道,维护环形缓冲区,按需实时推送消息。
|
||||
- 统一会话消息 UnifiedSessionMessage 与通知 SessionNotify:标准化消息格式,便于跨组件传递。
|
||||
- SSE 进度接口 agent_session_notification:为前端建立 SSE 连接,实时推送会话状态。
|
||||
- 清理任务 cleanup_task:定期扫描并清理闲置代理与孤立会话。
|
||||
|
||||
章节来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L1-L180)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L1-L120)
|
||||
|
||||
## 架构总览
|
||||
会话缓存的整体交互链路如下:
|
||||
- 代理侧 AcpAgentClient 在收到 session_notification 后,构造 SessionNotify 并调用 push_session_update,统一转为 UnifiedSessionMessage 写入 SessionData。
|
||||
- SSE 进度接口 agent_session_notification 为每个 session_id 创建新的 SessionData 并插入 SESSION_CACHE,随后创建连接并持续推送消息。
|
||||
- 聊天接口 chat_handler 在发起新请求前,会清理旧会话,确保全新开始。
|
||||
- 清理任务定期扫描 PROJECT_SESSION_MAP 与 SESSION_CACHE,清理孤立会话与闲置代理。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Agent as "代理(AcpAgentClient)"
|
||||
participant Cache as "SessionData/Worker"
|
||||
participant SSE as "SSE接口"
|
||||
participant Front as "前端"
|
||||
Agent->>Cache : "push_session_update(SessionNotify)"
|
||||
Cache->>Cache : "SessionWorker : Push消息到环形缓冲区"
|
||||
Cache->>Cache : "尝试实时推送至当前发送器"
|
||||
SSE->>Cache : "create_new_connection(新建SessionData)"
|
||||
Cache-->>SSE : "返回接收端+取消令牌"
|
||||
loop "SSE循环"
|
||||
Cache-->>SSE : "推送UnifiedSessionMessage"
|
||||
SSE-->>Front : "SSE事件"
|
||||
end
|
||||
Note over SSE,Cache : "取消令牌触发或发送端关闭时,SSE断开"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L105-L221)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 会话缓存数据结构与生命周期
|
||||
- 数据结构设计
|
||||
- SESSION_CACHE:全局 DashMap,键为 session_id,值为 Arc<SessionData>,保证并发安全与零拷贝共享。
|
||||
- SessionData:包含命令发送端、当前发送器与取消令牌的互斥保护,避免竞态。
|
||||
- SessionWorker:持有环形缓冲区(HeapRb),按最大容量维护消息队列,实时推送失败时自动清理当前发送器。
|
||||
- PROJECT_SESSION_MAP:全局 DashMap,键为 project_id,值为 session_id,确保同一项目仅有一个活跃会话。
|
||||
- 生命周期管理
|
||||
- 新建:SSE 接口为每个 session_id 创建新的 SessionData 并插入 SESSION_CACHE,覆盖旧值,确保“全新开始”。
|
||||
- 销毁:SessionWorker 退出时,SessionData 仍驻留缓存;清理任务通过移除映射与缓存条目实现资源回收。
|
||||
- 连接关闭:主动触发 CancellationToken 或显式关闭发送端,使接收端 recv() 返回 None,SSE 自然断开。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class SessionData {
|
||||
+command_tx
|
||||
+current_sender
|
||||
+current_cancel
|
||||
+new(max_size)
|
||||
+create_new_connection(buffer_size)
|
||||
+push_message(message)
|
||||
+close_current_connection()
|
||||
+message_count()
|
||||
}
|
||||
class SessionWorker {
|
||||
-max_size
|
||||
-command_rx
|
||||
-current_sender
|
||||
-current_cancel
|
||||
+spawn(...)
|
||||
+run()
|
||||
}
|
||||
class UnifiedSessionMessage {
|
||||
+session_id
|
||||
+message_type
|
||||
+sub_type
|
||||
+data
|
||||
+timestamp
|
||||
+heartbeat(session_id)
|
||||
}
|
||||
class SessionNotify {
|
||||
+to_unified_message()
|
||||
}
|
||||
SessionData --> SessionWorker : "spawn并消费命令"
|
||||
SessionWorker --> UnifiedSessionMessage : "生产消息"
|
||||
SessionNotify --> UnifiedSessionMessage : "转换"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L24-L221)
|
||||
- [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#L1-L140)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L1-L180)
|
||||
|
||||
### 并发访问控制机制
|
||||
- 全局缓存与映射
|
||||
- 使用 LazyLock 初始化 DashMap,保证线程安全与延迟初始化。
|
||||
- SessionData 内部对 current_sender/current_cancel 使用 Mutex 包裹,避免多处同时写入导致的竞争。
|
||||
- 命令通道
|
||||
- SessionData 内部使用无界 mpsc 通道接收命令,SessionWorker 异步消费,避免阻塞代理通知路径。
|
||||
- 取消令牌
|
||||
- 每次创建新连接都会生成新的 CancellationToken,旧连接一旦被新连接抢占或用户取消,立即触发取消,确保旧连接快速失效。
|
||||
|
||||
章节来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
|
||||
### 缓存项创建、更新与清理流程
|
||||
- 创建
|
||||
- SSE 接口为 session_id 创建 SessionData 并插入 SESSION_CACHE,同时创建连接并返回接收端与取消令牌。
|
||||
- 更新
|
||||
- 代理侧 session_notification 回调将 SessionUpdate 转为 SessionNotify,再转为 UnifiedSessionMessage,通过 SessionData.push_message 入队。
|
||||
- SessionWorker 将消息写入环形缓冲区,并尝试实时推送至当前发送器;若推送失败则清空当前发送器,避免脏写。
|
||||
- 清理
|
||||
- SSE 接口:当取消令牌被触发或发送端关闭时,SSE 断开,旧 SessionData 仍保留,等待清理任务回收。
|
||||
- 清理任务:扫描 PROJECT_SESSION_MAP 与 SESSION_CACHE,移除孤立会话与空闲代理,减少内存占用。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["开始"]) --> Create["SSE接口创建SessionData并插入缓存"]
|
||||
Create --> Push["代理推送SessionNotify->UnifiedSessionMessage"]
|
||||
Push --> Buffer["SessionWorker写入环形缓冲区"]
|
||||
Buffer --> Realtime{"实时推送成功?"}
|
||||
Realtime --> |是| SSELoop["SSE循环推送消息"]
|
||||
Realtime --> |否| ClearSender["清空当前发送器"]
|
||||
SSELoop --> Cancel{"取消令牌触发/发送端关闭?"}
|
||||
Cancel --> |是| Close["SSE断开,旧SessionData保留"]
|
||||
Cancel --> |否| Heartbeat["周期心跳"]
|
||||
Close --> Cleanup["清理任务扫描并移除"]
|
||||
Cleanup --> End(["结束"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L105-L221)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
|
||||
章节来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L105-L221)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
|
||||
### 与代理服务的交互模式
|
||||
- 代理侧 AcpAgentClient 实现 session_notification 回调,将 ACP SessionUpdate 转为 AgentSessionUpdate,再包装为 SessionNotify,最终调用 push_session_update 写入缓存。
|
||||
- 若 SessionNotification.meta 中未携带 request_id,则通过 PROJECT_AND_AGENT_INFO_MAP 查找 project_id,再从 SESSION_REQUEST_CONTEXT 获取 request_id,确保消息携带 request_id 以便前端关联。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant ACP as "ACP客户端"
|
||||
participant Client as "AcpAgentClient"
|
||||
participant Cache as "push_session_update"
|
||||
participant Worker as "SessionWorker"
|
||||
participant SSE as "SSE接口"
|
||||
ACP->>Client : "session_notification(SessionUpdate)"
|
||||
Client->>Client : "提取/回填request_id"
|
||||
Client->>Cache : "SessionNotify -> UnifiedSessionMessage"
|
||||
Cache->>Worker : "命令 : Push"
|
||||
Worker->>Worker : "写入环形缓冲区"
|
||||
Worker->>SSE : "尝试实时推送"
|
||||
SSE-->>Client : "SSE循环接收并转发"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L231-L257)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
|
||||
章节来源
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L231-L257)
|
||||
|
||||
### 过期策略与内存使用特征
|
||||
- 过期策略
|
||||
- 心跳消息:SSE 接口在建立连接后立即发送心跳,并按周期发送心跳事件,用于维持连接活性。
|
||||
- 取消与断开:取消令牌触发或发送端关闭时,SSE 断开;SessionWorker 退出后,SessionData 仍驻留缓存,等待清理任务回收。
|
||||
- 孤立会话清理:清理任务扫描 SESSION_CACHE 中不在活跃映射中的 session_id,若消息计数大于 0 则移除条目,否则标记为空会话清理。
|
||||
- 内存使用特征
|
||||
- 环形缓冲区:按最大容量维护最近消息,满时淘汰最旧消息,避免无限增长。
|
||||
- 连接级缓存:每次 SSE 连接都会创建新的 SessionData,覆盖旧值,确保不会累积历史消息。
|
||||
- 映射表:PROJECT_SESSION_MAP 仅保存活跃映射,清理任务移除无效映射,降低内存压力。
|
||||
|
||||
章节来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L385-L475)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L173-L221)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
|
||||
### 性能优化措施
|
||||
- 极简设计
|
||||
- SessionData 直接共享当前发送器与取消令牌,避免命令传递带来的额外开销。
|
||||
- SessionWorker 直接从共享状态获取发送器,实时推送失败时立即清空,避免后续无效尝试。
|
||||
- 通道与锁粒度
|
||||
- 使用无界命令通道与细粒度 Mutex,降低锁竞争概率。
|
||||
- 心跳与断开
|
||||
- 心跳事件降低连接空闲时的网络压力;取消令牌与发送端关闭确保旧连接快速失效,避免资源浪费。
|
||||
- 清理策略
|
||||
- 定期清理孤立会话与闲置代理,减少缓存与映射膨胀。
|
||||
|
||||
章节来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L105-L221)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L156-L241)
|
||||
|
||||
## 依赖关系分析
|
||||
- 组件耦合
|
||||
- session_cache 与 agent_session_notification:SSE 接口依赖 SessionData 的创建与连接能力。
|
||||
- proxy_agent/mod 与 session_cache:代理侧通知通过 push_session_update 写入缓存,二者通过统一消息模型解耦。
|
||||
- chat_handler 与 session_cache:聊天接口在发起新请求前清理旧会话,确保全新开始。
|
||||
- cleanup_task 与 session_cache/PROJECT_SESSION_MAP:清理孤立会话与映射,避免资源泄漏。
|
||||
- 外部依赖
|
||||
- DashMap 提供并发安全的哈希表。
|
||||
- ringbuf HeapRb 提供高效环形缓冲区。
|
||||
- tokio mpsc 提供异步通道与取消令牌。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A["agent_session_notification.rs"] --> B["session_cache.rs"]
|
||||
C["proxy_agent/mod.rs"] --> B
|
||||
D["chat_handler.rs"] --> B
|
||||
E["cleanup_task.rs"] --> B
|
||||
E --> F["PROJECT_SESSION_MAP"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L140)
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L211-L258)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
|
||||
章节来源
|
||||
- [model.rs](file://crates/agent_runner/src/model.rs#L1-L12)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L1-L180)
|
||||
|
||||
## 性能考量
|
||||
- 环形缓冲区容量:根据业务负载调整最大容量,平衡内存占用与消息保留范围。
|
||||
- 实时推送失败处理:推送失败时清空发送器,避免后续无效尝试;必要时增加接收端缓冲大小。
|
||||
- 心跳频率:合理的心跳间隔可在保持连接活性与网络开销之间取得平衡。
|
||||
- 清理周期:清理任务的间隔与闲置超时可根据系统负载动态调整,避免过于频繁或过少。
|
||||
|
||||
## 故障排查指南
|
||||
- SSE 连接无法建立
|
||||
- 检查 SSE 接口是否成功创建 SessionData 并插入 SESSION_CACHE。
|
||||
- 确认 create_new_connection 是否返回接收端与取消令牌。
|
||||
- 实时消息未到达前端
|
||||
- 检查 SessionWorker 是否成功写入环形缓冲区与尝试实时推送。
|
||||
- 若推送失败,确认当前发送器是否被清空,以及取消令牌是否被触发。
|
||||
- 旧会话消息残留
|
||||
- 确认 SSE 接口是否为每个 session_id 创建新的 SessionData 并覆盖旧值。
|
||||
- 检查清理任务是否正确扫描并移除孤立会话。
|
||||
- 代理通知未写入缓存
|
||||
- 确认 AcpAgentClient 的 session_notification 回调是否正确提取 request_id 并调用 push_session_update。
|
||||
- 检查 SessionData 是否存在且未被清理。
|
||||
|
||||
章节来源
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L105-L221)
|
||||
- [proxy_agent/mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L240)
|
||||
- [cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L156-L241)
|
||||
|
||||
## 结论
|
||||
session_cache 模块通过 SessionData + SessionWorker + 环形缓冲区的组合,实现了高并发、低开销的会话状态缓存与实时推送。配合 SSE 进度接口、聊天入口清理策略与定期清理任务,系统在保证消息实时性的同时,有效控制内存与资源占用,满足 AI 代理会话状态管理的需求。
|
||||
|
||||
## 附录
|
||||
|
||||
### 实际使用场景示例
|
||||
- 聊天交互
|
||||
- 前端调用聊天接口,后端为项目生成或复用会话,清理旧会话后启动代理任务,SSE 接口实时推送执行进度。
|
||||
- 进度查询
|
||||
- 前端通过 /agent/progress/{session_id} 建立 SSE 连接,接收 prompt_start、agent_message_chunk、tool_call 等事件,结合心跳维持连接活性。
|
||||
|
||||
章节来源
|
||||
- [chat_handler.rs](file://crates/agent_runner/src/handler/chat_handler.rs#L176-L320)
|
||||
- [agent_session_notification.rs](file://crates/agent_runner/src/handler/agent_session_notification.rs#L355-L483)
|
||||
314
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/代理运行器架构/清理任务.md
Normal file
314
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/代理运行器架构/清理任务.md
Normal file
@@ -0,0 +1,314 @@
|
||||
# 清理任务
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs)
|
||||
- [crates/rcoder/src/proxy_agent/docker_container_agent.rs](file://crates/rcoder/src/proxy_agent/docker_container_agent.rs)
|
||||
- [crates/rcoder/src/proxy_agent/port_manager.rs](file://crates/rcoder/src/proxy_agent/port_manager.rs)
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs)
|
||||
- [crates/docker_manager/src/container_stop.rs](file://crates/docker_manager/src/container_stop.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向“清理任务”模块,系统性阐述其如何在代理终止后回收系统资源,包括定时调度、闲置检测、容器与端口释放、SSE会话清理、孤立容器扫描、超时与错误处理策略,以及与代理停止处理器的协作方式。文档同时提供配置项说明、性能影响评估与最佳实践建议,帮助读者在不同场景下正确使用与扩展该模块。
|
||||
|
||||
## 项目结构
|
||||
清理任务位于 rcoder 与 agent_runner 两个子 crate 中,分别针对不同的运行形态与状态管理:
|
||||
- rcoder 清理任务:面向基于容器的代理,具备更完善的资源回收与超时控制,包含孤立容器扫描与端口释放。
|
||||
- agent_runner 清理任务:面向本地进程型代理,采用 RAII 模式,通过移除映射触发生命周期守卫自动清理。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "rcoder 清理任务"
|
||||
RC_Config["CleanupConfig<br/>闲置超时/清理间隔/Docker停止超时"]
|
||||
RC_AgentCleaner["AgentCleaner<br/>扫描/清理/统计"]
|
||||
RC_State["AppState<br/>project_and_agent_map/sessions"]
|
||||
RC_Docker["DockerManager<br/>统一停止接口"]
|
||||
RC_PortMgr["PortManager<br/>端口分配/释放"]
|
||||
RC_CleanupTask["start_cleanup_task()"]
|
||||
end
|
||||
subgraph "agent_runner 清理任务"
|
||||
AR_Config["CleanupConfig<br/>闲置超时/清理间隔"]
|
||||
AR_AgentCleaner["AgentCleaner<br/>扫描/清理/统计"]
|
||||
AR_Maps["PROJECT_AND_AGENT_INFO_MAP<br/>SESSION_CACHE/PROJECT_SESSION_MAP"]
|
||||
AR_CleanupTask["start_cleanup_task()"]
|
||||
end
|
||||
subgraph "代理停止处理器"
|
||||
StopGuard["AgentLifecycleGuard<br/>Drop自动清理"]
|
||||
end
|
||||
RC_AgentCleaner --> RC_State
|
||||
RC_AgentCleaner --> RC_Docker
|
||||
RC_AgentCleaner --> RC_PortMgr
|
||||
RC_CleanupTask --> RC_AgentCleaner
|
||||
AR_AgentCleaner --> AR_Maps
|
||||
AR_CleanupTask --> AR_AgentCleaner
|
||||
StopGuard -.协作.-> AR_AgentCleaner
|
||||
StopGuard -.协作.-> RC_AgentCleaner
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L67-L106)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L18-L36)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L21-L32)
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs#L26-L36)
|
||||
- [crates/rcoder/src/proxy_agent/port_manager.rs](file://crates/rcoder/src/proxy_agent/port_manager.rs#L1-L20)
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L67-L106)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L18-L36)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L21-L32)
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs#L26-L36)
|
||||
- [crates/rcoder/src/proxy_agent/port_manager.rs](file://crates/rcoder/src/proxy_agent/port_manager.rs#L1-L20)
|
||||
|
||||
## 核心组件
|
||||
- 清理配置 CleanupConfig
|
||||
- rcoder 版本包含闲置超时、清理间隔、Docker 停止超时;agent_runner 版本仅包含闲置超时与清理间隔。
|
||||
- 清理统计 CleanupStats
|
||||
- 记录清理总量、成功/失败数、孤立会话/SSE 消息清理数与最后清理时间。
|
||||
- AgentCleaner
|
||||
- 扫描闲置代理、清理孤立会话、销毁容器、释放端口、移除映射、触发生命周期守卫 Drop。
|
||||
- AgentLifecycleGuard(代理停止处理器)
|
||||
- 通过 Drop 自动清理资源,保证容器、进程、通道等资源得到回收。
|
||||
- 端口管理 PortManager
|
||||
- 在容器销毁时释放端口,避免端口泄漏。
|
||||
- DockerManager 统一停止接口
|
||||
- 提供运行时清理策略,支持优雅停止与强制停止,配合超时控制。
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L67-L106)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L18-L36)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L21-L32)
|
||||
- [crates/rcoder/src/proxy_agent/port_manager.rs](file://crates/rcoder/src/proxy_agent/port_manager.rs#L1-L20)
|
||||
- [crates/docker_manager/src/container_stop.rs](file://crates/docker_manager/src/container_stop.rs#L252-L269)
|
||||
|
||||
## 架构总览
|
||||
清理任务以“定时轮询 + RAII 回收”的方式工作:
|
||||
- 定时器按清理间隔触发清理流程。
|
||||
- 扫描阶段识别 Idle 状态且超时的代理,同时清理孤立会话与 SSE 消息。
|
||||
- 对于 rcoder 场景,先销毁容器并释放端口,再移除映射,触发生命周期守卫 Drop 完成其余资源回收。
|
||||
- 对于 agent_runner 场景,直接移除映射,生命周期守卫 Drop 触发资源清理。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Timer as "定时器(interval)"
|
||||
participant Cleaner as "AgentCleaner"
|
||||
participant State as "AppState/Maps"
|
||||
participant Docker as "DockerManager"
|
||||
participant Guard as "AgentLifecycleGuard"
|
||||
participant Port as "PortManager"
|
||||
Timer->>Cleaner : tick()
|
||||
Cleaner->>State : 读取project_and_agent_map/sessions
|
||||
Cleaner->>Cleaner : 扫描Idle且超时的代理
|
||||
alt rcoder场景
|
||||
Cleaner->>Docker : 停止容器(runtime_cleanup)
|
||||
Docker-->>Cleaner : 结果
|
||||
Cleaner->>Port : 释放端口
|
||||
Port-->>Cleaner : 完成
|
||||
end
|
||||
Cleaner->>State : 原子性移除映射(entry.remove_entry)
|
||||
State-->>Guard : Drop触发自动清理
|
||||
Cleaner-->>Timer : 统计与日志
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L787-L815)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L278-L292)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L236-L292)
|
||||
- [crates/rcoder/src/proxy_agent/port_manager.rs](file://crates/rcoder/src/proxy_agent/port_manager.rs#L51-L59)
|
||||
- [crates/docker_manager/src/container_stop.rs](file://crates/docker_manager/src/container_stop.rs#L252-L269)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 定时调度与清理流程
|
||||
- rcoder 清理任务
|
||||
- 使用 tokio::time::interval 控制清理间隔,每次清理前为整个清理流程设置超时上限,避免长时间阻塞。
|
||||
- 清理流程包含:孤立会话清理、代理扫描与判定、容器销毁与端口释放、映射移除、生命周期守卫 Drop、统计更新。
|
||||
- agent_runner 清理任务
|
||||
- 同样使用 interval 驱动,但不涉及容器销毁与端口释放,直接移除映射触发 Drop。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["定时tick"]) --> Scan["扫描project_and_agent_map"]
|
||||
Scan --> Filter{"Idle且超时?"}
|
||||
Filter -- 否 --> NextTick["等待下次tick"]
|
||||
Filter -- 是 --> Cleanup["执行清理"]
|
||||
Cleanup --> RC{"rcoder场景?"}
|
||||
RC -- 是 --> Stop["停止容器(runtime_cleanup)"]
|
||||
Stop --> Release["释放端口"]
|
||||
RC -- 否 --> Remove["移除映射(entry.remove_entry)"]
|
||||
Release --> Remove
|
||||
Remove --> Drop["生命周期守卫Drop自动清理"]
|
||||
Drop --> Stats["更新统计/日志"]
|
||||
Stats --> NextTick
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L787-L815)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L278-L292)
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L787-L815)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L278-L292)
|
||||
|
||||
### 闲置检测与保护期
|
||||
- 闲置超时判定:比较 last_activity 与当前时间,超过 idle_timeout 则视为可清理。
|
||||
- 保护期策略:新增最小保护时间(例如容器创建后5分钟内不清理),避免刚创建的容器被误清理。
|
||||
- 缓冲时间:在 rcoder 版本中对 idle_timeout 添加1秒缓冲,降低时间误差导致的误判。
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L136-L200)
|
||||
|
||||
### 资源释放流程
|
||||
- rcoder 场景
|
||||
- 容器销毁:通过统一运行时清理接口停止容器,支持优雅停止与强制停止。
|
||||
- 端口释放:若容器存在端口绑定,清理时释放对应端口。
|
||||
- 映射移除:使用 DashMap 的 Entry API 原子性移除,触发生命周期守卫 Drop。
|
||||
- agent_runner 场景
|
||||
- 直接移除映射,生命周期守卫 Drop 自动清理子进程、stderr 任务等资源。
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L643-L731)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L243-L276)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L236-L292)
|
||||
- [crates/rcoder/src/proxy_agent/port_manager.rs](file://crates/rcoder/src/proxy_agent/port_manager.rs#L51-L59)
|
||||
- [crates/docker_manager/src/container_stop.rs](file://crates/docker_manager/src/container_stop.rs#L252-L269)
|
||||
|
||||
### SSE 会话与孤立会话清理
|
||||
- 扫描活跃会话集合,定位不在活跃映射中的会话作为“孤立会话”,清理其缓存与消息。
|
||||
- 统计孤立会话数量与清理的 SSE 消息数量,便于监控与审计。
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L202-L246)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L81-L154)
|
||||
|
||||
### 孤立容器扫描与清理(rcoder)
|
||||
- 通过 DockerManager 列出匹配模式的容器,快速筛选 MAP 中缺失的“孤立容器”。
|
||||
- 限制单次清理数量与总超时,避免阻塞主清理流程。
|
||||
- 并行清理多个孤立容器,提升效率。
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L431-L602)
|
||||
|
||||
### 与代理停止处理器的协作
|
||||
- 生命周期守卫在 Drop 时自动清理资源,确保即使清理任务未及时触发,也能回收资源。
|
||||
- rcoder 场景下,清理任务优先销毁容器并释放端口,再移除映射,保证一致性。
|
||||
- agent_runner 场景下,清理任务移除映射即可,守卫负责清理本地资源。
|
||||
|
||||
章节来源
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L236-L292)
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L643-L731)
|
||||
|
||||
### 超时处理与重试机制
|
||||
- 整体清理超时:为一次完整的清理周期设置超时上限,超时后强制结束,避免阻塞。
|
||||
- 单次清理超时:对容器销毁、孤立容器清理等关键步骤设置超时,超时后记录告警并继续后续流程。
|
||||
- 重试策略:未实现显式的重试;遇到超时或错误时记录日志并继续,保证清理任务持续运行。
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L787-L815)
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L431-L453)
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L540-L599)
|
||||
|
||||
### 日志记录实践
|
||||
- 关键节点均输出 info/warn/debug/error 日志,包含项目ID、状态、耗时、清理结果等。
|
||||
- 对超时、失败、保护期内跳过等情况进行明确标注,便于问题定位与审计。
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L407-L419)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L214-L232)
|
||||
|
||||
## 依赖分析
|
||||
- 清理任务依赖
|
||||
- rcoder:AppState(DashMap)、DockerManager、PortManager、AgentLifecycleGuard。
|
||||
- agent_runner:全局映射(PROJECT_AND_AGENT_INFO_MAP、SESSION_CACHE、PROJECT_SESSION_MAP)、AgentLifecycleGuard。
|
||||
- 外部依赖
|
||||
- DockerManager 提供统一的容器停止接口,支持运行时清理策略。
|
||||
- DashMap 提供并发安全的映射与原子性 Entry API,保障清理过程的一致性。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Cleanup["AgentCleaner"] --> State["AppState/DashMap"]
|
||||
Cleanup --> Docker["DockerManager"]
|
||||
Cleanup --> Port["PortManager"]
|
||||
Cleanup --> Guard["AgentLifecycleGuard"]
|
||||
Docker --> Stop["runtime_cleanup_container"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L108-L113)
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs#L26-L36)
|
||||
- [crates/docker_manager/src/container_stop.rs](file://crates/docker_manager/src/container_stop.rs#L252-L269)
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/router.rs](file://crates/rcoder/src/router.rs#L26-L36)
|
||||
- [crates/docker_manager/src/container_stop.rs](file://crates/docker_manager/src/container_stop.rs#L252-L269)
|
||||
|
||||
## 性能考虑
|
||||
- 定时轮询频率
|
||||
- 默认清理间隔为 5 分钟,建议结合业务负载与资源占用调整,避免过于频繁导致 CPU 唤醒开销。
|
||||
- 扫描与清理复杂度
|
||||
- 扫描阶段遍历映射,复杂度 O(N);rcoder 场景额外包含容器查询与并行清理,注意 Docker API 调用次数。
|
||||
- 并发与超时
|
||||
- 孤立容器清理采用并行任务,限制单次清理数量,避免阻塞主流程;整体清理设置超时上限,保证稳定性。
|
||||
- 端口与容器资源
|
||||
- 端口释放与容器停止均设置超时,防止长时间阻塞;建议监控清理耗时与失败率,及时调整超时参数。
|
||||
|
||||
[本节为通用性能讨论,不直接分析具体文件]
|
||||
|
||||
## 故障排查指南
|
||||
- 清理任务未生效
|
||||
- 检查定时器是否启动、清理间隔是否合理、日志中是否有“定时清理完成/失败/超时”记录。
|
||||
- 容器未被清理
|
||||
- rcoder 场景确认容器停止接口是否成功、端口是否释放、映射是否移除;查看超时与错误日志。
|
||||
- 代理资源未回收
|
||||
- 确认生命周期守卫 Drop 是否触发;检查映射移除是否成功;核对本地进程资源清理日志。
|
||||
- 端口泄漏
|
||||
- 检查容器销毁后是否调用端口释放;核对端口管理器释放日志。
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L787-L815)
|
||||
- [crates/rcoder/src/proxy_agent/port_manager.rs](file://crates/rcoder/src/proxy_agent/port_manager.rs#L51-L59)
|
||||
- [crates/agent_runner/src/proxy_agent/agent_stop_handle.rs](file://crates/agent_runner/src/proxy_agent/agent_stop_handle.rs#L236-L292)
|
||||
|
||||
## 结论
|
||||
清理任务通过“定时轮询 + RAII 回收”的设计,在代理终止后可靠地回收容器、端口与会话等资源。rcoder 场景提供了更完善的超时控制、孤立容器扫描与端口释放能力;agent_runner 场景则通过映射移除触发生命周期守卫 Drop,实现轻量级资源回收。结合合理的配置与监控,可在保证稳定性的同时最大化资源利用率。
|
||||
|
||||
[本节为总结性内容,不直接分析具体文件]
|
||||
|
||||
## 附录
|
||||
|
||||
### 配置选项说明
|
||||
- rcoder 清理配置 CleanupConfig
|
||||
- idle_timeout:代理闲置超时时间,默认 30 分钟。
|
||||
- cleanup_interval:清理检查间隔,默认 5 分钟。
|
||||
- docker_stop_timeout:Docker 容器停止超时,默认 30 秒。
|
||||
- agent_runner 清理配置 CleanupConfig
|
||||
- idle_timeout:代理闲置超时时间,默认 30 分钟。
|
||||
- cleanup_interval:清理检查间隔,默认 5 分钟。
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L67-L89)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L18-L36)
|
||||
|
||||
### 启动与集成
|
||||
- rcoder 启动清理任务
|
||||
- 通过 start_cleanup_task(config, state) 启动,传入 AppState 与 CleanupConfig。
|
||||
- agent_runner 启动清理任务
|
||||
- 通过 start_cleanup_task(config) 启动,传入 CleanupConfig。
|
||||
|
||||
章节来源
|
||||
- [crates/rcoder/src/proxy_agent/cleanup_task.rs](file://crates/rcoder/src/proxy_agent/cleanup_task.rs#L823-L835)
|
||||
- [crates/agent_runner/src/proxy_agent/cleanup_task.rs](file://crates/agent_runner/src/proxy_agent/cleanup_task.rs#L300-L310)
|
||||
360
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/代理运行器架构/通道工具.md
Normal file
360
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/代理运行器架构/通道工具.md
Normal file
@@ -0,0 +1,360 @@
|
||||
# 通道工具
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.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)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs)
|
||||
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件系统性地介绍代理运行器中“通道工具”(channel_utils)模块提供的异步通信能力,重点说明其如何简化 Tokio 通道的使用,包括通道创建、消息转发、状态更新与错误处理等辅助函数。文档还解释了在代理运行器中各组件间通信的应用场景,如命令传递、状态更新和结果返回,并给出设计理念、性能特征与使用注意事项,以及典型使用模式的路径指引。
|
||||
|
||||
## 项目结构
|
||||
通道工具位于代理运行器的代理层,围绕 ACP 协议的客户端连接与会话管理展开,配合全局会话缓存与通知广播,形成“命令通道 + 数据通道”的双通道通信体系。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "代理层"
|
||||
CU["channel_utils<br/>通用通道处理工具"]
|
||||
MOD["proxy_agent/mod.rs<br/>会话上下文与通知入口"]
|
||||
AS["agent_service.rs<br/>代理服务抽象"]
|
||||
CA["claude_code_agent.rs<br/>Claude代理启动"]
|
||||
CO["codex_agent.rs<br/>Codex代理启动"]
|
||||
end
|
||||
subgraph "服务层"
|
||||
SC["service/session_cache.rs<br/>会话缓存与推送"]
|
||||
end
|
||||
subgraph "共享类型"
|
||||
AM["shared_types/agent_model.rs<br/>模型与生命周期"]
|
||||
AN["shared_types/agent_session_notify.rs<br/>统一通知模型"]
|
||||
AE["shared_types/app_error.rs<br/>错误类型"]
|
||||
end
|
||||
CA --> CU
|
||||
CO --> CU
|
||||
CU --> SC
|
||||
MOD --> SC
|
||||
SC --> AN
|
||||
AM --> CU
|
||||
AE --> SC
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L355)
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L294-L318)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L82-L163)
|
||||
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
|
||||
|
||||
章节来源
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L355)
|
||||
|
||||
## 核心组件
|
||||
- 通用通道处理工具(channel_utils)
|
||||
- 提供两类可复用的任务:取消处理任务与提示处理任务,分别封装对 Agent 的 cancel 与 prompt 调用、状态更新与通知广播。
|
||||
- 设计要点:超时保护、状态机切换、请求上下文透传、错误链路闭环。
|
||||
- 会话级上下文与通知入口(proxy_agent/mod.rs)
|
||||
- 维护会话级 request_id 上下文映射,支持 session_notification 回调中获取 request_id。
|
||||
- 实现 ACP 客户端的 session_notification,将 Agent 的会话更新转换为统一通知并推送。
|
||||
- 会话缓存与推送(service/session_cache.rs)
|
||||
- 全局会话缓存、项目-会话映射、环形缓冲区与实时推送,提供 push_session_update 与 push_session_update_with_project 两个便捷函数。
|
||||
- 代理服务抽象(agent_service.rs)
|
||||
- 定义 AcpAgentService trait,统一启动流程与代理类型名。
|
||||
- 代理启动与通道绑定(claude_code_agent.rs、codex_agent.rs)
|
||||
- 启动子进程/代理实例,创建 unbounded channel 用于取消与提示,绑定到通用通道处理工具。
|
||||
- 共享模型与错误(shared_types)
|
||||
- 统一的 Agent 状态、生命周期、通知模型与错误类型,保证跨模块一致性。
|
||||
|
||||
章节来源
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L355)
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L294-L318)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L82-L163)
|
||||
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
|
||||
|
||||
## 架构总览
|
||||
通道工具在代理运行器中的作用是“桥接外部命令与内部 Agent 执行”,并通过统一的通知模型将状态与结果广播给前端或上层服务。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant RC as "rcoder/上层"
|
||||
participant AG as "代理启动器<br/>claude_code_agent.rs/codex_agent.rs"
|
||||
participant CH as "通道工具<br/>channel_utils.rs"
|
||||
participant AC as "Agent 客户端连接"
|
||||
participant SV as "会话缓存<br/>session_cache.rs"
|
||||
participant FE as "前端/订阅者"
|
||||
RC->>AG : 发送取消/提示命令
|
||||
AG->>CH : 通过 unbounded channel 分发
|
||||
CH->>AC : 调用 cancel/prompt
|
||||
AC-->>CH : 返回执行结果/错误
|
||||
CH->>SV : 推送 SessionPromptStart/End/Error
|
||||
SV-->>FE : 通过 SSE 广播统一通知
|
||||
CH->>CH : 更新 Agent 状态Active/Idle
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L294-L318)
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L232-L278)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 通用通道处理工具(channel_utils)
|
||||
- 功能概览
|
||||
- 取消处理任务:接收取消通知,调用 Agent.cancel,带超时保护,发送响应并恢复 Agent 状态。
|
||||
- 提示处理任务:接收提示请求,校验/修正会话 ID,提取 request_id,更新 Agent 状态,发送开始通知,执行 prompt,按成功/失败路径发送结束通知并恢复状态。
|
||||
- 设计理念
|
||||
- 超时保护:对 Agent.cancel 加入固定超时,避免阻塞通道处理。
|
||||
- 状态机:在处理前后维护 Agent 状态(Active/Idle),确保状态与实际执行一致。
|
||||
- 请求上下文:从 PromptRequest.meta 提取 request_id 并写入会话级上下文,便于后续通知携带。
|
||||
- 通知闭环:无论成功或失败,均发送 SessionPromptEnd,确保会话结束语义明确。
|
||||
- 性能特征
|
||||
- 使用 unbounded channel 降低背压压力,适合高吞吐的提示处理。
|
||||
- 通过 tokio::task::spawn_local 在本地任务集中运行,减少跨线程调度开销。
|
||||
- 通知广播通过统一模型与会话缓存,避免重复序列化与多路分发。
|
||||
- 使用注意事项
|
||||
- 会话 ID 不一致时会强制覆盖为目标会话,确保消息路由正确。
|
||||
- request_id 为空时不会影响整体流程,但可能影响前端关联。
|
||||
- 错误路径会同时发送 SessionPromptError 与 SessionPromptEnd,确保前端能感知错误并结束会话。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进入提示处理任务"]) --> CheckSID["校验/修正 session_id"]
|
||||
CheckSID --> ExtractRID["从 meta 提取 request_id"]
|
||||
ExtractRID --> UpdateStatus["更新 Agent 状态为 Active"]
|
||||
UpdateStatus --> SaveCtx["写入会话级上下文project_id->request_id"]
|
||||
SaveCtx --> NotifyStart["发送 SessionPromptStart"]
|
||||
NotifyStart --> CallPrompt["调用 Agent.prompt()"]
|
||||
CallPrompt --> Ok{"执行成功?"}
|
||||
Ok --> |是| NotifyEnd["发送 SessionPromptEndstop_reason"]
|
||||
Ok --> |否| NotifyErr["发送 SessionPromptError含 code/message"]
|
||||
NotifyErr --> NotifyEnd2["发送 SessionPromptEndCancelled"]
|
||||
NotifyEnd --> ResetStatus["恢复 Agent 状态为 Idle"]
|
||||
NotifyEnd2 --> ResetStatus
|
||||
ResetStatus --> End(["任务继续监听新消息"])
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L92-L229)
|
||||
|
||||
章节来源
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
|
||||
### 会话级上下文与通知入口(proxy_agent/mod.rs)
|
||||
- 功能概览
|
||||
- 维护会话级 request_id 上下文映射(project_id -> request_id),避免锁竞争。
|
||||
- 实现 ACP 客户端的 session_notification,优先从 meta 获取 request_id,否则通过 session_id 查找 project_id 再从上下文获取,最终将 AgentSessionUpdate 转换为统一通知并推送。
|
||||
- 设计理念
|
||||
- 以 project_id 为键的上下文映射,确保同一项目多次请求自动覆盖为最新值,避免过期 request_id 影响。
|
||||
- 通知转换严格遵循统一模型,保证前端消费一致性。
|
||||
- 使用注意事项
|
||||
- 若 meta 与上下文均无 request_id,通知仍会成功推送,但前端可能缺少请求关联信息。
|
||||
|
||||
章节来源
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
|
||||
|
||||
### 会话缓存与推送(service/session_cache.rs)
|
||||
- 功能概览
|
||||
- 全局会话缓存(DashMap),按 session_id 分组,使用环形缓冲区保存最近消息,实时推送至当前连接。
|
||||
- 提供 push_session_update 与 push_session_update_with_project 两个便捷函数,后者自动处理项目-会话映射变更并清理旧数据。
|
||||
- SessionWorker 通过命令通道管理推送、清理与统计。
|
||||
- 设计理念
|
||||
- 极简优化:直接共享当前连接状态,避免命令传递带来的额外复杂度。
|
||||
- 心跳与实时推送:心跳消息单独处理,避免缓冲区占用。
|
||||
- 会话映射一致性:ensure_project_session 在 session_id 变更时清理旧数据并更新映射,避免脏数据污染。
|
||||
- 使用注意事项
|
||||
- 当前连接关闭时会显式 drop 发送端,接收端 recv() 立即返回 None,确保及时感知断开。
|
||||
- 清理旧会话数据时会移除缓存条目,注意不要在清理后继续向旧会话推送。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class SessionData {
|
||||
+command_tx
|
||||
+current_sender
|
||||
+current_cancel
|
||||
+create_new_connection(buffer_size)
|
||||
+push_message(message)
|
||||
+close_current_connection()
|
||||
}
|
||||
class SessionWorker {
|
||||
+max_size
|
||||
+command_rx
|
||||
+current_sender
|
||||
+current_cancel
|
||||
+run()
|
||||
}
|
||||
class SessionCache {
|
||||
+push_session_update(session_id, notify)
|
||||
+push_session_update_with_project(project_id, session_id, notify)
|
||||
+ensure_project_session(project_id, session_id)
|
||||
}
|
||||
SessionData --> SessionWorker : "spawn"
|
||||
SessionCache --> SessionData : "管理"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L355)
|
||||
|
||||
章节来源
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L355)
|
||||
|
||||
### 代理服务抽象与启动(agent_service.rs、claude_code_agent.rs、codex_agent.rs)
|
||||
- 功能概览
|
||||
- AcpAgentService 抽象统一启动流程,不同代理类型通过其实现启动。
|
||||
- 启动时创建取消与提示通道,绑定到通用通道处理工具,启动后等待取消信号。
|
||||
- 设计理念
|
||||
- 通过 trait 解耦代理类型,统一生命周期管理。
|
||||
- 通道绑定与任务分离,便于扩展与维护。
|
||||
- 使用注意事项
|
||||
- 通道使用 unbounded channel,注意避免无限增长导致内存压力。
|
||||
- 取消信号通过 CancellationToken 传播,确保子进程/连接正确退出。
|
||||
|
||||
章节来源
|
||||
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L294-L318)
|
||||
|
||||
### 统一通知模型与错误类型(shared_types)
|
||||
- 功能概览
|
||||
- 统一通知模型(SessionNotify)与统一消息(UnifiedSessionMessage),支持多种消息类型与子类型。
|
||||
- 错误类型(AppError)统一错误表示,支持从 tokio mpsc SendError 转换。
|
||||
- 设计理念
|
||||
- 前后端一致的事件模型,便于前端消费与状态机驱动。
|
||||
- 错误结构保留 code 与 message,便于前端展示与诊断。
|
||||
- 使用注意事项
|
||||
- 错误路径中 data 直接包含 code 与 message,前端无需二次解析。
|
||||
|
||||
章节来源
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L82-L163)
|
||||
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
|
||||
|
||||
## 依赖分析
|
||||
- 组件耦合
|
||||
- channel_utils 依赖代理运行器的全局映射(项目-代理信息)与会话缓存推送函数。
|
||||
- proxy_agent/mod.rs 依赖 shared_types 的通知模型与会话缓存推送函数。
|
||||
- 代理启动器(claude_code_agent.rs、codex_agent.rs)依赖 channel_utils 与 ACP 客户端连接。
|
||||
- 外部依赖
|
||||
- tokio mpsc、dashmap、ringbuf、tokio-util CancellationToken 等。
|
||||
- 循环依赖
|
||||
- 通过模块拆分与函数边界清晰,未发现循环依赖迹象。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
CU["channel_utils.rs"] --> SC["service/session_cache.rs"]
|
||||
CU --> AM["shared_types/agent_model.rs"]
|
||||
MOD["proxy_agent/mod.rs"] --> SC
|
||||
MOD --> AN["shared_types/agent_session_notify.rs"]
|
||||
CA["claude_code_agent.rs"] --> CU
|
||||
CO["codex_agent.rs"] --> CU
|
||||
SC --> AN
|
||||
AM --> CU
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L355)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L294-L318)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L82-L163)
|
||||
|
||||
章节来源
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L1-L230)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L1-L355)
|
||||
- [claude_code_agent.rs](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- [codex_agent.rs](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L294-L318)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
- [agent_session_notify.rs](file://crates/shared_types/src/model/agent_session_notify.rs#L82-L163)
|
||||
|
||||
## 性能考量
|
||||
- 通道选择
|
||||
- 提示处理使用 unbounded channel,降低背压,适合高并发提示场景。
|
||||
- 取消处理使用 unbounded channel,结合超时保护,避免阻塞。
|
||||
- 状态与上下文
|
||||
- 使用 DashMap 与 LazyLock 保证全局状态访问的低锁争用。
|
||||
- 会话级上下文使用 project_id 作为键,避免锁竞争。
|
||||
- 缓冲与推送
|
||||
- 环形缓冲区限制内存占用,实时推送失败时自动降级为丢弃旧数据。
|
||||
- 心跳消息不计入缓冲,避免阻塞。
|
||||
- 生命周期
|
||||
- CancellationToken 与显式 drop 发送端,确保连接断开的确定性与及时性。
|
||||
|
||||
[本节为通用性能讨论,不直接分析具体文件]
|
||||
|
||||
## 故障排查指南
|
||||
- 取消超时
|
||||
- 现象:取消请求响应为超时。
|
||||
- 排查:确认 Agent.cancel 是否阻塞,检查超时阈值与网络状况。
|
||||
- 参考路径:[取消处理任务](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L18-L89)
|
||||
- 提示失败
|
||||
- 现象:提示执行失败,前端收到错误通知。
|
||||
- 排查:检查 Agent.prompt 返回的错误结构,确认错误消息是否包含 code 与 message。
|
||||
- 参考路径:[提示处理任务错误分支](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L190-L224)
|
||||
- 通知未到达
|
||||
- 现象:前端未收到 SessionPromptStart/End/Error。
|
||||
- 排查:确认 push_session_update_with_project 是否正确更新项目-会话映射;检查 SessionData 是否仍在运行。
|
||||
- 参考路径:[会话缓存推送](file://crates/agent_runner/src/service/session_cache.rs#L232-L278)
|
||||
- request_id 缺失
|
||||
- 现象:前端无法关联请求。
|
||||
- 排查:确认 PromptRequest.meta 是否包含 request_id;若缺失,检查 session_notification 是否能通过 project_id 从上下文获取。
|
||||
- 参考路径:[会话通知入口](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L209)
|
||||
|
||||
章节来源
|
||||
- [channel_utils.rs](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L18-L224)
|
||||
- [session_cache.rs](file://crates/agent_runner/src/service/session_cache.rs#L232-L278)
|
||||
- [mod.rs](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L209)
|
||||
|
||||
## 结论
|
||||
通道工具通过“取消处理任务 + 提示处理任务”的双通道模式,将外部命令与内部 Agent 执行解耦,配合统一通知模型与会话缓存,实现了高效、稳定且可扩展的异步通信。其设计理念强调超时保护、状态机一致性与上下文透传,既满足高并发场景下的性能需求,又保证了错误路径的可观测性与前端体验的一致性。
|
||||
|
||||
[本节为总结性内容,不直接分析具体文件]
|
||||
|
||||
## 附录
|
||||
|
||||
### 典型使用模式(路径指引)
|
||||
- 启动代理并绑定通道
|
||||
- Claude 代理:[启动流程与通道绑定](file://crates/agent_runner/src/proxy_agent/claude_code_agent.rs#L1-L311)
|
||||
- Codex 代理:[启动流程与通道绑定](file://crates/agent_runner/src/proxy_agent/codex_agent.rs#L294-L318)
|
||||
- 取消处理任务
|
||||
- [通用取消处理函数](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L18-L89)
|
||||
- 提示处理任务
|
||||
- [通用提示处理函数](file://crates/agent_runner/src/proxy_agent/channel_utils.rs#L92-L229)
|
||||
- 会话通知入口
|
||||
- [session_notification 实现](file://crates/agent_runner/src/proxy_agent/mod.rs#L149-L209)
|
||||
- 会话缓存与推送
|
||||
- [统一推送函数](file://crates/agent_runner/src/service/session_cache.rs#L232-L278)
|
||||
- [项目-会话映射更新](file://crates/agent_runner/src/service/session_cache.rs#L282-L354)
|
||||
- 统一通知模型
|
||||
- [通知转统一消息](file://crates/shared_types/src/model/agent_session_notify.rs#L82-L163)
|
||||
- 错误类型
|
||||
- [AppError 定义与转换](file://crates/shared_types/src/model/app_error.rs#L1-L65)
|
||||
348
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/反向代理架构.md
Normal file
348
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/反向代理架构.md
Normal file
@@ -0,0 +1,348 @@
|
||||
# 反向代理架构
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [lib.rs](file://crates/pingora-proxy/src/lib.rs)
|
||||
- [server.rs](file://crates/pingora-proxy/src/server.rs)
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
- [pingora_server.rs](file://crates/pingora-proxy/src/pingora_server.rs)
|
||||
- [config.rs](file://crates/pingora-proxy/src/config.rs)
|
||||
- [Cargo.toml](file://crates/pingora-proxy/Cargo.toml)
|
||||
- [proxy_handler_api.rs](file://crates/rcoder/src/handler/proxy_handler_api.rs)
|
||||
- [proxy_api.rs](file://crates/rcoder/src/handler/proxy_api.rs)
|
||||
- [router.rs](file://crates/rcoder/src/router.rs)
|
||||
- [README.md](file://README.md)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [引言](#引言)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概述](#架构概述)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障恢复机制](#故障恢复机制)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 引言
|
||||
本文档详细描述了基于Cloudflare Pingora构建的高性能反向代理架构。该架构设计用于在Docker容器环境中统一端口访问多个前端应用,通过端口参数实现灵活的请求路由。文档涵盖了端口路由机制、请求转发流程、状态监控和与主应用的集成模式,解释了选择Pingora而非Nginx的技术决策、性能优化策略和资源隔离方案。
|
||||
|
||||
## 项目结构
|
||||
反向代理功能主要由`pingora-proxy` crate实现,该模块提供了完整的基于Pingora的高性能代理服务。主应用通过集成此模块,实现了对多个后端服务的统一访问和管理。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "主应用"
|
||||
A[rcoder]
|
||||
B[agent_runner]
|
||||
end
|
||||
subgraph "反向代理模块"
|
||||
C[pingora-proxy]
|
||||
D[config]
|
||||
E[service]
|
||||
F[server]
|
||||
G[pingora_server]
|
||||
end
|
||||
A --> C
|
||||
B --> C
|
||||
C --> D
|
||||
C --> E
|
||||
C --> F
|
||||
C --> G
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [lib.rs](file://crates/pingora-proxy/src/lib.rs)
|
||||
- [Cargo.toml](file://crates/pingora-proxy/Cargo.toml)
|
||||
|
||||
**章节来源**
|
||||
- [lib.rs](file://crates/pingora-proxy/src/lib.rs)
|
||||
- [Cargo.toml](file://crates/pingora-proxy/Cargo.toml)
|
||||
|
||||
## 核心组件
|
||||
反向代理的核心组件包括配置管理、服务实现、服务器管理和请求处理。`ProxyConfig`定义了代理服务的配置参数,`PingoraProxyService`实现了核心的代理逻辑,`ProxyServer`提供了服务器的启动和管理功能,而`PingoraServerManager`则负责完整的Pingora服务器生命周期管理。
|
||||
|
||||
**章节来源**
|
||||
- [config.rs](file://crates/pingora-proxy/src/config.rs)
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
- [server.rs](file://crates/pingora-proxy/src/server.rs)
|
||||
- [pingora_server.rs](file://crates/pingora-proxy/src/pingora_server.rs)
|
||||
|
||||
## 架构概述
|
||||
基于Pingora的反向代理架构采用分层设计,从配置层到服务层再到服务器层,每一层都有明确的职责。该架构支持HTTP/1.1和HTTP/2,利用Pingora的异步I/O能力实现高性能请求处理。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[客户端请求] --> B[端口路由]
|
||||
B --> C{路由规则}
|
||||
C --> |/proxy/{port}| D[提取目标端口]
|
||||
C --> |?port={port}| E[提取查询参数]
|
||||
C --> |默认端口| F[使用默认端口]
|
||||
D --> G[动态后端管理]
|
||||
E --> G
|
||||
F --> G
|
||||
G --> H[健康检查]
|
||||
H --> I[连接池管理]
|
||||
I --> J[请求转发]
|
||||
J --> K[后端服务]
|
||||
K --> L[响应处理]
|
||||
L --> M[客户端响应]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
- [server.rs](file://crates/pingora-proxy/src/server.rs)
|
||||
|
||||
**章节来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
- [server.rs](file://crates/pingora-proxy/src/server.rs)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 端口路由机制
|
||||
端口路由机制支持两种方式:路径方式(/proxy/{port}/{path})和查询参数方式(?port={port})。路径方式优先级高于查询参数方式,系统会首先尝试从路径中提取端口号,如果失败则尝试从查询参数中提取,最后使用默认端口。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> CheckPath{"路径是否以<br/>/proxy/开头?"}
|
||||
CheckPath --> |是| ExtractPortFromPath["从路径提取端口<br/>(parts[2].parse())"]
|
||||
CheckPath --> |否| CheckQuery{"查询参数中<br/>是否有port?"}
|
||||
CheckQuery --> |是| ExtractPortFromQuery["从查询参数提取端口<br/>(param.split_once('=')"]
|
||||
CheckQuery --> |否| UseDefaultPort["使用默认端口<br/>(3000)"]
|
||||
ExtractPortFromPath --> ValidatePort{"端口有效?"}
|
||||
ExtractPortFromQuery --> ValidatePort
|
||||
ValidatePort --> |是| ReturnPort["返回提取的端口"]
|
||||
ValidatePort --> |否| ReturnDefault["返回默认端口"]
|
||||
ReturnPort --> End([结束])
|
||||
ReturnDefault --> End
|
||||
UseDefaultPort --> End
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs#L358-L375)
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs#L478-L507)
|
||||
|
||||
**章节来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
|
||||
### 请求转发流程
|
||||
请求转发流程由`PortProxy`实现,该组件实现了Pingora的`ProxyHttp` trait,负责处理请求的完整生命周期,包括请求头过滤、上游服务器选择和响应过滤。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Proxy as "反向代理"
|
||||
participant Backend as "后端服务"
|
||||
Client->>Proxy : HTTP请求
|
||||
Proxy->>Proxy : 提取目标端口
|
||||
Proxy->>Proxy : 动态添加后端(如需要)
|
||||
Proxy->>Proxy : 重写Host头为127.0.0.1
|
||||
Proxy->>Proxy : 添加代理头(X-Forwarded-Proto等)
|
||||
Proxy->>Proxy : 重写请求路径
|
||||
Proxy->>Backend : 转发请求
|
||||
Backend-->>Proxy : 响应
|
||||
Proxy->>Proxy : 记录指标(响应时间等)
|
||||
Proxy->>Client : 返回响应
|
||||
Note over Proxy,Backend : 基于Pingora的异步代理流程
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs#L247-L353)
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs#L357-L397)
|
||||
|
||||
**章节来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
|
||||
### 状态监控与统计
|
||||
反向代理提供了全面的状态监控和统计功能,包括请求计数、成功率、响应时间、活跃连接数等指标。这些指标通过`ProxyMetrics`结构体进行管理,并可通过API接口查询。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class ProxyMetrics {
|
||||
+total_requests : AtomicU64
|
||||
+total_responses : AtomicU64
|
||||
+successful_responses : AtomicU64
|
||||
+failed_responses : AtomicU64
|
||||
+total_response_time_ns : AtomicU64
|
||||
+active_connections : AtomicU64
|
||||
+port_map : RwLock~HashMap<u16, Arc<PerPortMetrics>>~
|
||||
+record_request()
|
||||
+record_response()
|
||||
+avg_response_time_ms()
|
||||
+port_snapshots()
|
||||
}
|
||||
class PerPortMetrics {
|
||||
+requests : AtomicU64
|
||||
+successes : AtomicU64
|
||||
+failures : AtomicU64
|
||||
+total_response_time_ns : AtomicU64
|
||||
}
|
||||
class PortSnapshot {
|
||||
+port : u16
|
||||
+requests : u64
|
||||
+successes : u64
|
||||
+failures : u64
|
||||
+total_response_time_ns : u64
|
||||
}
|
||||
ProxyMetrics --> PerPortMetrics : "包含"
|
||||
ProxyMetrics --> PortSnapshot : "生成"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs#L26-L180)
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs#L598-L607)
|
||||
|
||||
**章节来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
|
||||
### 与主应用的集成模式
|
||||
反向代理通过`AppState`与主应用集成,主应用在启动时创建`PingoraProxyService`实例并将其注入应用状态,从而实现状态监控API与实际代理服务的数据共享。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AppState {
|
||||
+sessions : DashMap~String, Arc<ProjectAndContainerInfo>~
|
||||
+project_and_agent_map : DashMap~String, Arc<ProjectAndContainerInfo>~
|
||||
+config : AppConfig
|
||||
+pingora_service : Option~Arc<PingoraProxyService>~
|
||||
}
|
||||
class PingoraProxyService {
|
||||
+config : ProxyConfig
|
||||
+backends : Arc~RwLock<HashMap<u16, String>>~
|
||||
+use_round_robin : bool
|
||||
+metrics : Arc~ProxyMetrics~
|
||||
+health_map : Arc~RwLock<HashMap<u16, HealthInfo>>~
|
||||
+new(config)
|
||||
+create_pingora_proxy()
|
||||
+add_backend()
|
||||
+remove_backend()
|
||||
+list_backends()
|
||||
+start_health_check_loop()
|
||||
}
|
||||
class AppConfig {
|
||||
+proxy_config : Option~ProxyConfig~
|
||||
+projects_dir : String
|
||||
+agent : AgentConfig
|
||||
}
|
||||
AppState --> PingoraProxyService : "引用"
|
||||
AppState --> AppConfig : "包含"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [router.rs](file://crates/rcoder/src/router.rs#L27-L35)
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs#L224-L233)
|
||||
|
||||
**章节来源**
|
||||
- [router.rs](file://crates/rcoder/src/router.rs)
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
|
||||
## 依赖分析
|
||||
反向代理模块依赖于多个关键的Rust库,包括Pingora系列库用于高性能代理,Tokio用于异步运行时,Tracing用于日志记录,以及Axum用于HTTP服务构建。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[pingora-proxy] --> B[pingora]
|
||||
A --> C[pingora-core]
|
||||
A --> D[pingora-http]
|
||||
A --> E[pingora-proxy]
|
||||
A --> F[pingora-load-balancing]
|
||||
A --> G[tokio]
|
||||
A --> H[tracing]
|
||||
A --> I[axum]
|
||||
A --> J[reqwest]
|
||||
A --> K[async-trait]
|
||||
B --> L[Cloudflare Pingora]
|
||||
C --> L
|
||||
D --> L
|
||||
E --> L
|
||||
F --> L
|
||||
G --> M[Tokio Runtime]
|
||||
H --> N[Tracing Framework]
|
||||
I --> O[Axum Web Framework]
|
||||
J --> P[HTTP Client]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [Cargo.toml](file://crates/pingora-proxy/Cargo.toml)
|
||||
- [lib.rs](file://crates/pingora-proxy/src/lib.rs)
|
||||
|
||||
**章节来源**
|
||||
- [Cargo.toml](file://crates/pingora-proxy/Cargo.toml)
|
||||
|
||||
## 性能考虑
|
||||
基于Pingora的反向代理在性能方面进行了多项优化,包括异步I/O处理、连接池管理、负载均衡和健康检查。与Nginx相比,Pingora作为Rust编写的库,提供了更好的内存安全性和性能表现。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[性能优化策略] --> B[异步I/O]
|
||||
A --> C[连接池]
|
||||
A --> D[负载均衡]
|
||||
A --> E[健康检查]
|
||||
A --> F[零拷贝]
|
||||
A --> G[内存安全]
|
||||
B --> H["基于Tokio的异步运行时<br/>避免线程阻塞"]
|
||||
C --> I["复用TCP连接<br/>减少握手开销"]
|
||||
D --> J["Round Robin/Ketama算法<br/>均匀分发请求"]
|
||||
E --> K["定期TCP健康检查<br/>自动剔除故障节点"]
|
||||
F --> L["避免数据复制<br/>提高吞吐量"]
|
||||
G --> M["Rust所有权模型<br/>防止内存泄漏"]
|
||||
style A fill:#f9f,stroke:#333,stroke-width:2px
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
- [server.rs](file://crates/pingora-proxy/src/server.rs)
|
||||
|
||||
**章节来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
- [server.rs](file://crates/pingora-proxy/src/server.rs)
|
||||
|
||||
## 故障恢复机制
|
||||
反向代理实现了完善的故障恢复机制,包括健康检查、自动故障转移和连接重试。健康检查定期检测后端服务的可用性,并在服务恢复后自动重新加入负载均衡。
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Healthy
|
||||
Healthy --> Unhealthy : "健康检查失败"
|
||||
Unhealthy --> Healthy : "健康检查通过"
|
||||
Unhealthy --> Timeout : "连接超时"
|
||||
Timeout --> Unhealthy : "重试失败"
|
||||
Timeout --> Healthy : "重试成功"
|
||||
state Healthy {
|
||||
[*] --> Active
|
||||
Active --> Draining : "服务停止"
|
||||
Draining --> [*]
|
||||
}
|
||||
state Unhealthy {
|
||||
[*] --> Inactive
|
||||
Inactive --> [*]
|
||||
}
|
||||
state Timeout {
|
||||
[*] --> Retrying
|
||||
Retrying --> Healthy : "成功"
|
||||
Retrying --> Unhealthy : "失败"
|
||||
}
|
||||
note right of Healthy
|
||||
健康状态:可正常处理请求
|
||||
定期健康检查:每5秒一次
|
||||
end note
|
||||
note right of Unhealthy
|
||||
不健康状态:从负载均衡中移除
|
||||
不再接收新请求
|
||||
end note
|
||||
note right of Timeout
|
||||
超时状态:连接失败
|
||||
进行重试机制
|
||||
end note
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs#L556-L591)
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs#L182-L197)
|
||||
|
||||
**章节来源**
|
||||
- [service.rs](file://crates/pingora-proxy/src/service.rs)
|
||||
|
||||
## 结论
|
||||
基于Pingora的反向代理架构提供了一个高性能、高可靠性的解决方案,特别适合在容器化环境中统一管理多个前端应用的访问。通过端口路由机制,实现了灵活的服务访问;通过健康检查和负载均衡,确保了服务的高可用性;通过详细的指标统计,提供了全面的监控能力。与主应用的紧密集成使得状态监控和配置管理更加便捷,整体架构设计合理,性能优越。
|
||||
278
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/容器管理架构.md
Normal file
278
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/容器管理架构.md
Normal file
@@ -0,0 +1,278 @@
|
||||
# 容器管理架构
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [lib.rs](file://crates/docker_manager/src/lib.rs)
|
||||
- [manager.rs](file://crates/docker_manager/src/manager.rs)
|
||||
- [image_selector.rs](file://crates/docker_manager/src/image_selector.rs)
|
||||
- [types.rs](file://crates/docker_manager/src/types.rs)
|
||||
- [utils.rs](file://crates/docker_manager/src/utils.rs)
|
||||
- [container_stop.rs](file://crates/docker_manager/src/container_stop.rs)
|
||||
- [container_self_inspector.rs](file://crates/docker_manager/src/container_self_inspector.rs)
|
||||
- [Cargo.toml](file://crates/docker_manager/Cargo.toml)
|
||||
- [multi_image_config.rs](file://crates/shared_types/src/multi_image_config.rs)
|
||||
- [service_config.rs](file://crates/shared_types/src/service_config.rs)
|
||||
- [service_type.rs](file://crates/shared_types/src/service_type.rs)
|
||||
- [docker_container_agent.rs](file://crates/rcoder/src/proxy_agent/docker_container_agent.rs)
|
||||
- [container_manager.rs](file://crates/rcoder/src/service/container_manager.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概述](#架构概述)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
本文档详细描述了RCoder系统中容器管理架构的设计与实现。该架构基于Docker API,通过bollard客户端库实现对Docker容器的全生命周期管理,包括容器的创建、启动、停止和清理。系统支持多Docker镜像配置,能够根据服务类型和硬件架构自动选择最合适的镜像。架构设计中包含了启动时清理和运行时清理两种策略,确保系统稳定性和资源高效利用。同时,文档还涵盖了资源隔离、网络配置、安全性考虑和性能优化等关键方面。
|
||||
|
||||
## 项目结构
|
||||
容器管理功能主要位于`crates/docker_manager`目录下,作为一个独立的Rust crate实现。该模块通过bollard库与Docker守护进程交互,提供了完整的容器管理API。系统通过`MultiImageConfig`和`ServiceImageConfig`等配置结构支持多镜像配置,能够根据服务类型和硬件架构动态选择镜像。容器管理器与RCoder主应用通过`rcoder/src/service/container_manager.rs`进行集成,为上层应用提供容器生命周期管理服务。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "容器管理模块"
|
||||
DM[crates/docker_manager]
|
||||
DM --> Lib[lib.rs]
|
||||
DM --> Manager[manager.rs]
|
||||
DM --> ImageSelector[image_selector.rs]
|
||||
DM --> Types[types.rs]
|
||||
DM --> Utils[utils.rs]
|
||||
DM --> ContainerStop[container_stop.rs]
|
||||
DM --> ContainerInspector[container_self_inspector.rs]
|
||||
end
|
||||
subgraph "共享类型"
|
||||
ST[crates/shared_types]
|
||||
ST --> MultiImageConfig[multi_image_config.rs]
|
||||
ST --> ServiceConfig[service_config.rs]
|
||||
ST --> ServiceType[service_type.rs]
|
||||
end
|
||||
subgraph "RCoder主应用"
|
||||
RC[crates/rcoder]
|
||||
RC --> ContainerAgent[docker_container_agent.rs]
|
||||
RC --> ContainerManager[container_manager.rs]
|
||||
end
|
||||
DM --> ST
|
||||
RC --> DM
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [lib.rs](file://crates/docker_manager/src/lib.rs)
|
||||
- [multi_image_config.rs](file://crates/shared_types/src/multi_image_config.rs)
|
||||
- [container_manager.rs](file://crates/rcoder/src/service/container_manager.rs)
|
||||
|
||||
**Section sources**
|
||||
- [lib.rs](file://crates/docker_manager/src/lib.rs)
|
||||
- [manager.rs](file://crates/docker_manager/src/manager.rs)
|
||||
|
||||
## 核心组件
|
||||
容器管理架构的核心组件包括DockerManager、ImageSelector和ContainerStop模块。DockerManager是主要的容器管理器,负责容器的创建、启动、停止和状态监控。ImageSelector模块根据服务类型和项目配置选择合适的Docker镜像,支持多架构镜像的自动选择。ContainerStop模块提供了启动时清理和运行时清理两种策略,确保系统在启动和运行过程中都能有效管理容器资源。这些组件共同构成了一个健壮的容器管理解决方案,支持RCoder系统的动态容器化需求。
|
||||
|
||||
**Section sources**
|
||||
- [manager.rs](file://crates/docker_manager/src/manager.rs)
|
||||
- [image_selector.rs](file://crates/docker_manager/src/image_selector.rs)
|
||||
- [container_stop.rs](file://crates/docker_manager/src/container_stop.rs)
|
||||
|
||||
## 架构概述
|
||||
容器管理架构采用分层设计,上层为业务逻辑层,中层为容器管理服务层,底层为Docker API交互层。系统通过DockerManager单例模式提供全局容器管理服务,确保资源的统一管理和高效利用。架构支持动态网络配置,所有容器共享同一网络以便互相通信,同时通过环境变量和挂载点实现服务间的隔离。多镜像配置系统允许根据服务类型和硬件架构灵活选择镜像,提高了系统的可扩展性和适应性。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[业务应用] --> B[容器管理服务]
|
||||
B --> C[DockerManager]
|
||||
C --> D[ImageSelector]
|
||||
C --> E[ContainerStop]
|
||||
C --> F[ContainerInspector]
|
||||
C --> G[Bollard Docker Client]
|
||||
G --> H[Docker Daemon]
|
||||
style A fill:#f9f,stroke:#333
|
||||
style B fill:#bbf,stroke:#333
|
||||
style C fill:#f96,stroke:#333
|
||||
style D fill:#9f9,stroke:#333
|
||||
style E fill:#9f9,stroke:#333
|
||||
style F fill:#9f9,stroke:#333
|
||||
style G fill:#9f9,stroke:#333
|
||||
style H fill:#f9f,stroke:#333
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [manager.rs](file://crates/docker_manager/src/manager.rs)
|
||||
- [image_selector.rs](file://crates/docker_manager/src/image_selector.rs)
|
||||
- [container_stop.rs](file://crates/docker_manager/src/container_stop.rs)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### DockerManager分析
|
||||
DockerManager是容器管理的核心组件,负责容器的全生命周期管理。它通过bollard库与Docker守护进程交互,提供了创建、启动、停止、重启和清理容器的完整功能。管理器使用DashMap数据结构维护容器映射,确保多线程环境下的安全访问。系统在初始化时会自动检测主网络名称,确保新创建的容器能够正确连接到主网络。
|
||||
|
||||
#### DockerManager类图
|
||||
```mermaid
|
||||
classDiagram
|
||||
class DockerManager {
|
||||
+docker : Docker
|
||||
+config : DockerManagerConfig
|
||||
+containers : DashMap~String, DockerContainerInfo~
|
||||
+main_network_name : Arc~RwLock~String~~
|
||||
+new(config : DockerManagerConfig) DockerResult~Self~
|
||||
+create_container(config : DockerContainerConfig) DockerResult~DockerContainerInfo~
|
||||
+stop_container(project_id : &str) DockerResult~()~
|
||||
+get_container_info(project_id : &str) Option~DockerContainerInfo~
|
||||
+list_containers() Vec~DockerContainerInfo~
|
||||
+update_container_status(project_id : &str) DockerResult~Option~ContainerStatus~~
|
||||
+cleanup_all_containers() DockerResult~()~
|
||||
+get_container_logs(project_id : &str, lines : i64) DockerResult~String~
|
||||
+restart_container(project_id : &str) DockerResult~()~
|
||||
}
|
||||
class DockerContainerConfig {
|
||||
+project_id : String
|
||||
+image : String
|
||||
+name_prefix : String
|
||||
+host_path : String
|
||||
+container_path : String
|
||||
+work_dir : String
|
||||
+env_vars : HashMap~String, String~
|
||||
+port_bindings : HashMap~String, String~
|
||||
+network_mode : String
|
||||
+auto_remove : bool
|
||||
+resource_limits : Option~ResourceLimits~
|
||||
+extra_mounts : Vec~MountPoint~
|
||||
+command : Option~Vec~String~~
|
||||
+entrypoint : Option~Vec~String~~
|
||||
+network_name : Option~String~
|
||||
}
|
||||
class DockerContainerInfo {
|
||||
+container_id : String
|
||||
+container_name : String
|
||||
+project_id : String
|
||||
+image : String
|
||||
+status : ContainerStatus
|
||||
+created_at : DateTime~Utc~
|
||||
+started_at : Option~DateTime~Utc~~
|
||||
+host_path : String
|
||||
+container_path : String
|
||||
+port_bindings : HashMap~String, String~
|
||||
+assigned_port : u16
|
||||
+health_status : Option~String~
|
||||
+internal_port : u16
|
||||
+network_name : String
|
||||
}
|
||||
class DockerManagerConfig {
|
||||
+docker_host : Option~String~
|
||||
+default_image : String
|
||||
+default_platform : String
|
||||
+default_network_mode : String
|
||||
+default_work_dir : String
|
||||
+auto_cleanup : bool
|
||||
+container_ttl_seconds : Option~u64~
|
||||
+multi_image_config : MultiImageConfig
|
||||
}
|
||||
DockerManager --> DockerContainerConfig : "使用"
|
||||
DockerManager --> DockerContainerInfo : "管理"
|
||||
DockerManager --> DockerManagerConfig : "配置"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [manager.rs](file://crates/docker_manager/src/manager.rs)
|
||||
- [types.rs](file://crates/docker_manager/src/types.rs)
|
||||
|
||||
### ImageSelector分析
|
||||
ImageSelector模块负责根据服务类型和项目配置选择合适的Docker镜像。它实现了灵活的镜像选择策略,支持服务特定配置、架构特定镜像和全局默认配置。选择器会优先使用服务特定的通用镜像,如果没有则根据当前平台选择ARM64或AMD64架构的镜像,最后使用默认回退镜像。这种分层选择策略确保了系统在不同环境下的兼容性和稳定性。
|
||||
|
||||
#### 镜像选择流程图
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始选择镜像]) --> CheckServiceEnabled["检查服务是否启用"]
|
||||
CheckServiceEnabled --> |是| CheckServiceConfig["检查服务特定配置"]
|
||||
CheckServiceConfig --> CheckGenericImage["检查服务级通用镜像"]
|
||||
CheckGenericImage --> |存在| ReturnGenericImage["返回服务通用镜像"]
|
||||
CheckGenericImage --> |不存在| CheckPlatform["检查当前平台"]
|
||||
CheckPlatform --> |linux/arm64| CheckARM64Image["检查ARM64镜像"]
|
||||
CheckPlatform --> |linux/amd64| CheckAMD64Image["检查AMD64镜像"]
|
||||
CheckARM64Image --> |存在| ReturnARM64Image["返回ARM64镜像"]
|
||||
CheckARM64Image --> |不存在| ReturnDefaultImage["返回默认镜像"]
|
||||
CheckAMD64Image --> |存在| ReturnAMD64Image["返回AMD64镜像"]
|
||||
CheckAMD64Image --> |不存在| ReturnDefaultImage
|
||||
ReturnGenericImage --> End([返回镜像])
|
||||
ReturnARM64Image --> End
|
||||
ReturnAMD64Image --> End
|
||||
ReturnDefaultImage --> End
|
||||
CheckServiceEnabled --> |否| ReturnError["返回配置错误"]
|
||||
ReturnError --> End
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [image_selector.rs](file://crates/docker_manager/src/image_selector.rs)
|
||||
|
||||
### ContainerStop分析
|
||||
ContainerStop模块提供了两种容器清理策略:启动时清理和运行时清理。启动时清理用于服务启动时快速清理遗留容器,使用5秒超时并过滤409冲突错误,确保服务能快速启动。运行时清理用于运行时快速清理容器,使用3秒优雅停止超时,超时后立即强制停止,快速释放资源。两种策略都支持批量操作,通过并发处理提高清理效率。
|
||||
|
||||
#### 容器清理序列图
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Startup as 启动时清理
|
||||
participant Runtime as 运行时清理
|
||||
participant DockerManager as DockerManager
|
||||
participant Bollard as Bollard Client
|
||||
Startup->>DockerManager : startup_cleanup_containers(pattern)
|
||||
DockerManager->>DockerManager : list_containers_with_pattern(pattern)
|
||||
loop 每个匹配的容器
|
||||
DockerManager->>DockerManager : spawn async task
|
||||
DockerManager->>DockerManager : stop_container_startup_mode(container_id)
|
||||
DockerManager->>Bollard : stop_container_by_id_with_timeout(5s)
|
||||
Bollard-->>DockerManager : 响应
|
||||
DockerManager->>DockerManager : 处理结果
|
||||
end
|
||||
DockerManager-->>Startup : 返回清理结果
|
||||
Runtime->>DockerManager : runtime_cleanup_container(container_id)
|
||||
DockerManager->>DockerManager : stop_container_runtime_mode(container_id)
|
||||
DockerManager->>Bollard : stop_container_by_id_with_timeout(3s)
|
||||
Bollard-->>DockerManager : 响应
|
||||
DockerManager->>DockerManager : 等待POST_STOP_WAIT_MS
|
||||
DockerManager-->>Runtime : 响应
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [container_stop.rs](file://crates/docker_manager/src/container_stop.rs)
|
||||
|
||||
## 依赖分析
|
||||
容器管理模块依赖于多个外部库和内部组件。主要依赖包括bollard(Docker API客户端)、tokio(异步运行时)、serde(序列化)、tracing(日志记录)和shared_types(共享类型定义)。模块通过Cargo.toml文件管理这些依赖,确保版本的一致性和兼容性。内部依赖关系清晰,docker_manager模块依赖shared_types模块获取配置类型,而rcoder主应用依赖docker_manager模块提供容器管理服务。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[docker_manager] --> B[bollard]
|
||||
A --> C[tokio]
|
||||
A --> D[serde]
|
||||
A --> E[tracing]
|
||||
A --> F[shared_types]
|
||||
G[rcoder] --> A
|
||||
H[agent_runner] --> A
|
||||
style A fill:#f96,stroke:#333
|
||||
style B fill:#9f9,stroke:#333
|
||||
style C fill:#9f9,stroke:#333
|
||||
style D fill:#9f9,stroke:#333
|
||||
style E fill:#9f9,stroke:#333
|
||||
style F fill:#9f9,stroke:#333
|
||||
style G fill:#bbf,stroke:#333
|
||||
style H fill:#bbf,stroke:#333
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [Cargo.toml](file://crates/docker_manager/Cargo.toml)
|
||||
|
||||
## 性能考虑
|
||||
容器管理架构在设计时充分考虑了性能因素。通过使用Arc和RwLock等并发原语,确保多线程环境下的高效访问。容器操作采用异步模式,避免阻塞主线程。批量操作通过并发处理提高效率,如启动时清理会并发停止所有匹配的容器。资源限制配置允许为每个容器设置内存和CPU限制,防止资源耗尽。网络配置优化减少了端口映射的需求,通过内部网络通信提高性能。
|
||||
|
||||
## 故障排除指南
|
||||
当容器管理出现问题时,可以按照以下步骤进行排查:首先检查Docker守护进程是否正常运行,然后查看容器日志获取详细错误信息。对于镜像拉取失败,检查网络连接和镜像仓库权限。对于容器启动失败,检查资源限制是否过于严格。对于网络连接问题,验证容器是否正确连接到主网络。系统提供了详细的日志记录,包括DEBUG级别的调试信息,有助于快速定位问题。
|
||||
|
||||
**Section sources**
|
||||
- [manager.rs](file://crates/docker_manager/src/manager.rs)
|
||||
- [container_stop.rs](file://crates/docker_manager/src/container_stop.rs)
|
||||
|
||||
## 结论
|
||||
RCoder的容器管理架构设计合理,功能完整,能够有效支持系统的动态容器化需求。通过DockerManager、ImageSelector和ContainerStop等组件的协同工作,实现了容器全生命周期的自动化管理。架构支持多镜像配置和动态网络,具有良好的可扩展性和适应性。安全性考虑和性能优化措施确保了系统的稳定运行。未来可以进一步优化资源利用率和故障恢复机制,提升整体系统性能。
|
||||
218
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/核心模块架构.md
Normal file
218
qiming-rcoder/.qoder/repowiki/zh/content/核心模块架构/核心模块架构.md
Normal file
@@ -0,0 +1,218 @@
|
||||
# 核心模块架构
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [main.rs](file://crates/rcoder/src/main.rs)
|
||||
- [lib.rs](file://crates/rcoder/src/lib.rs)
|
||||
- [config.rs](file://crates/rcoder/src/config.rs)
|
||||
- [Cargo.toml](file://crates/rcoder/Cargo.toml)
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs)
|
||||
- [multi_image_config.rs](file://crates/shared_types/src/multi_image_config.rs)
|
||||
- [Dockerfile](file://docker/Dockerfile)
|
||||
- [docker-compose.yml](file://docker/docker-compose.yml)
|
||||
- [pingora-proxy](file://crates/pingora-proxy/src/lib.rs)
|
||||
- [docker_manager](file://crates/docker_manager/src/lib.rs)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概述](#架构概述)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
rcoder 是一个基于 Rust 的 AI 代理框架,旨在为 AI 驱动的开发平台提供核心服务。该系统通过集成多种 AI 代理(如 Claude 和 Codex),为项目提供智能开发支持。架构设计强调模块化、可扩展性和容器化部署,通过反向代理和 Docker 管理实现灵活的服务集成和资源隔离。
|
||||
|
||||
## 项目结构
|
||||
项目采用多 crate 的 Rust 工作区结构,核心模块包括 rcoder、agent_runner、shared_types、docker_manager 和 pingora-proxy。这种模块化设计实现了关注点分离,每个 crate 负责特定功能,通过工作区依赖进行集成。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[crates/] --> B[rcoder]
|
||||
A --> C[agent_runner]
|
||||
A --> D[shared_types]
|
||||
A --> E[docker_manager]
|
||||
A --> F[pingora-proxy]
|
||||
A --> G[acp_adapter]
|
||||
A --> H[claude-code-agent]
|
||||
A --> I[codex-acp-agent]
|
||||
B --> J[src/]
|
||||
C --> K[src/]
|
||||
D --> L[src/]
|
||||
E --> M[src/]
|
||||
F --> N[src/]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [Cargo.toml](file://Cargo.toml#L1-L205)
|
||||
|
||||
**本节来源**
|
||||
- [Cargo.toml](file://Cargo.toml#L1-L205)
|
||||
|
||||
## 核心组件
|
||||
系统核心由 rcoder 主服务、agent_runner 代理管理、shared_types 共享类型、docker_manager 容器管理和 pingora-proxy 反向代理组成。rcoder 作为主入口,协调各组件工作;agent_runner 管理 AI 代理生命周期;shared_types 提供跨 crate 的数据结构;docker_manager 处理容器操作;pingora-proxy 实现动态请求代理。
|
||||
|
||||
**本节来源**
|
||||
- [main.rs](file://crates/rcoder/src/main.rs#L1-L451)
|
||||
- [Cargo.toml](file://crates/rcoder/Cargo.toml#L1-L91)
|
||||
|
||||
## 架构概述
|
||||
系统采用微服务架构,以 rcoder 为核心协调器,通过 HTTP API 接收外部请求,动态创建和管理 AI 代理容器。架构支持多代理类型,通过 ACP 协议与代理通信,并利用反向代理实现服务发现和负载均衡。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Client[客户端] --> |HTTP请求| Rcoder[rcoder主服务]
|
||||
Rcoder --> |创建容器| Docker[Docker引擎]
|
||||
Docker --> |运行| AgentContainer[AI代理容器]
|
||||
AgentContainer --> |ACP协议| Rcoder
|
||||
Rcoder --> |SSE流| Client
|
||||
Rcoder --> |反向代理| Pingora[pingora-proxy]
|
||||
Pingora --> |动态路由| Backend[后端服务]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [main.rs](file://crates/rcoder/src/main.rs#L1-L451)
|
||||
- [pingora-proxy](file://crates/pingora-proxy/src/lib.rs#L1-L250)
|
||||
|
||||
**本节来源**
|
||||
- [main.rs](file://crates/rcoder/src/main.rs#L1-L451)
|
||||
- [pingora-proxy](file://crates/pingora-proxy/src/lib.rs#L1-L250)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### rcoder 主服务分析
|
||||
rcoder 是系统的核心服务,负责处理客户端请求、管理代理生命周期和协调系统组件。它通过 Axum 框架提供 REST API,集成 OpenTelemetry 进行遥测,并支持优雅关闭。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AppConfig {
|
||||
+default_agent : AgentType
|
||||
+projects_dir : PathBuf
|
||||
+port : u16
|
||||
+proxy_config : Option<ProxyConfig>
|
||||
+docker_config : Option<DockerConfig>
|
||||
}
|
||||
class CliArgs {
|
||||
+port : Option<u16>
|
||||
+projects_dir : Option<String>
|
||||
+enable_proxy : bool
|
||||
+proxy_port : Option<u16>
|
||||
+default_backend_port : Option<u16>
|
||||
}
|
||||
class AppState {
|
||||
+config : AppConfig
|
||||
+pingora_service : Option<PingoraProxyService>
|
||||
}
|
||||
AppConfig --> CliArgs : "命令行参数覆盖"
|
||||
AppState --> AppConfig : "包含配置"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [config.rs](file://crates/rcoder/src/config.rs#L1-L403)
|
||||
- [main.rs](file://crates/rcoder/src/main.rs#L1-L451)
|
||||
|
||||
**本节来源**
|
||||
- [main.rs](file://crates/rcoder/src/main.rs#L1-L451)
|
||||
- [config.rs](file://crates/rcoder/src/config.rs#L1-L403)
|
||||
|
||||
### Agent 生命周期管理
|
||||
系统通过 RAII 模式管理 AI 代理的生命周期,确保资源的正确清理。AgentLifecycleGuard 在 drop 时自动执行清理操作,防止资源泄漏。
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Idle
|
||||
Idle --> Active : "收到请求"
|
||||
Active --> Terminating : "收到取消信号"
|
||||
Terminating --> Idle : "清理完成"
|
||||
Active --> Idle : "任务完成"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
|
||||
**本节来源**
|
||||
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L1-L483)
|
||||
|
||||
### 多镜像配置系统
|
||||
系统支持灵活的多镜像配置,允许为不同服务类型指定不同的 Docker 镜像。配置系统包含全局默认、服务特定配置和选择策略。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class MultiImageConfig {
|
||||
+global_defaults : GlobalImageDefaults
|
||||
+services : HashMap<String, ServiceImageConfig>
|
||||
+selection_strategy : ImageSelectionStrategy
|
||||
+cache_config : ImageCacheConfig
|
||||
}
|
||||
class GlobalImageDefaults {
|
||||
+image : Option<String>
|
||||
+arm64_image : Option<String>
|
||||
+amd64_image : Option<String>
|
||||
+default_image : Option<String>
|
||||
+registry_prefix : Option<String>
|
||||
}
|
||||
class ServiceImageConfig {
|
||||
+service_type : ServiceType
|
||||
+image : Option<String>
|
||||
+arm64_image : Option<String>
|
||||
+amd64_image : Option<String>
|
||||
+default_image : Option<String>
|
||||
+mounts : Vec<ServiceMountConfig>
|
||||
+environment : HashMap<String, String>
|
||||
+enabled : bool
|
||||
}
|
||||
MultiImageConfig --> GlobalImageDefaults : "包含"
|
||||
MultiImageConfig --> ServiceImageConfig : "包含多个"
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [multi_image_config.rs](file://crates/shared_types/src/multi_image_config.rs#L1-L604)
|
||||
|
||||
**本节来源**
|
||||
- [multi_image_config.rs](file://crates/shared_types/src/multi_image_config.rs#L1-L604)
|
||||
|
||||
## 依赖分析
|
||||
系统依赖关系清晰,rcoder 依赖 agent_runner、shared_types、docker_manager 和 pingora-proxy。shared_types 作为共享库,被多个 crate 依赖,提供统一的数据结构和协议定义。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
Rcoder[rcoder] --> AgentRunner[agent_runner]
|
||||
Rcoder --> SharedTypes[shared_types]
|
||||
Rcoder --> DockerManager[docker_manager]
|
||||
Rcoder --> PingoraProxy[pingora-proxy]
|
||||
AgentRunner --> SharedTypes
|
||||
DockerManager --> SharedTypes
|
||||
PingoraProxy --> SharedTypes
|
||||
SharedTypes --> ACP[agent-client-protocol]
|
||||
```
|
||||
|
||||
**图表来源**
|
||||
- [Cargo.toml](file://crates/rcoder/Cargo.toml#L1-L91)
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml#L1-L79)
|
||||
|
||||
**本节来源**
|
||||
- [Cargo.toml](file://crates/rcoder/Cargo.toml#L1-L91)
|
||||
- [Cargo.toml](file://crates/agent_runner/Cargo.toml#L1-L79)
|
||||
|
||||
## 性能考虑
|
||||
系统在性能方面进行了多项优化:使用 Tokio 异步运行时处理并发请求,通过 DashMap 实现高效的状态管理,利用连接池减少资源开销。日志系统采用按天滚动策略,平衡了性能和可维护性。
|
||||
|
||||
**本节来源**
|
||||
- [main.rs](file://crates/rcoder/src/main.rs#L1-L451)
|
||||
- [config.rs](file://crates/rcoder/src/config.rs#L1-L403)
|
||||
|
||||
## 故障排除指南
|
||||
系统提供了完善的故障排除机制,包括详细的日志记录、健康检查端点和调试工具。Docker 配置问题可通过环境变量和挂载检查解决,代理通信问题可通过日志级别调整进行诊断。
|
||||
|
||||
**本节来源**
|
||||
- [main.rs](file://crates/rcoder/src/main.rs#L1-L451)
|
||||
- [Dockerfile](file://docker/Dockerfile#L1-L305)
|
||||
- [docker-compose.yml](file://docker/docker-compose.yml#L1-L37)
|
||||
|
||||
## 结论
|
||||
rcoder 架构设计合理,模块化程度高,具备良好的可扩展性和可维护性。通过微服务架构和容器化部署,系统能够灵活适应不同规模和需求的 AI 开发场景。未来可进一步优化性能监控和自动化部署流程。
|
||||
Reference in New Issue
Block a user