18 KiB
18 KiB
代理状态模型
**本文引用的文件** - [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.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs) - [agent_status_handler.rs(rcoder)](file://crates/rcoder/src/handler/agent_status_handler.rs) - [mod.rs(proxy_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)目录
简介
本文件系统化梳理代理状态模型,聚焦以下目标:
- 解释 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 下的抽象层与生命周期管理
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
- agent.rs
- agent_model.rs
- agent_type.rs
- model_provider.rs
- http_result.rs
- app_error.rs
- agent_status_handler.rs(agent_runner)
- agent_status_handler.rs(rcoder)
- mod.rs(proxy_agent)
- agent_service.rs
章节来源
- agent.proto
- agent.rs
- agent_model.rs
- agent_type.rs
- model_provider.rs
- http_result.rs
- app_error.rs
- agent_status_handler.rs(agent_runner)
- agent_status_handler.rs(rcoder)
- mod.rs(proxy_agent)
- agent_service.rs
核心组件
- AgentStatusResponse:HTTP 状态查询的统一响应载体,包含项目标识、存活标记、会话ID、代理状态、时间戳与模型提供商安全信息。
- AgentStatus:共享的代理服务状态枚举,抽象了 Active、Idle、Terminating 等状态。
- AgentType:代理类型枚举,区分 Claude 与 Codex,并提供从模型提供商配置推断类型的能力。
- ModelProviderConfig/SafeInfo:模型提供商配置与脱敏后的安全信息,用于在状态响应中安全暴露必要元数据。
- gRPC GetStatus:agent.proto 中定义的 GetStatusRequest/GetStatusResponse,字段为字符串形式的状态码。
- HTTP 层:agent_status_handler.rs(两套实现)负责参数校验、状态聚合与错误传播。
章节来源
- agent_model.rs
- agent_type.rs
- model_provider.rs
- agent.proto
- agent.rs
- agent_status_handler.rs(agent_runner)
- agent_status_handler.rs(rcoder)
架构总览
状态查询的端到端流程如下:
- HTTP 层:接收 /agent/status/{project_id} 请求,进行参数校验与错误传播
- 聚合层:从全局映射中读取项目对应的代理信息(含 AgentStatus、会话ID、时间戳、模型提供商)
- 输出层:构造 AgentStatusResponse,按 is_alive 控制可选字段的序列化
- gRPC 层:GetStatus 以字符串状态码返回,与 HTTP 层的 AgentStatus 枚举形成互补
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.rs(agent_runner)
- agent_status_handler.rs(rcoder)
- mod.rs(proxy_agent)
- agent_model.rs
详细组件分析
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
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 : "包含"
图表来源
章节来源
AgentType 抽象与多代理支持
- AgentType 枚举:Claude 与 Codex(条件编译 feature)
- 类型推断:根据 ModelProviderConfig 的 name 推断代理类型,默认 Claude
- 环境注入:提供从环境变量构建 Claude/Codex 模型提供商配置的方法
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 : "推断/配置"
图表来源
章节来源
gRPC GetStatus 协议映射
- 定义位置:agent.proto 中的 GetStatusRequest/GetStatusResponse
- 字段:GetStatusResponse.status 为字符串,取值为 "idle"、"busy"、"error"
- 生成代码:agent.rs 中包含 GetStatus 的客户端与服务端方法签名
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输出"]
图表来源
章节来源
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
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.rs(agent_runner)
- agent_status_handler.rs(rcoder)
- http_result.rs
- app_error.rs
- mod.rs(proxy_agent)
章节来源
- agent_status_handler.rs(agent_runner)
- agent_status_handler.rs(rcoder)
- http_result.rs
- app_error.rs
- mod.rs(proxy_agent)
不同代理(Codex、Claude Code)的状态表示与统一抽象
- HTTP 层:AgentStatusResponse 的 status 字段为 Active/Idle/Terminating 枚举,统一表达代理的运行态
- gRPC 层:GetStatusResponse.status 为字符串,取值为 "idle"、"busy"、"error",与 HTTP 枚举形成互补
- 类型抽象:AgentType 统一区分 Claude 与 Codex,便于在上层进行差异化配置与行为控制
章节来源
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
章节来源
依赖关系分析
- 低耦合与高内聚
- HTTP 层仅依赖共享模型(AgentStatusResponse、AgentStatus、ModelProviderSafeInfo),不直接依赖具体代理实现
- gRPC 层独立于 HTTP 层,二者通过共享的模型与协议文件解耦
- 关键依赖链
- HTTP 处理器依赖:PROJECT_AND_AGENT_INFO_MAP、AgentStatusResponse、HttpResult、AppError
- 代理抽象依赖:AgentType、AcpAgentService、生命周期管理(AgentLifecycle)
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.rs(agent_runner)
- agent_status_handler.rs(rcoder)
- agent_model.rs
- agent_service.rs
- agent_type.rs
- mod.rs(proxy_agent)
章节来源
- agent_status_handler.rs(agent_runner)
- agent_status_handler.rs(rcoder)
- agent_model.rs
- agent_service.rs
- agent_type.rs
- mod.rs(proxy_agent)
性能考量
- 读取开销:状态查询仅访问内存映射表(DashMap),读操作为 O(1) 量级
- 序列化成本:AgentStatusResponse 采用 serde,skip_serializing_if 减少冗余字段输出
- 错误路径短路:参数校验失败立即返回,避免不必要的映射查找
- 并发安全:代理信息结构体通过 Arc/Mutex 等并发原语保护(生命周期管理),状态查询不持有写锁
[本节为通用性能讨论,不直接分析具体文件]
故障排查指南
- 参数错误
- 现象:返回 INVALID_PARAMS
- 排查:确认 project_id 非空且去除前后空白
- 代理不存在
- 现象:is_alive=false,其余字段省略
- 排查:确认项目是否已创建代理服务;检查生命周期管理与清理逻辑
- 错误传播
- AppError 统一转为 HTTP 响应结构体,包含 success、code、message、tid
- gRPC 层的 GetStatus 返回字符串状态码,注意与 HTTP 枚举的映射关系
章节来源
结论
- AgentStatusResponse 与 AgentStatus 提供了跨代理的一致状态视图,满足 HTTP 与 gRPC 双栈需求
- AgentType 抽象确保 Claude 与 Codex 在配置与行为层面的统一入口
- 状态查询接口通过最小化参数校验与内存映射读取,实现高效稳定的可观测性
- 扩展建议
- 在 gRPC 层引入更丰富的状态枚举(如 error 详情),并与 HTTP 层对齐
- 在 AgentStatusResponse 中增加健康检查指标(如最近一次错误时间、重启次数)以增强可观测性
- 在生命周期管理中补充 Termination 阶段的细化状态,以便更精确地反映代理终止过程