添加qiming-rcoder模块
This commit is contained in:
@@ -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)
|
||||
Reference in New Issue
Block a user