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

391 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 代理状态模型
<cite>
**本文引用的文件**
- [agent.proto](file://crates/shared_types/proto/agent.proto)
- [agent.rs](file://crates/shared_types/src/grpc/agent.rs)
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs)
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs)
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs)
- [mod.rsproxy_agent](file://crates/agent_runner/src/proxy_agent/mod.rs)
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs)
- [agent-abstraction-layer-design.md](file://specs/agent-abstraction-layer-design.md)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
## 简介
本文件系统化梳理代理状态模型,聚焦以下目标:
- 解释 AgentStatusResponse、AgentType 等关键类型
- 对比不同 AI 代理Codex、Claude Code的状态表示与统一抽象机制
- 说明状态查询接口的数据输出格式、字段含义与扩展点
- 结合 agent_status_handler 的实现,展示状态聚合逻辑与错误传播路径
- 提供 gRPC 协议映射细节(来自 agent.proto与 JSON 序列化示例
## 项目结构
围绕“代理状态模型”的相关模块分布如下:
- 协议与序列化shared_types/proto/agent.proto 与生成的 gRPC 客户端/服务端代码
- 数据模型shared_types/src/model 下的 agent_model.rs、agent_type.rs、model_provider.rs、http_result.rs、app_error.rs
- HTTP 状态查询处理器agent_runner 与 rcoder 两处实现
- 代理抽象与生命周期agent_runner/proxy_agent 下的抽象层与生命周期管理
```mermaid
graph TB
subgraph "共享类型与协议"
P["agent.proto<br/>gRPC 定义"]
G["agent.rs<br/>生成的gRPC客户端/服务端"]
M["agent_model.rs<br/>AgentStatusResponse/AgentStatus"]
T["agent_type.rs<br/>AgentType/Claude/Codex"]
MP["model_provider.rs<br/>ModelProviderConfig/SafeInfo"]
HR["http_result.rs<br/>统一HTTP响应结构"]
AE["app_error.rs<br/>应用错误类型"]
end
subgraph "HTTP状态查询"
AR["agent_status_handler.rsagent_runner"]
RC["agent_status_handler.rsrcoder"]
end
subgraph "代理抽象与生命周期"
PA["proxy_agent/mod.rs<br/>PROJECT_AND_AGENT_INFO_MAP"]
AS["agent_service.rs<br/>AcpAgentService"]
end
P --> G
M --> AR
M --> RC
T --> AR
T --> RC
MP --> AR
MP --> RC
HR --> AR
HR --> RC
AE --> AR
AE --> RC
PA --> AR
AS --> AR
```
图表来源
- [agent.proto](file://crates/shared_types/proto/agent.proto#L1-L98)
- [agent.rs](file://crates/shared_types/src/grpc/agent.rs#L1-L120)
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L32-L117)
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L16-L63)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L43-L132)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L103)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L1-L122)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L1-L132)
- [mod.rsproxy_agent](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
章节来源
- [agent.proto](file://crates/shared_types/proto/agent.proto#L1-L98)
- [agent.rs](file://crates/shared_types/src/grpc/agent.rs#L1-L120)
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L32-L117)
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L16-L63)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L43-L132)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L103)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L1-L122)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L1-L132)
- [mod.rsproxy_agent](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
- [agent_service.rs](file://crates/agent_runner/src/proxy_agent/agent_service.rs#L1-L62)
## 核心组件
- AgentStatusResponseHTTP 状态查询的统一响应载体包含项目标识、存活标记、会话ID、代理状态、时间戳与模型提供商安全信息。
- AgentStatus共享的代理服务状态枚举抽象了 Active、Idle、Terminating 等状态。
- AgentType代理类型枚举区分 Claude 与 Codex并提供从模型提供商配置推断类型的能力。
- ModelProviderConfig/SafeInfo模型提供商配置与脱敏后的安全信息用于在状态响应中安全暴露必要元数据。
- gRPC GetStatusagent.proto 中定义的 GetStatusRequest/GetStatusResponse字段为字符串形式的状态码。
- HTTP 层agent_status_handler.rs两套实现负责参数校验、状态聚合与错误传播。
章节来源
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L32-L117)
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L16-L63)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L43-L132)
- [agent.proto](file://crates/shared_types/proto/agent.proto#L69-L76)
- [agent.rs](file://crates/shared_types/src/grpc/agent.rs#L82-L91)
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132)
## 架构总览
状态查询的端到端流程如下:
- HTTP 层:接收 /agent/status/{project_id} 请求,进行参数校验与错误传播
- 聚合层:从全局映射中读取项目对应的代理信息(含 AgentStatus、会话ID、时间戳、模型提供商
- 输出层:构造 AgentStatusResponse按 is_alive 控制可选字段的序列化
- gRPC 层GetStatus 以字符串状态码返回,与 HTTP 层的 AgentStatus 枚举形成互补
```mermaid
sequenceDiagram
participant C as "客户端"
participant H as "HTTP处理器<br/>agent_status_handler.rs"
participant M as "状态映射<br/>PROJECT_AND_AGENT_INFO_MAP"
participant R as "响应构造<br/>AgentStatusResponse"
C->>H : GET /agent/status/{project_id}
H->>H : 校验project_id
alt 有效
H->>M : 读取项目代理信息
M-->>H : 返回Agent信息(含AgentStatus/时间戳/模型提供商)
H->>R : 构造AgentStatusResponse(is_alive=true)
R-->>C : JSON响应(success=true,data=完整状态)
else 无效
H-->>C : JSON响应(success=false,error=INVALID_PARAMS)
end
```
图表来源
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132)
- [mod.rsproxy_agent](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L32-L117)
## 详细组件分析
### AgentStatusResponse 与 AgentStatus
- 字段与语义
- project_id项目唯一标识
- is_alive代理是否存活true 表示存在且健康)
- session_id仅在 is_alive=true 时存在
- status仅在 is_alive=true 时存在,枚举值为 Active/Idle/Terminating
- last_activity/created_at仅在 is_alive=true 时存在
- model_provider仅在 is_alive=true 时存在,使用脱敏后的安全信息
- 序列化策略
- 使用 serde 的 skip_serializing_if 控制可选字段的输出
- 通过 http_result.rs 的统一结构体包装 success、code、message、tid 与 data
```mermaid
classDiagram
class AgentStatusResponse {
+string project_id
+bool is_alive
+string session_id?
+AgentStatus status?
+datetime last_activity?
+datetime created_at?
+ModelProviderSafeInfo model_provider?
}
class AgentStatus {
<<enum>>
+Active
+Idle
+Terminating
}
class ModelProviderSafeInfo {
+string id
+string name
+string api_protocol
+string default_model
}
AgentStatusResponse --> AgentStatus : "包含"
AgentStatusResponse --> ModelProviderSafeInfo : "包含"
```
图表来源
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L70-L117)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L117-L132)
章节来源
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L70-L117)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L103)
### AgentType 抽象与多代理支持
- AgentType 枚举Claude 与 Codex条件编译 feature
- 类型推断:根据 ModelProviderConfig 的 name 推断代理类型,默认 Claude
- 环境注入:提供从环境变量构建 Claude/Codex 模型提供商配置的方法
```mermaid
classDiagram
class AgentType {
<<enum>>
+Claude
+Codex?
}
class ModelProviderConfig {
+string id
+string name
+string base_url
+string api_key
+bool requires_openai_auth
+string default_model
+string api_protocol?
+to_safe_info()
}
AgentType --> ModelProviderConfig : "推断/配置"
```
图表来源
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L16-L63)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L43-L132)
章节来源
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L16-L63)
- [model_provider.rs](file://crates/shared_types/src/model/model_provider.rs#L43-L132)
### gRPC GetStatus 协议映射
- 定义位置agent.proto 中的 GetStatusRequest/GetStatusResponse
- 字段GetStatusResponse.status 为字符串,取值为 "idle"、"busy"、"error"
- 生成代码agent.rs 中包含 GetStatus 的客户端与服务端方法签名
```mermaid
flowchart TD
Start(["gRPC调用 GetStatus"]) --> Req["构造GetStatusRequest(project_id)"]
Req --> Call["调用AgentService.get_status"]
Call --> Resp["返回GetStatusResponse(status)"]
Resp --> Map["映射到HTTP层AgentStatus枚举"]
Map --> Out["HTTP层AgentStatusResponse输出"]
```
图表来源
- [agent.proto](file://crates/shared_types/proto/agent.proto#L69-L76)
- [agent.rs](file://crates/shared_types/src/grpc/agent.rs#L82-L91)
章节来源
- [agent.proto](file://crates/shared_types/proto/agent.proto#L69-L76)
- [agent.rs](file://crates/shared_types/src/grpc/agent.rs#L82-L91)
### HTTP 状态查询接口与聚合逻辑
- 参数校验project_id 必填且非空,否则返回 INVALID_PARAMS
- 存在性判断:从 PROJECT_AND_AGENT_INFO_MAP 获取项目代理信息
- 聚合策略:
- 存在:填充完整 AgentStatusResponse包含 session_id、status、时间戳、model_provider.safe
- 不存在:仅返回 project_id 与 is_alive=false
- 错误传播AppError 统一转为 HTTP 响应结构体,包含 success、code、message、tid
```mermaid
flowchart TD
A["收到GET /agent/status/{project_id}"] --> B["trim并校验project_id"]
B --> C{"project_id为空?"}
C -- 是 --> E["返回HttpResult.error(INVALID_PARAMS)"]
C -- 否 --> D["从PROJECT_AND_AGENT_INFO_MAP读取"]
D --> F{"是否存在代理?"}
F -- 是 --> G["构造完整AgentStatusResponse(is_alive=true)"]
F -- 否 --> H["构造简化AgentStatusResponse(is_alive=false)"]
G --> I["返回HttpResult.success"]
H --> I
E --> J["返回HttpResult.error"]
```
图表来源
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L103)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
- [mod.rsproxy_agent](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
章节来源
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L103)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
- [mod.rsproxy_agent](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
### 不同代理Codex、Claude Code的状态表示与统一抽象
- HTTP 层AgentStatusResponse 的 status 字段为 Active/Idle/Terminating 枚举,统一表达代理的运行态
- gRPC 层GetStatusResponse.status 为字符串,取值为 "idle"、"busy"、"error",与 HTTP 枚举形成互补
- 类型抽象AgentType 统一区分 Claude 与 Codex便于在上层进行差异化配置与行为控制
章节来源
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L32-L61)
- [agent_type.rs](file://crates/shared_types/src/model/agent_type.rs#L16-L63)
- [agent.proto](file://crates/shared_types/proto/agent.proto#L69-L76)
- [agent.rs](file://crates/shared_types/src/grpc/agent.rs#L82-L91)
### JSON 序列化示例与字段含义
- 成功响应(代理存活)
- success: true
- data: 包含 project_id、is_alive(true)、session_id、status、last_activity、created_at、model_provider.safe
- 成功响应(代理不存活)
- success: true
- data: 包含 project_id、is_alive(false)
- 失败响应(参数错误)
- success: false
- error: 包含 code、message
章节来源
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L12-L69)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L12-L67)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L103)
## 依赖关系分析
- 低耦合与高内聚
- HTTP 层仅依赖共享模型AgentStatusResponse、AgentStatus、ModelProviderSafeInfo不直接依赖具体代理实现
- gRPC 层独立于 HTTP 层,二者通过共享的模型与协议文件解耦
- 关键依赖链
- HTTP 处理器依赖PROJECT_AND_AGENT_INFO_MAP、AgentStatusResponse、HttpResult、AppError
- 代理抽象依赖AgentType、AcpAgentService、生命周期管理AgentLifecycle
```mermaid
graph LR
AR["agent_status_handler.rsagent_runner"] --> MAP["PROJECT_AND_AGENT_INFO_MAP"]
AR --> RESP["AgentStatusResponse"]
AR --> HTTP["HttpResult"]
AR --> ERR["AppError"]
RC["agent_status_handler.rsrcoder"] --> MAP
RC --> RESP
RC --> HTTP
RC --> ERR
RESP --> STAT["AgentStatus"]
RESP --> MP["ModelProviderSafeInfo"]
AS["agent_service.rs"] --> AT["AgentType"]
```
图表来源
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L1-L122)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L1-L132)
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L32-L117)
- [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#L16-L63)
- [mod.rsproxy_agent](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
章节来源
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L1-L122)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L1-L132)
- [agent_model.rs](file://crates/shared_types/src/model/agent_model.rs#L32-L117)
- [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#L16-L63)
- [mod.rsproxy_agent](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256)
## 性能考量
- 读取开销状态查询仅访问内存映射表DashMap读操作为 O(1) 量级
- 序列化成本AgentStatusResponse 采用 serdeskip_serializing_if 减少冗余字段输出
- 错误路径短路:参数校验失败立即返回,避免不必要的映射查找
- 并发安全:代理信息结构体通过 Arc/Mutex 等并发原语保护(生命周期管理),状态查询不持有写锁
[本节为通用性能讨论,不直接分析具体文件]
## 故障排查指南
- 参数错误
- 现象:返回 INVALID_PARAMS
- 排查:确认 project_id 非空且去除前后空白
- 代理不存在
- 现象is_alive=false其余字段省略
- 排查:确认项目是否已创建代理服务;检查生命周期管理与清理逻辑
- 错误传播
- AppError 统一转为 HTTP 响应结构体,包含 success、code、message、tid
- gRPC 层的 GetStatus 返回字符串状态码,注意与 HTTP 枚举的映射关系
章节来源
- [agent_status_handler.rsagent_runner](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122)
- [agent_status_handler.rsrcoder](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132)
- [app_error.rs](file://crates/shared_types/src/model/app_error.rs#L1-L65)
- [http_result.rs](file://crates/shared_types/src/model/http_result.rs#L24-L103)
## 结论
- AgentStatusResponse 与 AgentStatus 提供了跨代理的一致状态视图,满足 HTTP 与 gRPC 双栈需求
- AgentType 抽象确保 Claude 与 Codex 在配置与行为层面的统一入口
- 状态查询接口通过最小化参数校验与内存映射读取,实现高效稳定的可观测性
- 扩展建议
- 在 gRPC 层引入更丰富的状态枚举(如 error 详情),并与 HTTP 层对齐
- 在 AgentStatusResponse 中增加健康检查指标(如最近一次错误时间、重启次数)以增强可观测性
- 在生命周期管理中补充 Termination 阶段的细化状态,以便更精确地反映代理终止过程