# 代理状态模型 **本文引用的文件** - [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) ## 目录 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
gRPC 定义"] G["agent.rs
生成的gRPC客户端/服务端"] M["agent_model.rs
AgentStatusResponse/AgentStatus"] T["agent_type.rs
AgentType/Claude/Codex"] MP["model_provider.rs
ModelProviderConfig/SafeInfo"] HR["http_result.rs
统一HTTP响应结构"] AE["app_error.rs
应用错误类型"] end subgraph "HTTP状态查询" AR["agent_status_handler.rsagent_runner"] RC["agent_status_handler.rsrcoder"] end subgraph "代理抽象与生命周期" PA["proxy_agent/mod.rs
PROJECT_AND_AGENT_INFO_MAP"] AS["agent_service.rs
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.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L1-L122) - [agent_status_handler.rs(rcoder)](file://crates/rcoder/src/handler/agent_status_handler.rs#L1-L132) - [mod.rs(proxy_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.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L1-L122) - [agent_status_handler.rs(rcoder)](file://crates/rcoder/src/handler/agent_status_handler.rs#L1-L132) - [mod.rs(proxy_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) ## 核心组件 - 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](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.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122) - [agent_status_handler.rs(rcoder)](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处理器
agent_status_handler.rs" participant M as "状态映射
PROJECT_AND_AGENT_INFO_MAP" participant R as "响应构造
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)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122) - [agent_status_handler.rs(rcoder)](file://crates/rcoder/src/handler/agent_status_handler.rs#L72-L132) - [mod.rs(proxy_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 { <> +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 { <> +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.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122) - [agent_status_handler.rs(rcoder)](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.rs(proxy_agent)](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256) 章节来源 - [agent_status_handler.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122) - [agent_status_handler.rs(rcoder)](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.rs(proxy_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.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L12-L69) - [agent_status_handler.rs(rcoder)](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.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L1-L122) - [agent_status_handler.rs(rcoder)](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.rs(proxy_agent)](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256) 章节来源 - [agent_status_handler.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L1-L122) - [agent_status_handler.rs(rcoder)](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.rs(proxy_agent)](file://crates/agent_runner/src/proxy_agent/mod.rs#L1-L256) ## 性能考量 - 读取开销:状态查询仅访问内存映射表(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 枚举的映射关系 章节来源 - [agent_status_handler.rs(agent_runner)](file://crates/agent_runner/src/handler/agent_status_handler.rs#L70-L122) - [agent_status_handler.rs(rcoder)](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 阶段的细化状态,以便更精确地反映代理终止过程