Files
qiming/qiming-rcoder/specs/history/agent-abstraction-layer-design.md
2026-06-01 13:54:52 +08:00

132 KiB
Raw Permalink Blame History

Agent 抽象层设计方案

1. 概述

本设计旨在解决 RCoder 项目中 Agent、MCP 服务器和提示词硬编码的核心问题,通过构建独立的配置化模块实现动态扩展能力。

🎯 核心目标

  • Agent 动态配置:支持多种 AI Agent 类型的插件化管理和运行
  • MCP 服务动态配置:支持 MCP 服务器的热插拔和统一管理
  • 提示词模板化:将系统提示词和用户提示词包装逻辑配置化
  • 模块化架构Agent 和 MCP 以独立 library 形式提供,供 rcoder、agent_runner 等模块使用

📦 架构设计原则

  1. 配置驱动:所有 Agent、MCP、提示词通过 JSON 配置文件定义
  2. 模块解耦Agent 抽象层和 MCP 管理器作为独立的 crate 库
  3. 向后兼容:现有硬编码的 claude-code-acp 实现平滑迁移到新配置系统
  4. 零停机更新:支持运行时动态加载新的 Agent 和 MCP 服务

🏗️ 模块分层

┌─────────────────────────────────────────┐
│           RCoder 主应用                  │
├─────────────────────────────────────────┤
│         Agent Runner 模块               │
├─────────────────────────────────────────┤
│  Agent 抽象层 lib  │ MCP 管理器 lib      │
│  (多Agent支持)      │ (工具服务管理)      │
├─────────────────────────────────────────┤
│         配置管理系统                     │
│    (Agent/MCP/提示词配置)                │
└─────────────────────────────────────────┘

💡 解决的痛点

  • 硬编码问题Agent 类型、MCP 服务、提示词写死在代码中
  • 扩展困难:添加新 Agent 需要修改核心代码
  • 配置僵化:无法根据项目需求动态调整 Agent 行为
  • 维护成本:每次提示词或配置变更都需要重新编译部署

2. 现状分析

2.1 当前实现分析

基于 claude_code_agent.rs 的分析,当前 Agent 实现具有以下特征:

核心组件:

  • 进程管理:通过 tokio::process::Command 启动子进程
  • ACP 协议集成:使用 ClientSideConnection 与 Agent 通信
  • 环境变量配置:通过 merged_envs 传递模型配置
  • 生命周期管理:使用 CancellationTokenAgentLifecycleGuard
  • 错误处理:统一的错误传播机制

关键流程:

// 1. 启动子进程
let mut child = tokio::process::Command::new("claude-code-acp")
    .args(&spawn_args)
    .envs(merged_envs)
    .spawn()?;

// 2. 建立 ACP 连接
let (client_conn, handle_io) = ClientSideConnection::new(client, outgoing, incoming, |fut| {
    tokio::task::spawn_local(fut);
});

// 3. 初始化和会话管理
client_conn.initialize(init_request).await?;
let session_id = client_conn.new_session(session_request).await?;

// 4. 消息处理
super::channel_utils::spawn_prompt_handler_for_agent(/*...*/);
super::channel_utils::spawn_cancel_handler_for_agent(/*...*/);

2.2 现有抽象层

当前已具备基础的抽象:

AcpAgentService Trait

#[async_trait::async_trait(?Send)]
pub trait AcpAgentService {
    async fn start_agent_service(
        &self,
        chat_prompt: ChatPrompt,
        model_provider: Option<ModelProviderConfig>,
    ) -> Result<AcpConnectionInfo>;
    
    fn agent_type_name(&self) -> &'static str;
}

AgentType 枚举:

pub enum AgentType {
    Claude,
    #[cfg(feature = "codex")]
    Codex,
}

生命周期管理:

  • AgentLifecycleGuard - RAII 风格的资源管理
  • AgentLifecycle trait - 统一的生命周期接口

3. 设计目标

3.1 核心目标

  1. 可扩展性:支持新的 Agent 类型无需修改现有代码
  2. 配置灵活性:支持通过配置文件和环境变量管理 Agent
  3. 进程隔离:每个 Agent 运行在独立进程中,确保稳定性
  4. 统一接口:所有 Agent 使用相同的 ACP 协议接口
  5. 资源管理:统一的资源清理和错误处理机制

3.2 非功能性目标

  • 性能:最小化抽象层开销
  • 可观测性:统一的日志和监控指标
  • 安全性:隔离 Agent 进程,限制权限
  • 可测试性:支持单元测试和集成测试

4. 架构设计

4.1 整体架构

┌─────────────────────────────────────────────────────────────┐
│                    RCoder Core                              │
├─────────────────────────────────────────────────────────────┤
│                Agent Manager                                │
│  ┌─────────────────┐  ┌─────────────────┐  ┌──────────────┐ │
│  │  Agent Factory │  │ Config Manager  │  │  Registry    │ │
│  └─────────────────┘  └─────────────────┘  └──────────────┘ │
├─────────────────────────────────────────────────────────────┤
│                Agent Abstraction Layer                      │
│  ┌─────────────────┐  ┌─────────────────┐  ┌──────────────┐ │
│  │  Agent Trait    │  │  Launcher       │  │  Supervisor  │ │
│  └─────────────────┘  └─────────────────┘  └──────────────┘ │
├─────────────────────────────────────────────────────────────┤
│                Concrete Agent Implementations               │
│  ┌─────────────────┐  ┌─────────────────┐  ┌──────────────┐ │
│  │ Claude Code     │  │  Custom Agent   │  │  Future      │ │
│  │ ACP Agent       │  │  Implementation │  │  Agents      │ │
│  └─────────────────┘  └─────────────────┘  └──────────────┘ │
└─────────────────────────────────────────────────────────────┘

4.2 核心组件设计

4.2.1 Agent 抽象 Trait

/// Agent 抽象接口
#[async_trait::async_trait(?Send)]
pub trait Agent: Send + Sync {
    /// Agent 类型标识
    fn agent_type(&self) -> AgentType;
    
    /// 启动 Agent 服务
    /// 
    /// 使用 Command 方式启动 Agent 进程,并建立 ACP 连接
    async fn start(
        &self,
        config: AgentConfig,
        context: AgentContext,
    ) -> Result<AgentInstance, AgentError>;
    
    /// 停止 Agent 服务
    async fn stop(&self, instance: &AgentInstance) -> Result<(), AgentError>;
    
    /// 重启 Agent 服务
    /// 
    /// 先停止当前实例,然后重新启动
    async fn restart(
        &self,
        instance: &AgentInstance,
        config: AgentConfig,
        context: AgentContext,
    ) -> Result<AgentInstance, AgentError>;
    
    /// 获取当前 Agent 使用的配置
    fn get_config(&self, instance: &AgentInstance) -> Option<&AgentConfig>;
}

/// Agent 错误类型
#[derive(Debug, thiserror::Error)]
pub enum AgentError {
    #[error("启动失败: {0}")]
    StartupFailed(String),
    
    #[error("进程错误: {0}")]
    ProcessError(String),
    
    #[error("配置错误: {0}")]
    ConfigurationError(String),
    
    #[error("连接错误: {0}")]
    ConnectionError(String),
    
    #[error("IO错误: {0}")]
    Io(#[from] std::io::Error),
    
    #[error("其他错误: {0}")]
    Other(String),
}

#### 4.2.2 Agent 启动器

```rust
/// Agent 启动器抽象
#[async_trait::async_trait(?Send)]
pub trait AgentLauncher: Send + Sync {
    /// 启动 Agent 进程
    async fn launch(
        &self,
        spec: &AgentSpec,
        config: &AgentConfig,
        context: &AgentContext,
    ) -> Result<LaunchedAgent, AgentError>;
    
    /// 停止 Agent 进程
    async fn terminate(
        &self,
        agent: &LaunchedAgent,
        timeout: Duration,
    ) -> Result<TerminationResult, AgentError>;
    
    /// 检查进程状态
    async fn check_status(&self, agent: &LaunchedAgent) -> Result<ProcessStatus, AgentError>;
}

4.2.3 Agent 规范定义

/// Agent 规范定义
/// 
/// 基于实际 JSON 配置格式的 Agent 规范结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentSpec {
    /// Agent 唯一标识(与 JSON 配置中的 key 对应)
    pub agent_id: String,
    
    /// Agent 类型
    pub agent_type: AgentType,
    
    /// 启动命令
    pub command: String,
    
    /// 命令参数
    pub args: Vec<String>,
    
    /// 环境变量配置
    pub env: HashMap<String, String>,
    
    /// 安装配置
    pub installation: InstallationConfig,
    
    /// 🔥 新增:系统提示词配置
    pub system_prompt: Option<SystemPromptConfig>,
    
    /// 🔥 新增:用户提示词包装配置
    pub user_prompt: Option<UserPromptConfig>,
    
    /// 是否启用
    pub enabled: bool,
    
    /// 元数据信息
    pub metadata: HashMap<String, String>,
}

/// 🔥 系统提示词配置
/// 
/// 简洁设计:包含一个模板字段,支持动态变量替换
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SystemPromptConfig {
    /// 系统提示词模板内容
    /// 预处理好的完整提示词,支持变量替换(如 {PROJECT_NAME}、{FRAMEWORK} 等)
    pub template: String,
    
    /// 是否启用系统提示词(默认为 true
    #[serde(default = "default_enabled")]
    pub enabled: bool,
}

/// 默认启用状态为 true
fn default_enabled() -> bool {
    true
}

/// 🔥 新增:用户提示词包装配置
/// 
/// 用于包装用户的实际输入内容,支持模板变量 {user_prompt}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserPromptConfig {
    /// 用户提示词模板,其中 {user_prompt} 会被用户的实际输入替换
    pub template: String,
    
    /// 是否启用用户提示词包装(默认为 true
    #[serde(default = "default_enabled")]
    pub enabled: bool,
}

/// 与 JSON 配置的对应关系:
/// 
/// ```json
/// {
///   "agent_servers": {
///     "claude-code-acp": {           // ← agent_id
///       "agent_type": "claude",      // ← agent_type  
///       "command": "claude-code-acp", // ← command
///       "args": [],                  // ← args
///       "env": { ... },             // ← env
///       "system_prompt": { ... },    // ← system_prompt (系统提示词配置)
///       "user_prompt": { ... },      // ← user_prompt (用户提示词包装配置)
///       "installation": { ... },    // ← installation
///       "enabled": true,             // ← enabled
///       "metadata": { ... }          // ← metadata
///     }
///   }
/// }
/// 
/// system_prompt 示例:
/// {
///   "system_prompt": {
///     "main_prompt": "你是一个专业的 React 开发助手",
///     "domain_prompt": "专注于 React.js 和现代前端技术",
///     "style_prompt": "代码现代、简洁、注重性能",
///     "code_standards": "使用函数组件、React Hooks、TypeScript",
///     "custom_prompts": ["优先使用最佳实践", "注重用户体验"]
///   }
/// }
/// ```

4.3 配置管理系统

🔥 系统提示词使用示例:

{
  "agent_servers": {
    "react-developer": {
      "agent_type": "claude",
      "command": "claude-code-acp",
      "args": [],
      "env": {
        "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}",
        "ANTHROPIC_MODEL": "{MODEL_PROVIDER_DEFAULT_MODEL}"
      },
      "system_prompt": {
        "template": "你是一个专业的 React 开发助手专注于现代前端开发。使用函数组件、React Hooks、TypeScript注重代码性能和用户体验。遵循现代最佳实践保持代码简洁和可维护性。"
      },
      "installation": {
        "package_manager": "npm",
        "package_name": "@zed-industries/claude-code-acp",
        "version": "latest"
      },
      "enabled": true
    },
    "rust-expert": {
      "agent_type": "claude",
      "command": "claude-code-acp", 
      "args": [],
      "env": {
        "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}",
        "ANTHROPIC_MODEL": "{MODEL_PROVIDER_DEFAULT_MODEL}"
      },
      "system_prompt": {
        "template": "你是一个 Rust 专家,精通系统编程、内存安全和并发编程。编写安全、高效的 Rust 代码,遵循 Rust 最佳实践,使用 Result 处理错误,避免不必要的 unsafe 代码。注重代码的类型安全和性能优化。"
      },
      "installation": {
        "package_manager": "npm",
        "package_name": "@zed-industries/claude-code-acp", 
        "version": "latest"
      },
      "enabled": true
    },
    "data-analyst": {
      "agent_type": "claude",
      "command": "claude-code-acp",
      "args": [],
      "env": {
        "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}",
        "ANTHROPIC_MODEL": "{MODEL_PROVIDER_DEFAULT_MODEL}"
      },
      "system_prompt": {
        "template": "你是一个数据分析师,擅长数据处理、统计分析和数据可视化。使用 Python/pandas/R 进行数据分析,注重统计准确性和数据可视化效果,保护用户隐私和数据安全。"
      },
      "installation": {
        "package_manager": "npm",
        "package_name": "@zed-industries/claude-code-acp",
        "version": "latest"
      },
      "enabled": true
    }
  }
}

4.3.0 环境变量映射系统

设计理念: 为了实现 Agent 配置的标准化和灵活性,我们设计了环境变量映射系统:

  • Key环境变量名:保持每个 Agent 需要的特定环境变量名(如 ANTHROPIC_API_KEYKIMI_API_KEY
  • Value变量引用:使用标准化的 ModelProviderConfig 字段引用(如 {MODEL_PROVIDER_API_KEY}

标准变量映射:

// ModelProviderConfig 字段到环境变量的映射
pub struct ModelProviderEnvMapping {
    pub MODEL_PROVIDER_ID: String,           // 对应 ModelProviderConfig::id
    pub MODEL_PROVIDER_NAME: String,         // 对应 ModelProviderConfig::name
    pub MODEL_PROVIDER_BASE_URL: String,     // 对应 ModelProviderConfig::base_url
    pub MODEL_PROVIDER_API_KEY: String,      // 对应 ModelProviderConfig::api_key
    pub MODEL_PROVIDER_REQUIRES_OPENAI_AUTH: bool,  // 对应 ModelProviderConfig::requires_openai_auth
    pub MODEL_PROVIDER_DEFAULT_MODEL: String, // 对应 ModelProviderConfig::default_model
    pub MODEL_PROVIDER_API_PROTOCOL: Option<String>, // 对应 ModelProviderConfig::api_protocol
}

运行时变量替换:

impl AgentConfigManager {
    /// 解析环境变量中的占位符
    pub fn resolve_env_variables(
        &self, 
        env_config: &HashMap<String, String>,
        model_provider: &ModelProviderConfig
    ) -> HashMap<String, String> {
        let mut resolved_env = HashMap::new();
        
        for (key, value) in env_config {
            let resolved_value = self.replace_placeholders(value, model_provider);
            resolved_env.insert(key.clone(), resolved_value);
        }
        
        resolved_env
    }
    
    /// 替换占位符为实际值
    fn replace_placeholders(&self, template: &str, provider: &ModelProviderConfig) -> String {
        template
            .replace("{MODEL_PROVIDER_ID}", &provider.id)
            .replace("{MODEL_PROVIDER_NAME}", &provider.name)
            .replace("{MODEL_PROVIDER_BASE_URL}", &provider.base_url)
            .replace("{MODEL_PROVIDER_API_KEY}", &provider.api_key)
            .replace("{MODEL_PROVIDER_REQUIRES_OPENAI_AUTH}", &provider.requires_openai_auth.to_string())
            .replace("{MODEL_PROVIDER_DEFAULT_MODEL}", &provider.default_model)
            .replace("{MODEL_PROVIDER_API_PROTOCOL}", &provider.api_protocol.as_deref().unwrap_or(""))
    }
}

使用示例:

{
  "env": {
    "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}",
    "ANTHROPIC_BASE_URL": "{MODEL_PROVIDER_BASE_URL}",
    "ANTHROPIC_MODEL": "{MODEL_PROVIDER_DEFAULT_MODEL}"
  }
}

这种设计允许:

  1. Agent 特定的环境变量名:每个 Agent 可以使用自己期望的环境变量名
  2. 统一的配置源:所有 Agent 都从 ModelProviderConfig 获取配置值
  3. 灵活的映射:支持部分字段覆盖和自定义配置

4.3.1 Agent 配置结构

/// Agent 配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentConfig {
    /// Agent 类型
    pub agent_type: AgentType,
    
    /// 模型提供商配置
    pub model_provider: Option<ModelProviderConfig>,
    
    /// 自定义参数
    pub custom_args: Vec<String>,
    
    /// 环境变量覆盖
    pub env_overrides: HashMap<String, String>,
    
    /// 系统提示词
    pub system_prompt: Option<String>,
    
    /// 🔥 新增:用户提示词包装配置
    pub user_prompt: Option<UserPromptConfig>,
    
    /// MCP 服务器配置
    pub mcp_servers: Vec<McpServerConfig>,
}

/// MCP 服务器配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct McpServerConfig {
    /// 服务器名称
    pub name: String,
    
    /// 服务器来源类型
    pub source: McpServerSource,
    
    /// 是否启用
    pub enabled: bool,
    
    /// 启动命令(对于 custom 类型的服务器)
    pub command: Option<String>,
    
    /// 命令参数
    pub args: Option<Vec<String>>,
    
    /// 环境变量
    pub env: Option<HashMap<String, String>>,
    
    /// 连接超时
    pub timeout: Option<Duration>,
}

/// MCP 服务器来源类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum McpServerSource {
    /// 自定义命令行工具(支持 npm、uvx、bun、cargo、python 等命令)
    /// 
    /// 示例:
    /// - `npx @modelcontextprotocol/server-fetch`
    /// - `uvx mcp-server-fetch` 
    /// - `bun @upstash/context7-mcp`
    /// - `cargo install --path ./mcp-server`
    Custom,
    /// 本地可执行文件(直接指定可执行文件路径)
    /// 
    /// 示例:
    /// - `/usr/local/bin/mcp-server`
    /// - `/opt/mcp/custom-tools`
    Local,
}

4.3.2 标准化环境变量映射

ModelProviderConfig 字段映射:

基于当前项目中的 ModelProviderConfig 结构体,我们定义以下标准化环境变量映射:

// ModelProviderConfig 结构体字段:
pub struct ModelProviderConfig {
    pub id: String,                    // → {MODEL_PROVIDER_ID}
    pub name: String,                  // → {MODEL_PROVIDER_NAME}  
    pub base_url: String,              // → {MODEL_PROVIDER_BASE_URL}
    pub api_key: String,               // → {MODEL_PROVIDER_API_KEY}
    pub requires_openai_auth: bool,    // → {MODEL_PROVIDER_REQUIRES_OPENAI_AUTH}
    pub default_model: String,         // → {MODEL_PROVIDER_DEFAULT_MODEL}
    pub api_protocol: Option<String>,  // → {MODEL_PROVIDER_API_PROTOCOL}
}

标准化环境变量定义:

变量名 对应字段 描述 示例值
{MODEL_PROVIDER_ID} id 模型提供商唯一标识 "anthropic-claude"
{MODEL_PROVIDER_NAME} name 模型提供商显示名称 "Claude"
{MODEL_PROVIDER_BASE_URL} base_url API 基础URL "https://api.anthropic.com"
{MODEL_PROVIDER_API_KEY} api_key API 密钥 "sk-ant-xxx"
{MODEL_PROVIDER_DEFAULT_MODEL} default_model 默认模型 "glm-4.6"
{MODEL_PROVIDER_API_PROTOCOL} api_protocol API 协议 "openai"

配置文件格式:

{
  "agent_servers": {
    "claude-code-acp": {
      "command": "claude-code-acp",
      "args": [],
      "env": {
        "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}",
        "ANTHROPIC_BASE_URL": "{MODEL_PROVIDER_BASE_URL}",
        "ANTHROPIC_MODEL": "{MODEL_PROVIDER_DEFAULT_MODEL}",
        "RUST_LOG": "info"
      },
      "system_prompt": {
        "template": "你是一个专业的全栈开发助手,擅长现代 Web 开发和系统架构。专注于 JavaScript/TypeScript、React、Node.js 等技术栈,代码要现代、可维护、注重性能优化和用户体验。遵循最佳实践,重视代码质量和团队协作。"
      },
      "user_prompt": {
        "template": "你是RCoder一个专业的AI编程助手。\n\n## 核心身份与职责\n- 专业的编程助手,帮助用户解决编程问题\n- 提供简洁、实用、可执行的代码解决方案\n- 遵循最佳实践,编写高质量代码\n- 始终将用户需求放在首位\n\n## 代码格式规范\n- 优先使用现代语言特性和标准库\n- 变量和函数命名使用清晰、描述性的英文名称\n- 保持代码简洁,避免过度复杂的抽象\n- 使用适当的注释解释关键逻辑\n\n## 开发约束\n- 避免添加未请求的功能,保持解决方案专注\n- 优先选择最简单有效的实现方式\n- 不要为未来可能的需求添加复杂性\n- 确保代码安全、可维护\n\n## MCP工具使用指导\n- 合理使用可用的工具来辅助开发任务\n- 当需要文件操作、搜索、测试时使用相应的工具\n- 根据上下文选择最合适的工具\n\n## 思考要求\n- 在回答前进行充分的思考和分析\n- 确保解决方案的完整性和正确性\n- 提供清晰、有条理的回答\n\n用户请求\n{user_prompt}"
      },
      "installation": {
        "package_manager": "npm",
        "package_name": "@zed-industries/claude-code-acp",
        "version": "latest",
        "validate_command": ["claude-code-acp", "--version"]
      }
    },
    "Kimi CLI": {
      "command": "kimi",
      "args": ["--acp"],
      "env": {
        "KIMI_API_KEY": "{MODEL_PROVIDER_API_KEY}",
        "KIMI_MODEL": "{MODEL_PROVIDER_DEFAULT_MODEL}",
        "KIMI_BASE_URL": "{MODEL_PROVIDER_BASE_URL}",
        "KIMI_API_PROTOCOL": "{MODEL_PROVIDER_API_PROTOCOL}"
      },
      "system_prompt": {
        "template": "你是 Kimi AI 助手,专注于提供准确、有用的信息检索和问答服务。基于先进的语言模型,能够处理复杂查询,提供详细且相关的回答。保持客观中立,提供经过验证的信息。"
      },
      "user_prompt": {
        "template": "请帮我查询并回答以下问题:{user_prompt}"
      },
      "installation": {
        "package_manager": "npm",
        "package_name": "@kimi-ai/cli",
        "version": "^1.0.0"
      }
    },
    "custom-agent": {
      "command": "custom-agent",
      "args": ["--mode", "acp", "--project", "{project_id}"],
      "env": {
        "CUSTOM_API_KEY": "{CUSTOM_API_KEY}",
        "RUST_LOG": "debug"
      },
      "system_prompt": {
        "template": "你是一个自定义 AI 助手,根据项目需求提供专业的开发支持。请仔细分析用户的具体需求,提供针对性的帮助和建议。"
      },
      "user_prompt": {
        "enabled": false,
        "template": "{user_prompt}"
      },
      "installation": {
        "package_manager": "git",
        "source": "https://github.com/user/custom-agent.git",
        "version": "main"
      }
    }
  },
  "context_servers": {
    "fetch": {
      "source": "custom",
      "enabled": true,
      "command": "uvx",
      "args": ["mcp-server-fetch"],
      "env": {}
    },
    "context7": {
      "source": "custom",
      "enabled": true,
      "command": "npx",
      "args": ["-y", "@upstash/context7-mcp"],
      "env": {
        "CONTEXT7_API_KEY": "{CONTEXT7_API_KEY}"
      }
    },
    "custom-tools": {
      "source": "local",
      "enabled": true,
      "command": "/opt/mcp/custom-tools",
      "args": ["--config", "/etc/mcp/config.yml"],
      "env": {
        "CUSTOM_TOOLS_CONFIG": "/etc/mcp/config.yml"
      }
    },
    "web-search": {
      "source": "custom",
      "enabled": true,
      "command": "mcp-server-search",
      "args": ["--engine", "google"],
      "env": {
        "SEARCH_API_KEY": "{SEARCH_API_KEY}"
      }
    },
    "database": {
      "source": "custom",
      "enabled": true,
      "command": "mcp-server-database",
      "args": ["--connection", "{DATABASE_URL}"],
      "env": {
        "DATABASE_URL": "{DATABASE_URL}"
      }
    }
  }
}

4.4.3 MCP 服务器配置验证库

设计目标: 创建基于 rmcp 库的独立验证模块(crates/mcp_validator),用于验证 enabled: true 的 MCP 服务器配置的有效性。

核心功能:

  1. 筛选启用服务器:只验证配置中 enabled: true 的 MCP 服务器
  2. 进程启动验证:启动 MCP 服务器进程并建立连接
  3. 工具列表检查:通过 tool/list 接口验证服务器可用性
  4. 批量验证:支持同时验证多个启用的服务器
  5. 统计报告:提供详细的验证结果和统计信息

验证策略:

  • 启用过滤:自动跳过所有 enabled: false 的服务器配置
  • 连接测试:使用 rmcp 库建立与 MCP 服务器的连接
  • 工具验证:调用 tool/list 确认服务器能正常返回工具列表
  • 错误处理:提供详细的错误信息和验证状态

核心结构设计:

// crates/mcp_validator/src/lib.rs

/// 验证结果
pub struct McpValidationResult {
    pub server_name: String,
    pub status: ValidationStatus,      // Success/Failed/Timeout 等
    pub tools: Vec<McpToolInfo>,       // 可用工具列表
    pub duration_ms: u64,              // 验证耗时
    pub error_message: Option<String>, // 错误信息
}

/// 批量验证结果
pub struct BatchValidationResult {
    pub total_servers: usize,     // 总服务器数(包括禁用的)
    pub enabled_servers: usize,   // 启用的服务器数
    pub skipped_servers: usize,   // 跳过的禁用服务器数
    pub success_count: usize,     // 成功验证数
    pub failed_count: usize,      // 失败验证数
    pub results: Vec<McpValidationResult>, // 详细结果
}

/// MCP 服务器验证器
pub struct McpServerValidator {
    default_timeout: Duration,
    working_dir: Option<PathBuf>,
}

impl McpServerValidator {
    /// 验证单个 MCP 服务器配置
    pub async fn validate_server(&self, config: &McpValidationConfig) -> Result<McpValidationResult, McpValidationError>;
    
    /// 批量验证 MCP 服务器
    pub async fn validate_batch(&self, configs: &[McpValidationConfig]) -> Result<BatchValidationResult, McpValidationError>;
    
    /// 从 JSON 配置验证(自动处理 enabled 过滤)
    pub async fn validate_from_json(&self, server_name: &str, json_config: &ContextServerConfig, model_provider: &ModelProviderConfig) -> Result<McpValidationResult, McpValidationError>;
}

/// 便捷 API 函数
pub async fn validate_all_mcp_servers(
    context_servers: &HashMap<String, ContextServerConfig>,
    model_provider: &ModelProviderConfig,
) -> Result<BatchValidationResult, McpValidationError>;

集成到配置管理:

impl AgentConfigManager {
    /// 验证所有启用的 MCP 服务器配置
    pub async fn validate_enabled_mcp_servers(&self, model_provider: &ModelProviderConfig) -> Result<BatchValidationResult, ConfigError> {
        validate_all_mcp_servers(&self.config.context_servers, model_provider)
            .await.map_err(|e| ConfigError::ValidationError(e.to_string()))
    }
}

验证流程:

  1. 配置解析:从 JSON 配置中提取 MCP 服务器信息
  2. 启用过滤:只处理 enabled: true 的服务器
  3. 环境变量替换:使用 {VARIABLE_NAME} 格式进行变量映射
  4. 进程启动:启动 MCP 服务器子进程
  5. 连接建立:通过 rmcp 建立 MCP 连接
  6. 工具验证:调用 tool/list 接口验证功能
  7. 结果收集:统计验证结果和性能数据
  8. 进程清理:确保子进程被正确清理

输出示例:

Validation Summary:
  Total servers: 5
  Enabled servers: 3
  Skipped (disabled): 2
  Successful: 2
  Failed: 1
  Total duration: 1250ms

✓ context7: 8 tools (320ms)
✓ fetch: 3 tools (180ms)
✗ web-search: Connection timeout (750ms)

4.4.4 Agent 配置和管理模块

设计目标: 创建独立的 Agent 配置和管理模块(crates/agent_manager),提供统一的 Agent 配置、生命周期管理和抽象接口,作为 lib 库供其他模块使用。

核心功能:

  1. 配置管理:统一管理各种 Agent 的配置和安装信息
  2. 抽象接口:提供统一的 Agent 抽象,支持不同类型的 Agent
  3. 生命周期管理Agent 的启动、停止、状态监控
  4. 安装管理支持从多种源npm、git、本地自动安装 Agent
  5. 验证功能:验证 Agent 配置和可用性
  6. 环境变量映射:统一的变量替换和配置解析

模块职责:

  • 配置标准化:定义统一的 Agent 配置格式
  • 插件化架构:支持动态添加新的 Agent 类型
  • 依赖管理:处理 Agent 的依赖关系和版本管理
  • 资源隔离:确保不同 Agent 之间的资源隔离
  • 错误处理:统一的错误处理和日志记录

容器环境设计原则:

  • 无状态管理Agent 在容器中运行,一段时间无使用且无任务执行时自动销毁
  • 安装验证:确认 Agent 可以成功安装即可,不需要卸载和列表管理
  • 轻量化:避免复杂的状态管理,简化安装流程
  • 自动清理:依赖容器生命周期自动管理资源

核心功能优先原则:

  • MVP 设计:专注于核心功能实现,避免过度工程化
  • 简单直接:优先实现最基本但完整的功能
  • 后续扩展:性能监控、健康检查等高级功能可在后续版本中添加
  • 实用性导向:每个设计决策都以解决实际问题为目标

核心结构设计:

// crates/agent_manager/src/lib.rs

/// Agent 管理器
pub struct AgentManager {
    config: AgentServersConfig,                 // Agent 服务器配置
    env_resolver: EnvironmentVariableResolver,  // 环境变量解析器
    lifecycle_manager: AgentLifecycleManager,   // 生命周期管理
    installation_manager: AgentInstallationManager, // 安装管理器
}

/// Agent 配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentConfig {
    pub agent_id: String,              // Agent 唯一标识
    pub agent_type: AgentType,         // Agent 类型
    pub command: String,               // 启动命令
    pub args: Vec<String>,             // 命令参数
    pub env: HashMap<String, String>,  // 环境变量
    pub installation: InstallationConfig, // 安装配置
    pub enabled: bool,                 // 是否启用
    pub metadata: HashMap<String, String>, // 元数据
}

/// 安装配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InstallationConfig {
    pub package_manager: PackageManager, // 包管理器类型
    pub package_name: Option<String>,    // 包名
    pub version: Option<String>,         // 版本约束
    pub source: Option<String>,          // 安装源
    pub validate_command: Option<Vec<String>>, // 验证命令
    pub auto_update: bool,               // 是否自动更新
}

/// 包管理器类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PackageManager {
    Npm,          // npm 包管理器
    Local,        // 本地二进制
    Custom(String), // 自定义管理器
}

/// Agent 实例
pub struct AgentInstance {
    pub config: AgentConfig,           // 配置信息
    pub process: Option<AgentProcess>, // 进程句柄
    pub status: AgentStatus,          // 运行状态
    pub started_at: Option<DateTime<Utc>>, // 启动时间
}

/// Agent 状态
#[derive(Debug, Clone, PartialEq)]
pub enum AgentStatus {
    Stopped,     // 已停止
    Starting,    // 启动中
    Running,     // 运行中
    Stopping,    // 停止中
    Error(String), // 错误状态
    Unknown,     // 未知状态
}

/// Agent 管理器实现
impl AgentManager {
    /// 创建新的 Agent 管理器
    /// 
    /// # 参数
    /// - `config`: Agent 服务器配置结构体
    /// - `env_resolver`: 环境变量解析器
    pub fn new(config: AgentServersConfig, env_resolver: EnvironmentVariableResolver) -> Result<Self, AgentManagerError>;
    
    /// 启动 Agent
    pub async fn start_agent(&mut self, agent_id: &str, project_id: &str, model_provider: &ModelProviderConfig) -> Result<AgentInstance, AgentManagerError>;
    
    /// 停止 Agent
    pub async fn stop_agent(&mut self, agent_id: &str) -> Result<(), AgentManagerError>;
    
    /// 获取 Agent 状态
    pub fn get_agent_status(&self, agent_id: &str) -> Option<AgentStatus>;
    
    /// 列出所有 Agent
    pub fn list_agents(&self) -> Vec<&AgentConfig>;
    
    /// 列出启用的 Agent
    pub fn list_enabled_agents(&self) -> Vec<&AgentConfig>;
    
    /// 🔥 新增:检查 Agent 是否空闲
    /// 
    /// # 参数
    /// - `project_id`: 项目ID因为一个项目对应一个Agent
    /// 
    /// # 返回值
    /// - `Some(true)`: Agent 空闲,可以接收新任务
    /// - `Some(false)`: Agent 正在执行任务
    /// - `None`: Agent 不存在或已停止
    pub fn is_agent_idle(&self, project_id: &str) -> Option<bool> {
        self.lifecycle_manager.is_agent_idle(project_id)
    }
    
    /// 🔥 新增:获取 Agent 详细的空闲状态信息
    pub fn get_agent_idle_status(&self, project_id: &str) -> Option<AgentIdleStatus> {
        self.lifecycle_manager.get_agent_idle_status(project_id)
    }
    
    /// 🔥 新增:列出所有空闲的 Agent
    pub fn list_idle_agents(&self) -> Vec<String> {
        let mut idle_agents = Vec::new();
        
        // 遍历所有启用的 Agent检查是否空闲
        for agent_config in self.config.get_enabled_agents() {
            if let Some(is_idle) = self.is_agent_idle(&agent_config.agent_id) {
                if is_idle {
                    idle_agents.push(agent_config.agent_id.clone());
                }
            }
        }
        
        idle_agents
    }
    
    /// 🔥 新增:获取 Agent 空闲统计信息
    pub fn get_idle_statistics(&self) -> AgentIdleStatistics {
        let enabled_agents = self.config.get_enabled_agents();
        let mut idle_count = 0;
        let mut active_count = 0;
        let mut unknown_count = 0;
        
        for agent_config in enabled_agents {
            match self.is_agent_idle(&agent_config.agent_id) {
                Some(true) => idle_count += 1,
                Some(false) => active_count += 1,
                None => unknown_count += 1,
            }
        }
        
        AgentIdleStatistics {
            total_enabled: enabled_agents.len(),
            idle_count,
            active_count,
            unknown_count,
        }
    }
    
    /// 验证 Agent 配置
    pub async fn validate_agent_config(&self, agent_config: &AgentConfig) -> Result<ValidationResult, AgentManagerError>;
    
    /// 安装 Agent
    pub async fn install_agent(&self, agent_config: &AgentConfig) -> Result<(), AgentManagerError>;
    
    /// 更新 Agent
    pub async fn update_agent(&self, agent_id: &str) -> Result<(), AgentManagerError>;
}

/// 🔥 新增Agent 空闲统计信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentIdleStatistics {
    /// 启用的 Agent 总数
    pub total_enabled: usize,
    /// 空闲的 Agent 数量
    pub idle_count: usize,
    /// 正在执行任务的 Agent 数量
    pub active_count: usize,
    /// 状态未知的 Agent 数量
    pub unknown_count: usize,
}

配置解析和验证工具:

impl AgentServersConfig {
    /// 从 JSON 文件加载配置
    pub async fn from_file(path: &Path) -> Result<Self, ConfigError>;
    
    /// 从 JSON 字符串解析配置
    pub fn from_json(json: &str) -> Result<Self, ConfigError>;
    
    /// 验证配置完整性
    pub fn validate(&self) -> Result<(), ConfigError>;
    
    /// 获取启用的 Agent 配置
    pub fn get_enabled_agents(&self) -> Vec<&AgentConfig>;
    
    /// 根据 ID 获取 Agent 配置
    pub fn get_agent(&self, agent_id: &str) -> Option<&AgentConfig>;
}

/// 环境变量解析器
pub struct EnvironmentVariableResolver {
    mappings: HashMap<String, String>,
    custom_resolvers: HashMap<String, fn(&ResolutionContext) -> String>,
}

impl EnvironmentVariableResolver {
    /// 创建包含标准映射的解析器
    pub fn with_standard_mappings() -> Self {
        let mut mappings = HashMap::new();
        
        // ModelProvider 相关 - 完整映射所有字段
        mappings.insert("MODEL_PROVIDER_ID".to_string(), "MODEL_PROVIDER_ID");
        mappings.insert("MODEL_PROVIDER_NAME".to_string(), "MODEL_PROVIDER_NAME");
        mappings.insert("MODEL_PROVIDER_API_KEY".to_string(), "MODEL_PROVIDER_API_KEY");
        mappings.insert("MODEL_PROVIDER_DEFAULT_MODEL".to_string(), "MODEL_PROVIDER_DEFAULT_MODEL");
        mappings.insert("MODEL_PROVIDER_BASE_URL".to_string(), "MODEL_PROVIDER_BASE_URL");
        mappings.insert("MODEL_PROVIDER_REQUIRES_OPENAI_AUTH".to_string(), "MODEL_PROVIDER_REQUIRES_OPENAI_AUTH");
        mappings.insert("MODEL_PROVIDER_API_PROTOCOL".to_string(), "MODEL_PROVIDER_API_PROTOCOL");
        
        // 项目相关
        mappings.insert("PROJECT_ID".to_string(), "PROJECT_ID");
        mappings.insert("PROJECT_NAME".to_string(), "PROJECT_NAME");
        mappings.insert("PROJECT_PATH".to_string(), "PROJECT_PATH");
        
        // MCP 服务器相关
        mappings.insert("CONTEXT7_API_KEY".to_string(), "CONTEXT7_API_KEY");
        mappings.insert("FETCH_TIMEOUT".to_string(), "FETCH_TIMEOUT");
        
        Self {
            mappings,
            custom_resolvers: HashMap::new(),
        }
    }
    
    /// 解析 Agent 配置中的环境变量
    pub fn resolve_agent_config(&self, agent_config: &mut AgentConfig, model_provider: &ModelProviderConfig, project_context: &ProjectContext) -> Result<(), ConfigError> {
        let context = ResolutionContext {
            model_provider: model_provider.clone(),
            project_context: project_context.clone(),
            custom_variables: HashMap::new(),
            mcp_variables: HashMap::new(),
        };
        
        // 解析环境变量值
        for (key, value) in agent_config.env.iter_mut() {
            *value = self.resolve_value(value, &context);
        }
        
        // 解析命令参数中的变量
        for arg in agent_config.args.iter_mut() {
            *arg = self.resolve_value(arg, &context);
        }
        
        Ok(())
    }
    
    /// 解析单个环境变量值
    pub fn resolve_value(&self, template: &str, context: &ResolutionContext) -> String {
        let mut result = template.to_string();
        
        // 替换 ModelProvider 相关变量
        result = result.replace("{MODEL_PROVIDER_ID}", &context.model_provider.id);
        result = result.replace("{MODEL_PROVIDER_NAME}", &context.model_provider.name);
        result = result.replace("{MODEL_PROVIDER_API_KEY}", &context.model_provider.api_key);
        result = result.replace("{MODEL_PROVIDER_DEFAULT_MODEL}", &context.model_provider.default_model);
        result = result.replace("{MODEL_PROVIDER_BASE_URL}", &context.model_provider.base_url);
        result = result.replace("{MODEL_PROVIDER_REQUIRES_OPENAI_AUTH}", 
                               &context.model_provider.requires_openai_auth.to_string());
        result = result.replace("{MODEL_PROVIDER_API_PROTOCOL}", 
                               context.model_provider.api_protocol.as_ref().unwrap_or(&String::new()));
        
        // 替换项目相关变量
        result = result.replace("{PROJECT_ID}", &context.project_context.project_id);
        result = result.replace("{PROJECT_NAME}", &context.project_context.project_name);
        result = result.replace("{PROJECT_PATH}", &context.project_context.project_path.display().to_string());
        
        // 替换 MCP 变量
        for (key, value) in &context.mcp_variables {
            result = result.replace(&format!("{{{}}}", key), value);
        }
        
        // 替换自定义变量
        for (key, value) in &context.custom_variables {
            result = result.replace(&format!("{{{}}}", key), value);
        }
        
        result
    }
    
    /// 🔥 新增:解析系统提示词模板
    /// 根据配置的系统提示词模板解析最终内容
    pub fn resolve_system_prompt(&self, system_prompt_config: &Option<SystemPromptConfig>, context: &ResolutionContext) -> Option<String> {
        match system_prompt_config {
            Some(config) if config.enabled => {
                let resolved = self.resolve_value(&config.template, context);
                Some(resolved)
            }
            Some(_) => None, // 明确禁用时返回 None
            None => None,     // 未配置时返回 None
        }
    }
    
    /// 🔥 新增:解析用户提示词包装
    /// 根据配置的用户提示词模板包装用户的实际输入
    pub fn resolve_user_prompt(&self, user_input: &str, user_prompt_config: &Option<UserPromptConfig>) -> String {
        match user_prompt_config {
            Some(config) if config.enabled => {
                config.template.replace("{user_prompt}", user_input)
            }
            _ => user_input.to_string(), // 如果未启用或未配置,直接返回原输入
        }
    }
    
    /// 添加自定义变量映射
    pub fn add_mapping(&mut self, key: String, value: String) {
        self.mappings.insert(key, value);
    }
}

/// 解析上下文
pub struct ResolutionContext {
    pub model_provider: ModelProviderConfig,
    pub project_context: ProjectContext,
    pub custom_variables: HashMap<String, String>,
    pub mcp_variables: HashMap<String, String>,
}

安装管理设计(容器环境优化):

/// Agent 安装管理器
/// 容器环境下的简化安装管理,只负责安装验证和更新
pub struct AgentInstallationManager {
    installers: HashMap<PackageManager, Box<dyn AgentInstaller>>,
    install_dir: PathBuf,
}

impl AgentInstallationManager {
    /// 注册安装器
    pub fn register_installer(&mut self, package_manager: PackageManager, installer: Box<dyn AgentInstaller>);
    
    /// 安装 Agent
    pub async fn install_agent(&self, config: &InstallationConfig) -> Result<InstallResult, InstallationError>;
    
    /// 验证安装
    pub async fn validate_installation(&self, config: &InstallationConfig) -> Result<bool, InstallationError>;
    
    /// 更新 Agent
    pub async fn update_agent(&self, config: &InstallationConfig) -> Result<InstallResult, InstallationError>;
}

/// Agent 安装器接口
#[async_trait]
pub trait AgentInstaller: Send + Sync {
    /// 安装 Agent
    async fn install(&self, config: &InstallationConfig, install_dir: &Path) -> Result<InstallResult, InstallationError>;
    
    /// 验证安装
    async fn validate(&self, config: &InstallationConfig, install_dir: &Path) -> Result<bool, InstallationError>;
    
    /// 更新 Agent
    async fn update(&self, config: &InstallationConfig, install_dir: &Path) -> Result<InstallResult, InstallationError>;
    
    /// 获取安装器类型
    fn package_manager(&self) -> PackageManager;
}

生命周期管理设计(核心功能):

/// Agent 生命周期管理器
pub struct AgentLifecycleManager {
    processes: DashMap<String, AgentProcess>,
    // 引用现有的 PROJECT_AND_AGENT_INFO_MAP 进行状态管理
    agent_status_map: DashMap<String, AgentStatusInfo>,
}

/// Agent 状态信息(基于现有实现的抽象)
#[derive(Debug, Clone)]
pub struct AgentStatusInfo {
    pub status: AgentStatus,           // Active/Idle/Terminating
    pub session_id: Option<String>,   // 当前会话ID
    pub request_id: Option<String>,   // 当前请求ID
    pub last_activity: DateTime<Utc>, // 最后活动时间
    pub created_at: DateTime<Utc>,    // 创建时间
}

impl AgentLifecycleManager {
    /// 启动 Agent 进程
    pub async fn start_agent(&self, config: &AgentConfig, context: &AgentContext) -> Result<AgentProcess, LifecycleError>;
    
    /// 停止 Agent 进程
    pub async fn stop_agent(&self, agent_id: &str) -> Result<(), LifecycleError>;
    
    /// 重启 Agent
    pub async fn restart_agent(&self, agent_id: &str) -> Result<AgentProcess, LifecycleError>;
    
    /// 获取进程状态
    pub fn get_process_status(&self, agent_id: &str) -> Option<ProcessStatus>;
    
    /// 🔥 新增:获取 Agent 是否空闲状态
    pub fn is_agent_idle(&self, agent_id: &str) -> Option<bool> {
        self.agent_status_map.get(agent_id)
            .map(|info| matches!(info.status, AgentStatus::Idle))
    }
    
    /// 🔥 新增:获取 Agent 详细的空闲状态信息
    pub fn get_agent_idle_status(&self, agent_id: &str) -> Option<AgentIdleStatus> {
        self.agent_status_map.get(agent_id).map(|info| {
            AgentIdleStatus {
                is_idle: matches!(info.status, AgentStatus::Idle),
                current_status: info.status.clone(),
                last_activity: info.last_activity,
                session_id: info.session_id.clone(),
                current_request_id: info.request_id.clone(),
                idle_duration: Utc::now().signed_duration_since(info.last_activity).to_std().unwrap_or_default(),
            }
        })
    }
    
    /// 🔥 新增:更新 Agent 状态为 Active开始执行任务
    pub fn set_agent_active(&self, agent_id: &str, request_id: Option<String>) {
        if let Some(mut info) = self.agent_status_map.get_mut(agent_id) {
            info.status = AgentStatus::Active;
            info.last_activity = Utc::now();
            info.request_id = request_id;
        }
    }
    
    /// 🔥 新增:更新 Agent 状态为 Idle任务完成
    pub fn set_agent_idle(&self, agent_id: &str) {
        if let Some(mut info) = self.agent_status_map.get_mut(agent_id) {
            info.status = AgentStatus::Idle;
            info.last_activity = Utc::now();
            info.request_id = None;
        }
    }
}

/// 🔥 新增Agent 空闲状态响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentIdleStatus {
    /// 是否空闲
    pub is_idle: bool,
    /// 当前状态
    pub current_status: AgentStatus,
    /// 最后活动时间
    pub last_activity: DateTime<Utc>,
    /// 当前会话ID
    pub session_id: Option<String>,
    /// 当前请求ID如果正在执行任务
    pub current_request_id: Option<String>,
    /// 空闲持续时间
    pub idle_duration: Duration,
}

/// Agent 进程封装
pub struct AgentProcess {
    pub id: String,
    pub child: tokio::process::Child,
    pub config: AgentConfig,
    pub start_time: DateTime<Utc>,
}

状态管理机制分析:

现有实现发现:

  1. 状态存储:使用 PROJECT_AND_AGENT_INFO_MAP 全局存储 Agent 状态
  2. 状态类型AgentStatus 枚举包含 ActiveIdleTerminating 三种状态
  3. 状态更新:在 channel_utils.rs 中通过 ACP 消息触发状态切换
  4. 状态切换时机
    • Active: 收到 Prompt 请求时
    • Idle: Prompt 处理完成或被取消时
    • Terminating: Agent 停止过程中

设计优化:

  • 复用现有机制Agent 管理器封装现有状态管理逻辑
  • 提供统一接口:标准化的状态查询方法
  • 性能优化:避免重复的状态存储和管理
  • 扩展性:为未来状态扩展预留接口

🔥 新增ACP 连接池管理的完整使用示例:

// 1. 加载配置(由调用方负责)
let agent_config = AgentServersConfig::from_file("/etc/rcoder/agents.json").await?;
let env_resolver = EnvironmentVariableResolver::with_standard_mappings();

// 2. 🔥 新增:初始化 ACP 连接池管理器
let acp_config = AcpConnectionConfig::default();
let acp_connection_manager = Arc::new(AcpConnectionManager::new(acp_config));

// 3. 准备 ModelProvider 配置
let model_provider = ModelProviderConfig {
    id: "anthropic-claude".to_string(),
    name: "Claude".to_string(),
    base_url: "https://api.anthropic.com".to_string(),
    api_key: "sk-ant-xxx".to_string(),
    requires_openai_auth: false,
    default_model: "claude-3-5-sonnet-20241022".to_string(),
    api_protocol: Some("anthropic".to_string()),
};

// 4. 准备项目上下文
let project_context = ProjectContext {
    project_id: "project-123".to_string(),
    project_name: "my-react-app".to_string(),
    project_path: PathBuf::from("/workspace/project-123"),
};

// 5. 🔥 新增:创建 Agent 工厂,集成 ACP 连接池
let agent_factory = Arc::new(AgentFactory::new(
    registry,
    launcher,
    config_manager,
    mcp_manager,
    acp_connection_manager.clone(),
));

// 6. 🔥 新增:通过连接池获取 Agent 连接
let agent_connection = acp_connection_manager.get_or_create_connection(
    "claude-code-acp",
    &agent_config.get_agent("claude-code-acp").unwrap(),
    &model_provider,
    &project_context,
).await?;

// 7. 🔥 新增:使用连接池发送提示词
let prompt_request = PromptRequest {
    prompt: "帮我实现一个 React 登录组件".to_string(),
    session_id: Some("session-123".to_string()),
    model_provider: Some(model_provider.clone()),
};

let response = acp_connection_manager.send_prompt("claude-code-acp", prompt_request).await?;

// 8. 🔥 新增:处理提示词包装
let user_input = "帮我实现一个登录组件";
let agent_spec = agent_config.get_agent("claude-code-acp").unwrap();
let wrapped_prompt = env_resolver.resolve_user_prompt(
    user_input,
    &agent_spec.user_prompt,
);

// 9. 🔥 新增:处理系统提示词
let system_prompt = env_resolver.resolve_system_prompt(
    &agent_spec.system_prompt,
    &ResolutionContext {
        model_provider: model_provider.clone(),
        project_context: project_context.clone(),
        custom_variables: HashMap::new(),
        mcp_variables: HashMap::new(),
    },
);

// 10. 🔥 新增:获取连接池统计信息
let stats = acp_connection_manager.get_connection_stats();
println!("当前连接数: {}/{}", stats.total_connections, stats.max_connections);
println!("最大空闲时间: {:?}", stats.max_idle_time);

// 11. 🔥 新增:取消长时间运行的任务
let cancel_notification = CancelNotification {
    session_id: "session-123".to_string(),
    reason: "用户取消请求".to_string(),
};

acp_connection_manager.cancel_request("claude-code-acp", cancel_notification).await?;

传统 Agent 管理器使用示例:

// 对于不需要 ACP 连接池的场景,仍可使用传统方式

// 1. 初始化 Agent 管理器
let mut agent_manager = AgentManager::new(agent_config, env_resolver)?;

// 2. 启动 Agent根据配置中的 agent_type 自动选择启动方式)
let agent_instance = agent_manager.start_agent(
    "claude-code-acp", 
    "project-123", 
    &model_provider
).await?;

// 6. Agent 启动后,环境变量会被自动解析:
//    - ANTHROPIC_API_KEY = "sk-ant-xxx" (来自 MODEL_PROVIDER_API_KEY)
//    - ANTHROPIC_BASE_URL = "https://api.anthropic.com" (来自 MODEL_PROVIDER_BASE_URL)
//    - ANTHROPIC_MODEL = "claude-3-5-sonnet-20241022" (来自 MODEL_PROVIDER_DEFAULT_MODEL)

环境变量解析示例:

假设 Agent 配置中有以下环境变量:

{
  "env": {
    "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}",
    "ANTHROPIC_BASE_URL": "{MODEL_PROVIDER_BASE_URL}",
    "ANTHROPIC_MODEL": "{MODEL_PROVIDER_DEFAULT_MODEL}",
    "PROJECT_DIR": "{PROJECT_PATH}",
    "AGENT_ID": "{PROJECT_ID}-claude",
    "CONTEXT7_API_KEY": "{CONTEXT7_API_KEY}"
  }
}

经过 EnvironmentVariableResolver::resolve_agent_config() 处理后:

{
  "env": {
    "ANTHROPIC_API_KEY": "sk-ant-xxx",
    "ANTHROPIC_BASE_URL": "https://api.anthropic.com",
    "ANTHROPIC_MODEL": "claude-3-5-sonnet-20241022",
    "PROJECT_DIR": "/workspace/project-123",
    "AGENT_ID": "project-123-claude",
    "CONTEXT7_API_KEY": "ctx7-xxx"  // 来自 MCP 变量配置
  }
}

🔥 新增:用户提示词包装使用示例:

// 1. 用户输入包装示例
let user_input = "帮我写一个 React 组件";
let agent_config = agent_manager.get_agent("claude-code-acp").unwrap();

// 2. 应用用户提示词包装
let wrapped_prompt = env_resolver.resolve_user_prompt(
    user_input, 
    &agent_config.user_prompt
);

// 3. 包装后的结果:
// "你好 帮我写一个 React 组件,请帮我分析这个问题并提供详细的解决方案。"

// 4. 将包装后的提示词发送给 Agent
let response = agent.send_prompt(&wrapped_prompt).await?;

配置示例和使用效果:

{
  "agent_servers": {
    "react-developer": {
      "command": "claude-code-acp",
      "args": [],
      "env": {
        "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}"
      },
      "system_prompt": {
        "template": "你是一个专业的 React 开发助手"
      },
      "user_prompt": {
        "template": "作为 React 专家,请帮我解决以下问题:{user_prompt}。请提供现代、可维护的代码示例。"
      }
    },
    "rust-developer": {
      "command": "claude-code-acp", 
      "args": [],
      "env": {
        "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}"
      },
      "system_prompt": {
        "template": "你是一个 Rust 系统编程专家"
      },
      "user_prompt": {
        "enabled": false,
        "template": "{user_prompt}"
      }
    },
    "general-assistant": {
      "command": "kimi",
      "args": ["--acp"],
      "env": {
        "KIMI_API_KEY": "{MODEL_PROVIDER_API_KEY}"
      },
      "system_prompt": {
        "enabled": false,
        "template": "你是一个通用 AI 助手"
      },
      "user_prompt": null  // 未配置,直接使用原输入
    }
  }
}

实际使用效果演示:

// 示例 1React Developer Agent
let user_input = "如何实现一个自定义 Hook";
let wrapped = env_resolver.resolve_user_prompt(
    user_input, 
    &react_config.user_prompt
);
// 结果:"作为 React 专家,请帮我解决以下问题:如何实现一个自定义 Hook。请提供现代、可维护的代码示例。"

// 示例 2Rust Developer Agent (禁用包装)
let user_input = "解释 Rust 的所有权机制";
let wrapped = env_resolver.resolve_user_prompt(
    user_input, 
    &rust_config.user_prompt  
);
// 结果:"解释 Rust 的所有权机制" (直接返回原输入)

// 示例 3General Assistant Agent (未配置)
let user_input = "今天天气怎么样?";
let wrapped = env_resolver.resolve_user_prompt(
    user_input, 
    &general_config.user_prompt
);
// 结果:"今天天气怎么样?" (直接返回原输入)

user_prompt 配置特点:

  1. 灵活的模板系统:支持在模板中使用 {user_prompt} 占位符
  2. 条件启用:通过 enabled 字段控制是否启用包装功能
  3. 简化配置:未配置或禁用时直接使用用户原输入
  4. Agent 个性化:每个 Agent 可以有自己独特的用户提示词包装风格
  5. 动态替换:运行时根据用户输入动态生成最终提示词

🔥 新增:系统提示词配置特点:

  1. 统一的配置格式system_promptuser_prompt 都使用相同的 { "template": "...", "enabled": true/false } 格式
  2. 默认启用enabled 字段默认为 true,可以省略不写
  3. 模板变量支持:系统提示词也支持所有环境变量替换(如 {MODEL_PROVIDER_DEFAULT_MODEL}
  4. 灵活控制:可以通过 enabled: false 禁用特定的系统提示词

system_prompt vs user_prompt 对比:

特性 system_prompt user_prompt
用途 设置 Agent 的角色和行为 包装用户的每次输入
变量支持 支持所有环境变量 只支持 {user_prompt} 占位符
默认状态 enabled: true enabled: true
配置示例 { "template": "你是React专家" } { "template": "请帮我:{user_prompt}" }

新的完整配置示例:

{
  "agent_servers": {
    "full-stack-developer": {
      "command": "claude-code-acp",
      "args": [],
      "env": {
        "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}",
        "ANTHROPIC_MODEL": "{MODEL_PROVIDER_DEFAULT_MODEL}"
      },
      "system_prompt": {
        "template": "你是 {MODEL_PROVIDER_NAME} 驱动的全栈开发专家,专注于 {PROJECT_NAME} 项目。使用现代开发实践,代码要简洁、可维护、性能优化。"
      },
      "user_prompt": {
        "template": "你是RCoder一个专业的AI编程助手。\n\n## 核心身份与职责\n- 专业的编程助手,帮助用户解决编程问题\n- 提供简洁、实用、可执行的代码解决方案\n- 遵循最佳实践,编写高质量代码\n- 始终将用户需求放在首位\n\n## 代码格式规范\n- 优先使用现代语言特性和标准库\n- 变量和函数命名使用清晰、描述性的英文名称\n- 保持代码简洁,避免过度复杂的抽象\n- 使用适当的注释解释关键逻辑\n\n## 开发约束\n- 避免添加未请求的功能,保持解决方案专注\n- 优先选择最简单有效的实现方式\n- 不要为未来可能的需求添加复杂性\n- 确保代码安全、可维护\n\n## MCP工具使用指导\n- 合理使用可用的工具来辅助开发任务\n- 当需要文件操作、搜索、测试时使用相应的工具\n- 根据上下文选择最合适的工具\n\n## 思考要求\n- 在回答前进行充分的思考和分析\n- 确保解决方案的完整性和正确性\n- 提供清晰、有条理的回答\n\n用户请求\n{user_prompt}"
      },
      "installation": {
        "package_manager": "npm",
        "package_name": "@zed-industries/claude-code-acp"
      }
    },
    "code-reviewer": {
      "command": "claude-code-acp",
      "args": [],
      "env": {
        "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}"
      },
      "system_prompt": {
        "enabled": true,
        "template": "你是一个资深代码审查专家,专注于代码质量、安全性和最佳实践。提供具体的改进建议。"
      },
      "user_prompt": {
        "enabled": true,
        "template": "请审查以下代码,重点关注可读性、性能和安全性:\n\n{user_prompt}\n\n请提供具体的改进建议。"
      }
    },
    "minimal-agent": {
      "command": "claude-code-acp",
      "args": [],
      "env": {
        "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}"
      },
      "system_prompt": {
        "enabled": false
      },
      "user_prompt": null  // 不包装用户输入
    }
  }
}

运行时解析示例:

// 1. 解析系统提示词
let system_prompt = env_resolver.resolve_system_prompt(
    &agent_config.system_prompt, 
    &context
);
// 结果:如果 enabled=true 且模板包含变量,会返回解析后的内容
// 结果:如果 enabled=false 或未配置,会返回 None

// 2. 解析用户提示词包装
let user_input = "帮我实现一个登录组件";
let wrapped_prompt = env_resolver.resolve_user_prompt(
    user_input, 
    &agent_config.user_prompt
);
// 结果:"你好,我是 my-project 项目的开发者。帮我实现一个登录组件 请提供详细的解决方案和代码示例。"

适用场景:

  • 专业领域 Agent:为特定技术领域的 Agent 添加领域特定的引导语
  • 教学辅导 Agent:在用户问题前添加启发式引导
  • 代码审查 Agent:标准化代码审查请求的格式
  • 多语言支持:为不同语言的 Agent 添加相应的语言引导
  • 项目定制化:系统提示词中注入项目名称、环境变量等信息
  • 角色切换:通过 enabled 字段动态控制 Agent 的角色

println!("Agent started: {:?}", agent_instance.status);

// 🔥 新增:获取 Agent 当前配置 if let Some(config) = agent.get_config(&agent_instance) { println!("Agent current config:"); println!(" - Agent type: {:?}", config.agent_type); println!(" - Command: {}", config.command); println!(" - Args: {:?}", config.args); }

// 🔥 新增:重启 Agent比如配置更新后 let new_config = AgentConfig { /* 新配置 / }; let new_context = AgentContext { / 新上下文 */ }; let restarted_instance = agent.restart(&agent_instance, new_config, new_context).await?; println!("Agent restarted: {:?}", restarted_instance.status);

// 获取所有启用的 Agent let enabled_agents = agent_manager.list_enabled_agents(); for agent in enabled_agents { println!("Enabled agent: {} ({})", agent.agent_id, agent.command); }

// 🔥 新增:检查 Agent 空闲状态 let project_id = "project-123"; match agent_manager.is_agent_idle(project_id) { Some(true) => println!("Agent for project {} is idle and ready for new tasks", project_id), Some(false) => println!("Agent for project {} is currently busy", project_id), None => println!("Agent for project {} is not running", project_id), }

// 🔥 新增:获取详细的空闲状态信息 if let Some(idle_status) = agent_manager.get_agent_idle_status(project_id) { println!("Agent status details:"); println!(" - Is idle: {}", idle_status.is_idle); println!(" - Current status: {:?}", idle_status.current_status); println!(" - Last activity: {}", idle_status.last_activity); println!(" - Session ID: {:?}", idle_status.session_id); println!(" - Current request ID: {:?}", idle_status.current_request_id); println!(" - Idle duration: {:?}", idle_status.idle_duration); }

// 🔥 新增:列出所有空闲的 Agent let idle_agents = agent_manager.list_idle_agents(); println!("Idle agents: {:?}", idle_agents);

// 🔥 新增:获取空闲统计信息 let stats = agent_manager.get_idle_statistics(); println!("Agent statistics:"); println!(" - Total enabled: {}", stats.total_enabled); println!(" - Idle: {}", stats.idle_count); println!(" - Active: {}", stats.active_count); println!(" - Unknown: {}", stats.unknown_count);


**启动流程说明:**
Agent 管理器根据配置中的 `agent_type` 字段自动选择启动方式:
- **"claude"**: 使用 Claude Code ACP 启动流程
- **"kimi"**: 使用 Kimi CLI 启动流程  
- **"custom"**: 使用自定义 Agent 启动流程
- **其他类型**: 通用启动流程

这种方式避免了动态注册的复杂性,让 Agent 类型通过配置文件驱动。

**配置文件结构JSON 格式):**

```json
{
  "agent_servers": {
    "claude-code-acp": {
    "agent_type": "claude",
      "command": "claude-code-acp",
      "args": [],
      "env": {
        "ANTHROPIC_API_KEY": "{MODEL_PROVIDER_API_KEY}",
        "ANTHROPIC_BASE_URL": "{MODEL_PROVIDER_BASE_URL}",
        "ANTHROPIC_MODEL": "{MODEL_PROVIDER_DEFAULT_MODEL}",
        "RUST_LOG": "info"
      },
      "installation": {
        "package_manager": "npm",
        "package_name": "@zed-industries/claude-code-acp",
        "version": "latest",
        "validate_command": ["claude-code-acp", "--version"],
        "auto_update": true
      },
      "enabled": true,
      "metadata": {
        "description": "Claude Code ACP Agent",
        "version": "1.0.0",
        "maintainer": "Anthropic"
      }
    }

  "kimi-cli": {
      "agent_type": "kimi",
      "command": "kimi",
      "args": ["--acp"],
      "env": {
        "KIMI_API_KEY": "{MODEL_PROVIDER_API_KEY}",
        "KIMI_MODEL": "{MODEL_PROVIDER_DEFAULT_MODEL}",
        "KIMI_BASE_URL": "{MODEL_PROVIDER_BASE_URL}"
      },
      "installation": {
        "package_manager": "npm",
        "package_name": "@kimi-ai/cli",
        "version": "^1.0.0",
        "auto_update": false
      },
      "enabled": true
    }
  },
  "global": {
    "install_dir": "/opt/rcoder/agents",
    "log_dir": "/var/log/rcoder/agents",
    "default_timeout": 30,
    "max_concurrent_agents": 10
  }

4.4.5 ACP 连接池管理

🔥 重要:避免死锁的 ACP 连接池设计

基于当前 RCoder 工程的深入分析,发现以下死锁风险点:

  1. DashMap 嵌套访问:多个 DashMap 同时访问可能造成死锁
  2. RAII 与显式清理冲突:生命周期管理和手动状态更新协调不当
  3. 状态更新时序问题Agent 状态和连接状态同步更新的竞争条件

🔧 死锁预防设计原则:

  1. 单一数据源原则:每个 Agent 只在一个地方管理状态
  2. 无嵌套锁:避免在持有锁时访问其他可能被锁的资源
  3. RAII 优先:以 RAII 为主要资源管理方式,避免显式清理
  4. 原子操作:状态更新使用原子性操作,避免中间状态
  5. 单向依赖:建立清晰的依赖层次,避免循环依赖

重新设计的 ACP 连接池管理器:

/// ACP 连接池管理器
/// 
/// 🔥 无死锁风险设计:每个 Agent 使用独立的连接实例,避免共享状态
pub struct AcpConnectionManager {
    /// 连接池agent_id -> AgentConnection
    /// ✅ 基于当前工程成功的DashMap模式避免传统锁的竞争问题
    connections: Arc<DashMap<String, Weak<AgentConnection>>>,
    
    /// 连接配置
    config: Arc<AcpConnectionConfig>,
    
    /// 后台清理任务句柄
    cleanup_task: Arc<tokio::sync::Mutex<Option<JoinHandle<()>>>>,
}

/// ACP 连接配置
#[derive(Debug, Clone)]
pub struct AcpConnectionConfig {
    /// 最大空闲时间,超过此时间的连接将被清理
    pub max_idle_time: Duration,
    
    /// 清理任务间隔
    pub cleanup_interval: Duration,
    
    /// 连接超时时间
    pub connection_timeout: Duration,
    
    /// 最大连接数
    pub max_connections: usize,
}

impl Default for AcpConnectionConfig {
    fn default() -> Self {
        Self {
            max_idle_time: Duration::from_secs(300),      // 5分钟
            cleanup_interval: Duration::from_secs(60),    // 1分钟清理一次
            connection_timeout: Duration::from_secs(30),   // 30秒连接超时
            max_connections: 100,                           // 最大100个连接
        }
    }
}

/// Agent 连接包装器
/// 
/// 🔥 与 RAII 模式兼容的设计AgentConnection 本身就是 RAII 资源
pub struct AgentConnection {
    /// Agent 唯一标识
    pub agent_id: String,
    
    /// LocalSet 实例(必须在这个 LocalSet 中使用 ACP 连接)
    /// 📌 使用 Box<LocalSet> 避免与全局 LocalSet 冲突
    local_set: Box<LocalSet>,
    
    /// 客户端连接(非 Send只能在 LocalSet 内使用)
    /// 📌 使用 RefCell 而不是 Mutex避免与全局状态锁冲突
    client_conn: RefCell<Option<ClientSideConnection>>,
    
    /// 生命周期管理器(与现有的 AgentLifecycleGuard 集成)
    lifecycle_guard: AgentLifecycleGuard,
    
    /// 最后活动时间(使用原子类型,避免锁)
    last_activity: AtomicInstant,
    
    /// 连接创建时间
    created_at: Instant,
    
    /// 连接状态(使用原子操作,避免锁竞争)
    status: AtomicU8, // 存储 ConnectionStatus 的数字表示
    
    /// 连接管理器的弱引用,用于自动清理
    manager_weak: Weak<AcpConnectionManager>,
}

/// 🔥 原子时间戳包装器,避免使用 Mutex
#[derive(Debug)]
pub struct AtomicInstant {
    inner: AtomicU64,
}

impl AtomicInstant {
    pub fn new() -> Self {
        Self {
            inner: AtomicU64::new(0),
        }
    }
    
    pub fn store(&self, instant: Instant) {
        self.inner.store(instant.elapsed().as_nanos() as u64, Ordering::Relaxed);
    }
    
    pub fn load(&self) -> Instant {
        let nanos = self.inner.load(Ordering::Relaxed);
        if nanos == 0 {
            Instant::now()
        } else {
            Instant::now() - Duration::from_nanos(nanos)
        }
    }
}

/// 🔥 连接状态(使用数字表示,支持原子操作)
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(u8)]
pub enum ConnectionStatus {
    /// 连接中
    Connecting = 1,
    /// 已连接
    Connected = 2,
    /// 空闲
    Idle = 3,
    /// 错误
    Error = 4,
    /// 已关闭
    Closed = 5,
}

impl ConnectionStatus {
    fn to_u8(self) -> u8 {
        self as u8
    }
    
    fn from_u8(value: u8) -> Self {
        match value {
            1 => Self::Connecting,
            2 => Self::Connected,
            3 => Self::Idle,
            4 => Self::Error,
            5 => Self::Closed,
            _ => Self::Closed,
        }
    }
}

impl AcpConnectionManager {
    /// 创建新的连接池管理器
    /// 
    /// 🎯 基于当前工程成功的DashMap模式避免传统锁的竞争问题
    pub fn new(config: AcpConnectionConfig) -> Self {
        let manager = Self {
            connections: Arc::new(DashMap::new()), // ✅ 使用DashMap替代RwLock<HashMap>
            config: Arc::new(config),
            cleanup_task: Arc::new(tokio::sync::Mutex::new(None)),
        };
        
        // 启动后台清理任务
        manager.start_cleanup_task();
        manager
    }
    
    /// 🔥 获取或创建 Agent 连接基于DashMap的无死锁设计
    /// 
    /// 关键设计点:
    /// 1. 使用DashMap的entry API避免嵌套访问
    /// 2. 基于当前工程验证成功的并发模式
    /// 3. 使用 Weak 引用避免循环依赖
    /// 4. RAII 资源自动清理,无需手动管理
    pub async fn get_or_create_connection(
        &self,
        agent_id: &str,
        agent_config: &AgentConfig,
        model_provider: &ModelProviderConfig,
        project_context: &ProjectContext,
    ) -> Result<Arc<AgentConnection>, AcpError> {
        let agent_id = agent_id.to_string();
        
        // 🎯 使用DashMap的entry API原子性的检查-创建操作
        let connection_entry = self.connections.entry(agent_id.clone());
        
        match connection_entry {
            dashmap::mapref::entry::Entry::Occupied(mut occupied) => {
                // 现有连接存在
                if let Some(connection) = occupied.get().upgrade() {
                    // 检查连接状态(原子操作)
                    let status = connection.get_status();
                    if status == ConnectionStatus::Connected || status == ConnectionStatus::Idle {
                        // 原子更新最后活动时间
                        connection.update_last_activity();
                        return Ok(connection);
                    } else {
                        // 连接状态异常,清理并继续创建新连接
                        occupied.remove();
                    }
                } else {
                    // Weak引用已失效清理并继续创建新连接
                    occupied.remove();
                }
            }
            dashmap::mapref::entry::Entry::Vacant(_) => {
                // 没有现有连接,继续创建新连接
            }
        }
        
        // 📌 创建新连接
        let connection = self.create_new_connection(&agent_id, agent_config, model_provider, project_context).await?;
        
        // 📌 注册新连接(原子操作)
        self.connections.insert(agent_id, Arc::downgrade(&connection));
        
        Ok(connection)
    }
    
    /// 🔥 创建新的 ACP 连接(无死锁设计)
    async fn create_new_connection(
        &self,
        agent_id: &str,
        agent_config: &AgentConfig,
        model_provider: &ModelProviderConfig,
        project_context: &ProjectContext,
    ) -> Result<Arc<AgentConnection>, AcpError> {
        // 创建 LocalSet 实例(使用 Box 避免与全局 LocalSet 冲突)
        let local_set = Box::new(LocalSet::new());
        
        // 准备 Agent 配置
        let mut resolved_config = agent_config.clone();
        let env_resolver = EnvironmentVariableResolver::with_standard_mappings();
        env_resolver.resolve_agent_config(&mut resolved_config, model_provider, project_context)?;
        
        // 🔥 关键设计:将连接创建移到独立的作用域,避免闭包捕获 self
        let agent_id_clone = agent_id.to_string();
        let connection_future = async move {
            // 创建进程(在 LocalSet 中执行)
            let mut command = tokio::process::Command::new(&resolved_config.command);
            command.args(&resolved_config.args);
            command.envs(&resolved_config.env);
            
            let child = command.spawn()
                .map_err(|e| AcpError::ProcessError(e.to_string()))?;
            
            // 创建生命周期管理器(与现有工程集成)
            let lifecycle_guard = AgentLifecycleGuard::new(child, agent_id_clone)?;
            
            // 🔥 在 LocalSet 中创建 ACP 连接
            // 这里需要根据具体的 ACP 协议实现
            let client_conn = Self::create_acp_connection_internal(&lifecycle_guard).await?;
            
            Ok((client_conn, lifecycle_guard))
        };
        
        // 在 LocalSet 中执行连接创建
        let (client_conn, lifecycle_guard) = local_set.run_until(connection_future).await?;
        
        // 🔥 创建连接包装器RAII 模式)
        let connection = Arc::new(AgentConnection {
            agent_id: agent_id.to_string(),
            local_set,
            client_conn: RefCell::new(Some(client_conn)),
            lifecycle_guard,
            last_activity: AtomicInstant::new(),
            created_at: Instant::now(),
            status: AtomicU8::new(ConnectionStatus::Connected.to_u8()),
            manager_weak: Arc::downgrade(&self.connections),
        });
        
        // 初始化最后活动时间
        connection.last_activity.store(Instant::now());
        
        Ok(connection)
    }
    
    /// 🔥 内部 ACP 连接创建方法(避免捕获 self
    async fn create_acp_connection_internal(
        lifecycle_guard: &AgentLifecycleGuard,
    ) -> Result<ClientSideConnection, AcpError> {
        // 在这里实现具体的 ACP 连接创建逻辑
        // 根据 ACP 协议规范,建立与 Agent 的连接
        
        // 示例实现(需要根据实际 ACP 协议调整):
        let (stdin, stdout) = lifecycle_guard.get_process_stdio()?;
        let (outgoing, incoming) = create_acp_channels(stdin, stdout)?;
        
        let (client_conn, handle_io) = ClientSideConnection::new(
            client, outgoing, incoming, |fut| {
                tokio::task::spawn_local(fut);
            }
        );
        
        tokio::task::spawn_local(handle_io);
        
        Ok(client_conn)
    }
    
    /// 🔥 发送提示词到 Agent简化的无死锁接口
    pub async fn send_prompt(
        &self,
        agent_id: &str,
        prompt_request: PromptRequest,
    ) -> Result<PromptResponse, AcpError> {
        // 获取连接(会自动复用或创建新连接)
        let connection = self.get_or_create_connection(
            agent_id,
            &self.get_default_agent_config()?,
            &self.get_default_model_provider(),
            &ProjectContext::default(),
        ).await?;
        
        // 使用连接自己的方法执行操作
        connection.execute_operation(|client_conn| {
            Box::pin(async move {
                // 在这里实现具体的提示词发送逻辑
                let response = client_conn.send_prompt(prompt_request).await?;
                Ok(response)
            })
        }).await
    }
    
    /// 🔥 取消正在执行的任务(简化的无死锁接口)
    pub async fn cancel_request(
        &self,
        agent_id: &str,
        cancel_notification: CancelNotification,
    ) -> Result<(), AcpError> {
        // 获取连接
        let connection = self.get_or_create_connection(
            agent_id,
            &self.get_default_agent_config()?,
            &self.get_default_model_provider(),
            &ProjectContext::default(),
        ).await?;
        
        // 使用连接自己的方法执行操作
        connection.execute_operation(|client_conn| {
            Box::pin(async move {
                client_conn.send_cancel(cancel_notification).await?;
                Ok(())
            })
        }).await
    }
    
    /// 🔥 获取连接统计信息(无锁设计)
    pub fn get_connection_stats(&self) -> ConnectionStats {
        let connections = self.connections.read().unwrap();
        ConnectionStats {
            total_connections: connections.len(),
            max_connections: self.config.max_connections,
            cleanup_interval: self.config.cleanup_interval,
            max_idle_time: self.config.max_idle_time,
        }
    }
    
    /// 🔥 获取默认 Agent 配置(辅助方法)
    fn get_default_agent_config(&self) -> Result<AgentConfig, AcpError> {
        // 这里应该从配置管理器获取,暂时返回默认配置
        Ok(AgentConfig::default())
    }
    
    /// 🔥 获取默认 ModelProvider辅助方法
    fn get_default_model_provider(&self) -> ModelProviderConfig {
        // 这里应该从配置获取,暂时返回默认配置
        ModelProviderConfig::default()
    }
    
    /// 🔥 启动后台清理任务(无死锁设计)
    fn start_cleanup_task(&mut self) {
        let connections = self.connections.clone();
        let max_idle_time = self.config.max_idle_time;
        let cleanup_interval = self.config.cleanup_interval;
        
        let cleanup_task = tokio::spawn(async move {
            let mut interval = tokio::time::interval(cleanup_interval);
            
            loop {
                interval.tick().await;
                
                // 📌 使用 try_read 而不是 read避免阻塞
                if let Ok(connections_guard) = connections.try_read() {
                    let now = Instant::now();
                    let mut to_remove = Vec::new();
                    
                    // 检查空闲连接(使用 Weak 引用,自动处理已销毁的连接)
                    for (agent_id, weak_conn) in connections_guard.iter() {
                        if let Some(connection) = weak_conn.upgrade() {
                            // 检查连接空闲时间(原子操作,无需锁)
                            if connection.idle_duration() > max_idle_time {
                                to_remove.push(agent_id.clone());
                            }
                        } else {
                            // Weak 引用已失效,连接已被销毁
                            to_remove.push(agent_id.clone());
                        }
                    }
                    
                    // 🔥 清理无效连接(需要获取写锁,但在这里是安全的)
                    drop(connections_guard); // 释放读锁
                    
                    if let Ok(mut connections_guard) = connections.try_write() {
                        for agent_id in to_remove {
                            log::info!("清理空闲/无效连接: {}", agent_id);
                            connections_guard.remove(&agent_id);
                        }
                    }
                }
                // 如果无法获取读锁,跳过本次清理
            }
        });
        
        self.cleanup_task = Some(cleanup_task);
    }
}

/// 连接统计信息
#[derive(Debug, Clone)]
pub struct ConnectionStats {
    /// 当前总连接数
    pub total_connections: usize,
    
    /// 最大连接数限制
    pub max_connections: usize,
    
    /// 清理间隔
    pub cleanup_interval: Duration,
    
    /// 最大空闲时间
    pub max_idle_time: Duration,
}

/// ACP 错误类型
#[derive(Debug, thiserror::Error)]
pub enum AcpError {
    #[error("连接数超过限制")]
    ConnectionLimitExceeded,
    
    #[error("连接不可用")]
    ConnectionNotAvailable,
    
    #[error("进程错误: {0}")]
    ProcessError(String),
    
    #[error("连接超时")]
    ConnectionTimeout,
    
    #[error("协议错误: {0}")]
    ProtocolError(String),
    
    #[error("配置错误: {0}")]
    ConfigurationError(String),
    
    #[error("IO错误: {0}")]
    IoError(#[from] std::io::Error),
}

impl AgentConnection {
    /// 🔥 获取连接状态(原子操作)
    pub fn get_status(&self) -> ConnectionStatus {
        ConnectionStatus::from_u8(self.status.load(Ordering::Relaxed))
    }
    
    /// 🔥 设置连接状态(原子操作)
    pub fn set_status(&self, status: ConnectionStatus) {
        self.status.store(status.to_u8(), Ordering::Relaxed);
    }
    
    /// 🔥 更新最后活动时间(原子操作)
    pub fn update_last_activity(&self) {
        self.last_activity.store(Instant::now());
    }
    
    /// 🔥 获取空闲时长(原子操作)
    pub fn idle_duration(&self) -> Duration {
        let last_activity = self.last_activity.load();
        Instant::now().duration_since(last_activity)
    }
    
    /// 🔥 检查连接是否活跃(原子操作)
    pub fn is_active(&self) -> bool {
        matches!(self.get_status(), ConnectionStatus::Connected | ConnectionStatus::Idle)
    }
    
    /// 🔥 在 LocalSet 中执行 ACP 操作(无锁设计)
    pub async fn execute_operation<F, R>(&self, operation: F) -> Result<R, AcpError>
    where
        F: FnOnce(&ClientSideConnection) -> Pin<Box<dyn Future<Output = Result<R, AcpError>> + '_>> + Send + 'static,
        R: Send + 'static,
    {
        // 📌 使用 RefCell 而不是 Mutex避免与全局状态锁冲突
        let client_conn = self.client_conn.borrow_mut()
            .take()
            .ok_or_else(|| AcpError::ConnectionNotAvailable)?;
        
        // 在 LocalSet 中执行操作
        let operation_future = async move {
            // 执行用户定义的操作
            let result = operation(&client_conn).await?;
            
            // 重新存入连接(使用 RefCell 的运行时借用检查)
            Ok((result, client_conn))
        };
        
        let (result, client_conn) = self.local_set.run_until(operation_future).await?;
        
        // 重新存入连接
        *self.client_conn.borrow_mut() = Some(client_conn);
        
        Ok(result)
    }
}

impl Drop for AgentConnection {
    /// 🔥 RAII 自动清理:连接销毁时自动从管理器中移除
    fn drop(&mut self) {
        // 更新连接状态
        self.set_status(ConnectionStatus::Closed);
        
        // 尝试从管理器中移除自己
        if let Some(connections_arc) = self.manager_weak.upgrade() {
            if let Ok(mut connections) = connections_arc.try_write() {
                connections.remove(&self.agent_id);
            }
        }
        
        log::info!("Agent 连接已自动清理: {}", self.agent_id);
    }
}

impl Drop for AcpConnectionManager {
    fn drop(&mut self) {
        // 清理后台任务
        if let Some(task) = self.cleanup_task.take() {
            task.abort();
        }
        
        // 清理所有连接
        for agent_id in self.connections.iter().map(|entry| entry.key().clone()).collect::<Vec<_>>() {
            tokio::spawn({
                let manager = self.clone();
                async move {
                    manager.cleanup_connection(&agent_id).await;
                }
            });
        }
    }
}

🔥 无死锁 ACP 连接池使用示例:

// 1. 创建连接池管理器(自动启用后台清理)
let acp_config = AcpConnectionConfig::default();
let connection_manager = Arc::new(AcpConnectionManager::new(acp_config));

// 2. 🔥 简化的提示词发送(自动处理连接复用和创建)
let prompt_request = PromptRequest {
    prompt: "帮我写一个 React 组件".to_string(),
    session_id: Some("session-123".to_string()),
    model_provider: Some(model_provider.clone()),
};

let response = connection_manager.send_prompt("claude-code-acp", prompt_request).await?;

// 3. 🔥 简化的请求取消
let cancel_notification = CancelNotification {
    session_id: "session-123".to_string(),
    reason: "用户取消".to_string(),
};

connection_manager.cancel_request("claude-code-acp", cancel_notification).await?;

// 4. 🔥 连接自动管理(无需手动清理)
// 连接会根据 RAII 模式自动清理,后台任务会清理空闲连接

// 5. 获取连接统计(无锁操作)
let stats = connection_manager.get_connection_stats();
println!("当前连接数: {}/{}", stats.total_connections, stats.max_connections);
println!("最大空闲时间: {:?}", stats.max_idle_time);

// 6. 🔥 高级用法:直接使用连接对象
let agent_connection = connection_manager.get_or_create_connection(
    "claude-code-acp",
    &agent_config,
    &model_provider,
    &project_context,
).await?;

// 使用连接自己的 execute_operation 方法
let custom_result = agent_connection.execute_operation(|client_conn| {
    Box::pin(async move {
        // 自定义 ACP 操作
        let response = client_conn.custom_operation(request).await?;
        Ok(response)
    })
}).await?;

// 🔥 连接会在 agent_connection 离开作用域时自动清理

🔧 关键优势对比:

特性 原设计(死锁风险) 新设计(无死锁)
状态管理 Arc<Mutex> AtomicU8, AtomicInstant
连接存储 DashMap<String, Arc<>> RwLock<HashMap<String, Weak<>>>
锁策略 多个锁可能嵌套 单一锁,原子操作
清理方式 手动清理 RAII 自动清理
内存泄漏 可能发生 Weak 引用自动处理
死锁风险 高风险 无风险
性能 锁竞争开销 原子操作,高性能

设计要点总结:

  1. 连接复用:避免重复创建昂贵的 ACP 连接
  2. 资源隔离:每个连接使用独立的 LocalSet避免非 Send 问题
  3. 自动清理:后台任务定期清理空闲连接
  4. 线程安全:使用 Arc<Mutex<>> 包装非 Send 的 ACP 连接
  5. 状态管理:完整的连接状态跟踪和管理

这个设计解决了 ACP 协议的技术限制,同时提供了高效的连接管理机制。

4.4.6 MCP 服务器管理器

/// MCP 服务器管理器
pub struct McpServerManager {
    /// 已注册的服务器
    servers: DashMap<String, McpServerInstance>,
    /// 服务器配置
    config: Arc<McpConfig>,
    /// 进程池
    process_pool: Arc<McpProcessPool>,
}

/// MCP 服务器实例
#[derive(Debug, Clone)]
pub struct McpServerInstance {
    /// 服务器名称
    pub name: String,
    /// 服务器配置
    pub config: McpServerConfig,
    /// 进程句柄
    pub process: Option<ProcessHandle>,
    /// 连接信息
    pub connection: Option<McpConnection>,
    /// 启动时间
    pub started_at: Option<DateTime<Utc>>,
}

impl McpServerManager {
    /// 创建新的 MCP 服务器管理器
    pub fn new(config: McpConfig) -> Self {
        Self {
            servers: DashMap::new(),
            config: Arc::new(config),
            process_pool: Arc::new(McpProcessPool::new()),
        }
    }
    
    /// 启动指定的 MCP 服务器
    pub async fn start_server(
        &self,
        server_name: &str,
        agent_context: &AgentContext,
    ) -> Result<McpServerInstance, McpError> {
        // 1. 获取服务器配置
        let server_config = self.config.get_server_config(server_name)?;
        
        if !server_config.enabled {
            return Err(McpError::ServerDisabled(server_name.to_string()));
        }
        
        // 2. 检查是否已经启动
        if let Some(instance) = self.servers.get(server_name) {
            if instance.process.is_some() {
                return Ok(instance.clone());
            }
        }
        
        // 3. 启动服务器进程
        let process = self.start_server_process(&server_config, agent_context).await?;
        
        // 4. 建立 MCP 连接
        let connection = self.establish_mcp_connection(&server_config, &process).await?;
        
        // 5. 创建服务器实例
        let instance = McpServerInstance {
            name: server_name.to_string(),
            config: server_config.clone(),
            process: Some(process),
            connection: Some(connection),
            started_at: Some(Utc::now()),
        };
        
        // 6. 注册实例
        self.servers.insert(server_name.to_string(), instance.clone());
        
        Ok(instance)
    }
    
    /// 启动服务器进程
    async fn start_server_process(
        &self,
        config: &McpServerConfig,
        context: &AgentContext,
    ) -> Result<ProcessHandle, McpError> {
        match &config.source {
            McpServerSource::Custom | McpServerSource::Local => {
                self.start_command_server(config, context).await
            }
        }
    }
    
    /// 启动命令行服务器
    async fn start_command_server(
        &self,
        config: &McpServerConfig,
        context: &AgentContext,
    ) -> Result<ProcessHandle, McpError> {
        let command = config.command.as_ref()
            .ok_or_else(|| McpError::MissingCommand)?;
        
        let mut cmd = tokio::process::Command::new(command);
        
        // 添加参数
        if let Some(args) = &config.args {
            for arg in args {
                let processed_arg = self.process_template(arg, context)?;
                cmd.arg(processed_arg);
            }
        }
        
        // 设置环境变量
        if let Some(env_vars) = &config.env {
            for (key, value) in env_vars {
                let processed_value = self.process_template(value, context)?;
                cmd.env(key, processed_value);
            }
        }
        
        // 配置标准输入输出
        cmd.stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .kill_on_drop(true);
        
        // 启动进程
        let child = cmd.spawn()
            .map_err(|e| McpError::ProcessStartFailed(e.to_string()))?;
        
        Ok(ProcessHandle::new(child, config.name.clone()))
    }
    
    
    
    /// 建立 MCP 连接
    async fn establish_mcp_connection(
        &self,
        config: &McpServerConfig,
        process: &ProcessHandle,
    ) -> Result<McpConnection, McpError> {
        // 等待服务器启动
        tokio::time::sleep(self.config.mcp_startup_delay).await;
        
        // 建立 ACP 连接到 MCP 服务器
        let timeout = config.timeout.unwrap_or(self.config.mcp_timeout);
        
        let connection = tokio::time::timeout(timeout, async {
            // 实现具体的 MCP 连接逻辑
            self.create_mcp_connection(process).await
        }).await
        .map_err(|_| McpError::ConnectionTimeout)?
        .map_err(|e| McpError::ConnectionFailed(e.to_string()))?;
        
        Ok(connection)
    }
    
    /// 停止服务器
    pub async fn stop_server(&self, server_name: &str) -> Result<(), McpError> {
        if let Some((_, instance)) = self.servers.remove(server_name) {
            // 停止进程
            if let Some(process) = instance.process {
                self.process_pool.terminate(process.id(), Duration::from_secs(10)).await?;
            }
            
            // 关闭连接
            if let Some(connection) = instance.connection {
                connection.close().await?;
            }
            
            Ok(())
        } else {
            Err(McpError::ServerNotFound(server_name.to_string()))
        }
    }
    
    /// 为 Agent 启动所需的服务器
    pub async fn start_servers_for_agent(
        &self,
        server_names: &[String],
        agent_context: &AgentContext,
    ) -> Result<Vec<McpServerInstance>, McpError> {
        let mut instances = Vec::new();
        
        for server_name in server_names {
            let instance = self.start_server(server_name, agent_context).await?;
            instances.push(instance);
        }
        
        Ok(instances)
    }
    
    /// 获取服务器状态
    pub fn get_server_status(&self, server_name: &str) -> Option<McpServerInstance> {
        self.servers.get(server_name).map(|entry| entry.clone())
    }
    
    /// 列出所有服务器
    pub fn list_servers(&self) -> Vec<String> {
        self.servers.iter().map(|entry| entry.key().clone()).collect()
    }
}

4.5 Agent 工厂模式

4.4.1 AgentFactory 设计

/// Agent 工厂
pub struct AgentFactory {
    registry: Arc<AgentRegistry>,
    launcher: Arc<dyn AgentLauncher>,
    config_manager: Arc<AgentConfigManager>,
    mcp_manager: Arc<McpServerManager>,
    /// 🔥 新增ACP 连接池管理器
    acp_connection_manager: Arc<AcpConnectionManager>,
}

impl AgentFactory {
    /// 创建新的 Agent 工厂
    pub fn new(
        registry: Arc<AgentRegistry>,
        launcher: Arc<dyn AgentLauncher>,
        config_manager: Arc<AgentConfigManager>,
        mcp_manager: Arc<McpServerManager>,
        acp_connection_manager: Arc<AcpConnectionManager>,
    ) -> Self {
        Self {
            registry,
            launcher,
            config_manager,
            mcp_manager,
            acp_connection_manager,
        }
    }
    
    /// 创建 Agent 实例
    pub async fn create_agent(
        &self,
        agent_type: AgentType,
        chat_prompt: ChatPrompt,
        model_provider: Option<ModelProviderConfig>,
    ) -> Result<AgentInstance, AgentError> {
        // 1. 获取 Agent 规范
        let spec = self.registry.get_spec(&agent_type)?;
        
        // 2. 构建配置
        let config = self.config_manager.build_config(
            &spec,
            chat_prompt,
            model_provider,
        )?;
        
        // 3. 验证依赖
        self.validate_dependencies(&spec).await?;
        
        // 4. 创建上下文
        let context = AgentContext::new(&chat_prompt.project_id, chat_prompt.project_path.clone());
        
        // 5. 自动启动所有启用的 MCP 服务器
        let enabled_mcp_servers = self.config_manager.get_enabled_mcp_servers().await?;
        let mcp_instances = self.mcp_manager.start_servers_for_agent(
            &enabled_mcp_servers,
            &context,
        ).await?;
        
        // 6. 启动 Agent
        let agent_impl = self.registry.get_implementation(&agent_type)?;
        let instance = agent_impl.start(config, context, mcp_instances).await?;
        
        Ok(instance)
    }
    
    /// 验证依赖
    async fn validate_dependencies(&self, spec: &AgentSpec) -> Result<(), AgentError> {
        for dependency in &spec.dependencies {
            dependency.check().await?;
        }
        Ok(())
    }
}

4.4.2 Agent 注册表

/// Agent 注册表
pub struct AgentRegistry {
    agents: DashMap<AgentType, Arc<dyn Agent>>,
    specs: DashMap<AgentType, AgentSpec>,
}

impl AgentRegistry {
    /// 创建新的注册表
    pub fn new() -> Self {
        Self {
            agents: DashMap::new(),
            specs: DashMap::new(),
        }
    }
    
    /// 注册 Agent
    pub fn register(
        &self,
        agent_type: AgentType,
        agent: Arc<dyn Agent>,
        spec: AgentSpec,
    ) -> Result<(), AgentError> {
        if self.agents.contains_key(&agent_type) {
            return Err(AgentError::AlreadyRegistered(agent_type));
        }
        
        self.agents.insert(agent_type.clone(), agent);
        self.specs.insert(agent_type, spec);
        Ok(())
    }
    
    /// 获取 Agent 实现
    pub fn get_implementation(&self, agent_type: &AgentType) -> Result<Arc<dyn Agent>, AgentError> {
        self.agents
            .get(agent_type)
            .map(|entry| entry.value().clone())
            .ok_or_else(|| AgentError::NotFound(agent_type.clone()))
    }
    
    /// 获取 Agent 规范
    pub fn get_spec(&self, agent_type: &AgentType) -> Result<AgentSpec, AgentError> {
        self.specs
            .get(agent_type)
            .map(|entry| entry.value().clone())
            .ok_or_else(|| AgentError::NotFound(agent_type.clone()))
    }
    
    /// 列出所有注册的 Agent 类型
    pub fn list_agents(&self) -> Vec<AgentType> {
        self.agents.iter().map(|entry| entry.key().clone()).collect()
    }
}

4.5 进程管理和监控

4.5.1 进程启动器实现

/// 子进程启动器
pub struct SubprocessLauncher {
    process_pool: Arc<ProcessPool>,
    monitor: Arc<ProcessMonitor>,
}

impl SubprocessLauncher {
    /// 创建新的启动器
    pub fn new() -> Self {
        Self {
            process_pool: Arc::new(ProcessPool::new()),
            monitor: Arc::new(ProcessMonitor::new()),
        }
    }
}

#[async_trait::async_trait(?Send)]
impl AgentLauncher for SubprocessLauncher {
    async fn launch(
        &self,
        spec: &AgentSpec,
        config: &AgentConfig,
        context: &AgentContext,
    ) -> Result<LaunchedAgent, AgentError> {
        // 1. 构建命令
        let mut cmd = self.build_command(spec, config, context)?;
        
        // 2. 设置环境变量
        self.setup_environment(&mut cmd, spec, config)?;
        
        // 3. 启动进程
        let child = cmd.spawn()
            .map_err(|e| AgentError::LaunchFailed(e.to_string()))?;
        
        // 4. 创建进程句柄
        let process = ProcessHandle::new(child, context.project_id.clone());
        
        // 5. 启动监控
        self.monitor.start_monitoring(&process).await?;
        
        // 6. 创建 LaunchedAgent
        let launched = LaunchedAgent {
            process,
            spec: spec.clone(),
            config: config.clone(),
            launched_at: Utc::now(),
        };
        
        Ok(launched)
    }
    
    async fn terminate(
        &self,
        agent: &LaunchedAgent,
        timeout: Duration,
    ) -> Result<TerminationResult, AgentError> {
        self.monitor.stop_monitoring(&agent.process).await?;
        self.process_pool.terminate(agent.process.id(), timeout).await
    }
    
    async fn check_status(&self, agent: &LaunchedAgent) -> Result<ProcessStatus, AgentError> {
        self.process_pool.get_status(agent.process.id()).await
    }
}

4.5.2 进程监控

/// 进程监控器
pub struct ProcessMonitor {
    monitored_processes: DashMap<String, MonitoredProcess>,
    health_checker: Arc<HealthChecker>,
}

impl ProcessMonitor {
    /// 启动监控
    pub async fn start_monitoring(&self, process: &ProcessHandle) -> Result<(), AgentError> {
        let monitored = MonitoredProcess {
            process: process.clone(),
            last_health_check: Utc::now(),
            health_status: HealthStatus::Unknown,
        };
        
        self.monitored_processes.insert(process.id().to_string(), monitored);
        
        // 启动健康检查任务
        self.start_health_check_task(process).await;
        
        Ok(())
    }
    
    /// 健康检查任务
    async fn start_health_check_task(&self, process: &ProcessHandle) {
        let process = process.clone();
        let health_checker = self.health_checker.clone();
        let monitored_processes = self.monitored_processes.clone();
        
        tokio::spawn(async move {
            let mut interval = tokio::time::interval(Duration::from_secs(30));
            
            loop {
                interval.tick().await;
                
                let status = health_checker.check(&process).await;
                
                if let Some(mut monitored) = monitored_processes.get_mut(&process.id().to_string()) {
                    monitored.last_health_check = Utc::now();
                    monitored.health_status = status.clone();
                    
                    // 处理不健康状态
                    match status {
                        HealthStatus::Unhealthy(reason) => {
                            tracing::error!("Agent {} is unhealthy: {}", process.id(), reason);
                            // 可以触发重启或告警
                        }
                        HealthStatus::Dead => {
                            tracing::warn!("Agent {} is dead, removing from monitoring", process.id());
                            break;
                        }
                        _ => {}
                    }
                } else {
                    break; // 进程已被移除
                }
            }
        });
    }
}

5. 实现计划

5.1 阶段一基础抽象层2-3 周)

目标: 建立核心抽象接口和基础实现

任务:

  1. 定义核心 TraitAgent, AgentLauncher, AgentFactory
  2. 实现基础的 AgentRegistry
  3. 重构现有的 Claude Code ACP Agent 实现
  4. 创建基础的配置管理系统

交付物:

  • crates/agent_runner/src/agent/ 模块
  • 核心接口定义
  • Claude Code Agent 的新实现
  • 基础配置文件

5.2 阶段二进程管理和监控2-3 周)

目标: 完善进程生命周期管理和健康监控

任务:

  1. 实现 SubprocessLauncher
  2. 开发 ProcessMonitor 和 HealthChecker
  3. 添加进程池管理
  4. 实现优雅关闭机制

交付物:

  • crates/agent_runner/src/process/ 模块
  • 进程监控功能
  • 健康检查机制
  • 重启策略

5.3 阶段三配置系统和依赖管理1-2 周)

目标: 完善配置管理和依赖检查

任务:

  1. 完善 AgentConfig 结构
  2. 实现配置文件解析和验证
  3. 开发依赖检查系统
  4. 添加动态配置更新

交付物:

  • 配置文件规范
  • 依赖检查器
  • 配置热更新功能

5.4 阶段四可观测性和测试1-2 周)

目标: 添加监控、日志和测试支持

任务:

  1. 集成 OpenTelemetry 追踪
  2. 添加结构化日志
  3. 开发单元测试和集成测试
  4. 性能测试和优化

交付物:

  • 监控指标
  • 测试套件
  • 性能基准测试

6. 使用示例

6.1 基本使用

// 1. 创建 Agent 工厂
let registry = Arc::new(AgentRegistry::new());
let launcher = Arc::new(SubprocessLauncher::new());
let config_manager = Arc::new(AgentConfigManager::new());

let factory = AgentFactory::new(registry, launcher, config_manager);

// 2. 注册内置 Agent
let claude_agent = Arc::new(ClaudeCodeAgent::new());
let claude_spec = AgentSpec::from_file("claude-code-acp.yml").await?;
factory.register_agent(AgentType::Claude, claude_agent, claude_spec).await?;

// 3. 创建 Agent 实例
let chat_prompt = ChatPrompt::new("project123", "Hello, world!");
let model_provider = Some(ModelProviderConfig::anthropic("claude-3-sonnet"));

let instance = factory.create_agent(
    AgentType::Claude,
    chat_prompt,
    model_provider,
).await?;

// 4. 使用 Agent
let response = instance.send_prompt("Help me write Rust code").await?;

6.2 自定义 Agent

// 1. 实现 Agent trait
pub struct MyCustomAgent;

#[async_trait::async_trait(?Send)]
impl Agent for MyCustomAgent {
    fn agent_type(&self) -> AgentType {
        AgentType::Custom("my-agent".to_string())
    }
    
    async fn start(
        &self,
        config: AgentConfig,
        context: AgentContext,
    ) -> Result<AgentInstance, AgentError> {
        // 自定义启动逻辑
        let spec = AgentSpec::from_file("my-agent.yml").await?;
        let launcher = SubprocessLauncher::new();
        let launched = launcher.launch(&spec, &config, &context).await?;
        
        Ok(AgentInstance::new(launched, self.agent_type()))
    }
    
    // ... 其他方法实现
}

// 2. 注册自定义 Agent
let custom_agent = Arc::new(MyCustomAgent);
let custom_spec = AgentSpec::from_file("my-agent.yml").await?;

factory.register_agent(
    AgentType::Custom("my-agent".to_string()),
    custom_agent,
    custom_spec,
).await?;

7. 迁移策略

7.1 🔥 向后兼容和默认 Agent 迁移策略

核心原则:零中断迁移,用户无感知

基于对当前 claude-code-acp 实现的深入分析,我们设计了一个完美的兼容层,确保:

  • 现有 HTTP 接口完全不变
  • 现有功能 100% 保持
  • 内部逻辑平滑重构到新配置系统

7.1.1 当前实现与新配置格式的映射分析

当前硬编码逻辑 → 新配置文件格式映射:

当前硬编码 新配置文件字段 映射关系
"claude-code-acp" agent_servers.claude-code-acp.command 直接映射
Vec::<String>::new() agent_servers.claude-code-acp.args 直接映射
AgentType::claude_model_provider() agent_servers.claude-code-acp.env 环境变量映射
create_default_mcp_servers(None) context_servers.* MCP 服务器映射
chat_prompt.project_path 项目上下文自动注入 工作目录映射

7.1.2 默认配置自动生成机制

🔥 智能默认配置生成器:

/// 🔥 默认配置生成器
/// 
/// 根据当前硬编码逻辑自动生成标准配置文件
pub struct DefaultConfigGenerator;

impl DefaultConfigGenerator {
    /// 🔥 获取默认系统提示词模板
    /// 
    /// 基于现有 system_prompt.rs 的完整内容,预处理的完整系统提示词
    /// 支持动态变量替换,如 {PROJECT_NAME}、{FRAMEWORK}、{AGENT_VERSION} 等
    pub fn get_default_system_prompt_template() -> String {
        r#"<SYSTEM_INSTRUCTIONS>

你是一个专业的前端项目开发专家集成了MCP模型上下文协议工具。
你精通现代前端开发技术栈,包括 React、Vue、Vite、TypeScript 等主流框架和工具。
你被设计成能够识别项目使用的框架,并基于项目现有技术栈进行开发,而不是强行转换框架。

**核心能力**
• **框架识别**: 能够自动识别项目使用的前端框架React、Vue 等)
• **框架适配**: 基于项目当前框架编写代码,保持技术栈一致性
• **通用工具**: Vite、TypeScript、Tailwind CSS、ESLint、Prettier
• **HTTP客户端**: Axios、Fetch API
• **包管理器**: pnpm、npm、yarn
• **构建工具**: Vite (热重载、快速构建)
• **代码规范**: ESLint + Prettier + TypeScript 严格模式

**关键原则**
1. **优先识别现有框架**:在修改代码前,先检测项目使用的框架(通过 package.json、文件结构等
2. **保持技术栈一致**:如果项目使用 Vue就用 Vue 开发;如果是 React就用 React
3. **不强行转换框架**:绝对不要将 Vue 代码改为 React或将 React 代码改为 Vue
4. **项目开发**:基于现有项目结构开发,来开发新功能或修复现有功能

</SYSTEM_INSTRUCTIONS>

<ROLE_DEFINITION>
你是专业的前端开发专家,精通多种现代前端框架和工具链。
你可以访问各种MCP工具包括用于网络搜索和文档检索的 context7。

**技术能力范围**
• **主流框架**: React、Vue、Angular、Svelte 等现代前端框架及其生态系统
• **开发语言**: TypeScript、JavaScript (ES6+)、HTML5、CSS3
• **样式方案**: Tailwind CSS、CSS Modules、Sass、Less、Styled Components
• **构建工具**: Vite、Webpack、Rollup、esbuild 等现代构建工具
• **状态管理**: 各框架对应的状态管理方案Redux、Pinia、NgRx、Zustand 等)
• **HTTP客户端**: Axios、Fetch API、各框架的 HTTP 库
• **代码规范**: ESLint、Prettier、TSLint 等代码质量工具

**核心工作原则**
1. **先识别框架**:在编写代码前,必须先识别项目使用的框架和技术栈
2. **尊重现有技术栈**:基于项目现有框架和工具进行开发,不擅自转换
3. **保持一致性**:使用项目当前框架的语法、规范和最佳实践
4. **使用工具**:在可以提供更好答案的情况下,使用可用的 MCP 工具
5. **最佳实践**:遵循各框架和工具的最新最佳实践和设计模式
</ROLE_DEFINITION>

<CODE_FORMAT_RULES>
**通用代码规范**
1. 始终使用 TypeScript 严格模式编写代码
2. 组件文件使用 PascalCase 命名,工具函数使用 camelCase
3. 接口类型使用 PascalCase + 'Interface' 或 'Type' 后缀
4. 优先使用 Tailwind CSS 进行样式设计
5. API 调用使用 Axios 客户端或 Fetch API
6. 为复杂逻辑添加 JSDoc 风格注释
7. 遵循项目的代码规范和文件结构约定
8. 确保代码格式正确且可读
9. 考虑错误处理和边界情况
10. 使用适当的变量和函数名称
11. 利用 Vite 的快速构建和热重载特性
12. 项目根目录下的文件'index.html',这个文件的'title'标签里,不要包含前端框架名 比如: React,Vite,Vue,Antd,Angular 等
13. **重要:路由模式规范**:在开发过程中,涉及到路由时请务必使用 hash 模式。例如React Router 使用 `HashRouter`Vue Router 配置 `mode: 'hash'`Angular Router 使用 `LocationStrategy` 的 `HashLocationStrategy`。
14. **重要:保护注入代码块**:绝对禁止删除或修改被 `DEV-INJECT-START` 和 `DEV-INJECT-END` 标记包围的代码块。这些代码块是由开发工具自动注入的,必须完整保留。在编辑代码时,需要保留这些标记及其之间的所有内容。

**React 项目特定规范**
• 遵循 React 函数组件最佳实践,使用 React.FC 类型
• 使用 Radix UI 组件库构建 UI
• 表单使用 React Hook Form + Zod 进行验证
• 使用 React.memo、useCallback、useMemo 优化性能
• 遵循 React Hooks 规则
• 路由必须使用 `HashRouter`(来自 react-router-dom不要使用 `BrowserRouter`

**Vue 项目特定规范**
• 优先使用 Composition APIsetup 语法糖)
• 使用 Element Plus 或其他 Vue UI 组件库
• 使用 Pinia 进行状态管理
• 遵循 Vue 最佳实践和响应式系统规则
• 使用 computed、watch、ref、reactive 等组合式 API
• Vue Router 必须配置为 hash 模式:`createRouter({ history: createWebHashHistory(), ... })`
</CODE_FORMAT_RULES>

<DEVELOPMENT_CONSTRAINTS>
**严格禁止的操作 - 绝对不允许执行**

🚫 **安全禁令**(最高优先级):
- **绝对禁止**探测、扫描或访问内网IP地址如 10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、127.0.0.0/8
- **绝对禁止**尝试访问本地服务localhost、127.0.0.1、0.0.0.0
- **绝对禁止**端口扫描、网络探测、内网服务发现等行为
- **绝对禁止**在代码中硬编码内网IP地址或私有网络地址
- **绝对禁止**使用 curl、wget、nc、telnet、nmap 等工具探测内网
- **绝对禁止**执行任何可能危害系统安全的命令或代码
- **绝对禁止**绕过安全限制或尝试提权操作
- **绝对禁止**执行反向Shell、远程代码执行等恶意操作
- **核心原则**所有网络请求必须指向公网服务或用户明确提供的合法API端点

🚫 **框架转换禁令**(最重要):
- **绝对禁止**将 Vue 代码改写为 React 代码
- **绝对禁止**将 React 代码改写为 Vue 代码
- **绝对禁止**在现有项目中擅自更换框架
- **必须遵守**识别项目框架后只使用该框架的语法和API
- **核心原则**:尊重项目现有技术栈,保持框架一致性

🚫 **项目初始化禁令**
- 禁止使用 npm create、npm init
- 禁止使用 yarn create、yarn init
- 禁止使用 npx create-react-app、npx create-vue
- 禁止使用 pnpm create
- 禁止使用任何shell命令进行项目初始化
- 禁止提示用户如何使用 npm dev、npm build 等命令(因为工程是服务器部署的服务,用户没有权限执行)

🚫 **文件/脚本创建禁令**
- **禁止**在项目中创建、引用或注入名为 'dev-monitor.js' 的文件或脚本

🚫 **代码块保护禁令**(重要):
- **绝对禁止**删除或修改被 `DEV-INJECT-START` 和 `DEV-INJECT-END` 标记包围的代码块
- **绝对禁止**在编辑代码时移除这些标记或它们之间的内容
- **必须遵守**:这些代码块是由开发工具自动注入的,必须完整保留
- **核心原则**:在修改代码时,如果遇到这些标记,需要绕开或保留这些标记之间的所有内容

✅ **允许的操作范围**
- **首要任务**:识别项目使用的框架(检查 package.json、文件结构等
- 专注于编写和修改前端代码文件
- 基于项目框架创建组件、页面、样式文件Vue 用 .vueReact 用 .tsx/.jsx
- 修改现有的 TypeScript/JavaScript 代码(保持框架语法)
- 编写 Tailwind CSS 或其他样式
- 使用项目对应的 UI 组件库React 用 Radix UIVue 用 Element Plus
- 配置文件的代码层面修改(如 tsconfig.json、vite.config.ts
- 遵循项目的代码规范和文件结构
- **仅允许访问**用户明确提供的公网API端点或合法的外部服务

**核心原则**
- 你是前端代码编写专家,不是项目管理员
- **最重要**:识别并尊重项目框架,绝不擅自转换框架
- **安全第一**:绝不执行任何可能危害系统安全的操作
- 用户负责依赖安装、服务启动和测试运行
- 总是用中文回复
</DEVELOPMENT_CONSTRAINTS>

<MCP_TOOL_GUIDANCE>
可用的MCP工具
- context7: 搜索网络、检索前端框架文档React、Vue、Vite、TypeScript等

**关键工具使用规则**
1. **支持的主流技术栈**
   - 前端框架React、Vue、Angular、Svelte 等及其对应的生态系统
   - 构建工具Vite、Webpack、Rollup、esbuild 等
   - 开发语言TypeScript、JavaScript、HTML、CSS
   - 样式方案Tailwind CSS、CSS Modules、Sass、Less 等
   - 通用工具Axios、Fetch API、ESLint、Prettier 等
2. **现有项目处理流程**(最重要):
   - **第一步**:检查 package.json 识别项目使用的框架和依赖
   - **第二步**:检查文件结构识别项目类型(.vue = Vue.tsx/.jsx = React.component.ts = Angular
   - **第三步**:基于识别的框架编写代码,绝不转换框架
   - **示例**:检测到 "vue" 依赖则使用 Vue 语法,检测到 "react" 则用 React 语法
3. 使用 context7 搜索对应框架的文档、示例和最佳实践
4. 在编写任何代码之前始终验证项目结构和框架

**核心记忆**
- 现有项目 = 先识别框架,再用对应框架语法编码
- **绝不擅自转换框架**Vue 项目保持 VueReact 项目保持 React
</MCP_TOOL_GUIDANCE>

<THINKING_REQUIREMENTS>
回应之前,你必须遵循这个确切的前端开发工作流程:

**第一阶段:项目状态检测**
1. **关键第一步**:检查项目目录状态
2. **如果是现有项目**(最重要):
   - **步骤1**:立即读取 package.json 文件
   - **步骤2**:检查 dependencies 识别前端框架react、vue、@angular/core、svelte 等)
   - **步骤3**:检查项目文件结构识别框架类型(.vue、.tsx/.jsx、.component.ts、.svelte 等)
   - **步骤4**:明确识别项目使用的框架和技术栈
   - **步骤5**在后续所有操作中只使用该框架的语法和API

**第二阶段:框架识别与确认**
3. **框架识别标志**
   - Vue 项目package.json 中有 "vue" 依赖,存在 .vue 文件
   - React 项目package.json 中有 "react" 依赖,存在 .tsx/.jsx 文件
   - Angular 项目package.json 中有 "@angular/core" 依赖,存在 .component.ts 文件
   - Svelte 项目package.json 中有 "svelte" 依赖,存在 .svelte 文件
4. **框架确认后的行为**
   - Vue 项目:使用 Vue APIComposition API 或 Options API、.vue 文件、Vue Router、Pinia 等
   - React 项目:使用 React APIHooks、类组件等、.tsx/.jsx 文件、React Router、Redux/Zustand 等
   - Angular 项目:使用 Angular API、组件/服务/模块、RxJS、Angular Router 等
   - Svelte 项目:使用 Svelte 语法、.svelte 文件、SvelteKit 等
   - **绝对禁止**:在任何项目中擅自切换到其他框架的语法

**第三阶段:开发执行**
5. 详细分析用户的开发请求
6. 确定是否需要使用 context7 搜索对应框架的文档
7. 基于识别的框架生态系统规划开发方法
8. 优先考虑该框架的最佳实践和现代开发模式
9. 考虑框架特有的错误处理、状态管理、组件设计等
10. 遵循项目的代码规范和文件结构约定
11. **路由配置要求**(重要):
    - 如果涉及路由配置,必须使用 hash 模式
    - React 项目:使用 `HashRouter`
    - Vue 项目:使用 `createWebHashHistory()`
    - Angular 项目:使用 `HashLocationStrategy`
    - 绝对禁止使用 history 模式BrowserRouter、createWebHistory 等)
12. **MCP工具调用规范**
    - 使用 context7 搜索对应框架的文档和最佳实践

**绝对规则(核心中的核心)**
⚠️ **框架一致性原则**
- 识别项目使用的框架 → 只用该框架的语法和API → 绝不转换为其他框架
- Vue 项目保持 Vue、React 项目保持 React、Angular 项目保持 Angular
- **违反此原则是最严重的错误**

**检查清单**
✓ 是否已读取 package.json
✓ 是否已识别项目框架?
✓ 是否确认使用正确的框架语法?
✓ 是否避免了框架转换?
✓ 如果涉及路由,是否使用了 hash 模式?
</THINKING_REQUIREMENTS>

</SYSTEM_INSTRUCTIONS>

📋 **项目信息**
- 项目名称:{PROJECT_NAME}
- Agent 版本:{AGENT_VERSION}
- 构建时间:{BUILD_TIME}

💻 **提示词处理**
- 用户输入将被包装在 `<USER_REQUEST>` 标签中
- 支持动态变量替换:{PROJECT_NAME}、{FRAMEWORK}、{WORKSPACE_DIR} 等
- 保持完整的系统提示词结构和格式"#.to_string()
    }
    
    /// 🔥 获取默认用户提示词包装模板
    /// 
    /// 基于现有 system_prompt.rs 的完整内容,预处理的用户提示词包装逻辑
    /// 支持动态变量替换,如 {PROJECT_NAME}、{FRAMEWORK}、{AGENT_VERSION} 等
    pub fn get_default_user_prompt_template() -> String {
        r#"你是RCoder一个专业的AI编程助手。

## 核心身份与职责
- 专业的编程助手,帮助用户解决编程问题
- 提供简洁、实用、可执行的代码解决方案
- 遵循最佳实践,编写高质量代码
- 始终将用户需求放在首位

## 代码格式规范
- 优先使用现代语言特性和标准库
- 变量和函数命名使用清晰、描述性的英文名称
- 保持代码简洁,避免过度复杂的抽象
- 使用适当的注释解释关键逻辑

## 开发约束
- 避免添加未请求的功能,保持解决方案专注
- 优先选择最简单有效的实现方式
- 不要为未来可能的需求添加复杂性
- 确保代码安全、可维护

## MCP工具使用指导
- 合理使用可用的工具来辅助开发任务
- 当需要文件操作、搜索、测试时使用相应的工具
- 根据上下文选择最合适的工具

## 思考要求
- 在回答前进行充分的思考和分析
- 确保解决方案的完整性和正确性
- 提供清晰、有条理的回答

项目信息:{PROJECT_NAME}
Agent 版本:{AGENT_VERSION}

用户请求:
{user_prompt}"#.to_string()
    }
    
    /// 🔥 生成 claude-code-acp 的默认配置
        AgentServersConfig {
            agent_servers: {
                let mut agents = HashMap::new();
                
                // 基于当前实现的 claude-code-acp 配置
                agents.insert("claude-code-acp".to_string(), AgentServerConfig {
                    command: "claude-code-acp".to_string(),
                    args: vec![], // 与当前 Vec::<String>::new() 一致
                    
                    // 🔥 环境变量映射:基于 AgentType::claude_model_provider() 逻辑
                    env: {
                        let mut env = HashMap::new();
                        // 这些环境变量与当前 AgentType::claude_model_provider() 完全一致
                        env.insert("ANTHROPIC_API_KEY".to_string(), "{MODEL_PROVIDER_API_KEY}".to_string());
                        env.insert("ANTHROPIC_BASE_URL".to_string(), "{MODEL_PROVIDER_BASE_URL}".to_string());
                        env.insert("ANTHROPIC_MODEL".to_string(), "{MODEL_PROVIDER_DEFAULT_MODEL}".to_string());
                        env.insert("RUST_LOG".to_string(), "info".to_string());
                        env
                    },
                    
                    // 🔥 系统提示词,这里没有
                    system_prompt: Some(SystemPromptConfig {
                        template: ""
                        enabled: true, // 默认启用
                    }),
                    
                    // 🔥 用户提示词包装:基于现有 system_prompt.rs 的完整包装逻辑
                    user_prompt: Some(UserPromptConfig {
                        template: Self::get_default_user_prompt_template(), // 使用完整的用户提示词包装逻辑
                        enabled: true,
                    }),
                    
                    installation: InstallationConfig {
                        package_manager: PackageManager::Npm,
                        package_name: "@zed-industries/claude-code-acp".to_string(),
                        version: "latest".to_string(),
                        source: None,
                        validate_command: Some(vec!["claude-code-acp".to_string(), "--version".to_string()]),
                        auto_update: false,
                    },
                    enabled: true,
                    metadata: {
                        let mut meta = HashMap::new();
                        meta.insert("version".to_string(), env!("CARGO_PKG_VERSION").to_string());
                        meta.insert("compatibility".to_string(), "claude-code-acp-v1".to_string());
                        meta
                    },
                });
                
                agents
            },
            
            // 🔥 MCP 服务器配置:基于 create_default_mcp_servers(None) 逻辑
            context_servers: Self::generate_default_mcp_servers(),
        }
    }
    
    /// 🔥 生成默认 MCP 服务器配置
    fn generate_default_mcp_servers() -> HashMap<String, ContextServerConfig> {
        let mut servers = HashMap::new();
        
        // 基于当前 create_default_mcp_servers() 的逻辑
        
        // Fetch MCP 服务器
        servers.insert("fetch".to_string(), ContextServerConfig {
            source: McpServerSource::Custom,
            enabled: true,
            command: "uvx".to_string(),
            args: vec!["mcp-server-fetch".to_string()],
            env: HashMap::new(),
            timeout: Some(Duration::from_secs(30)),
        });
        
        // Context7 MCP 服务器(当前默认不使用 API key
        servers.insert("context7".to_string(), ContextServerConfig {
            source: McpServerSource::Custom,
            enabled: true,
            command: "npx".to_string(),
            args: vec!["-y".to_string(), "@upstash/context7-mcp".to_string()],
            env: {
                let mut env = HashMap::new();
                env.insert("NODE_ENV".to_string(), "production".to_string());
                // 注意:当前不设置 CONTEXT7_API_KEY与 None 参数一致
                env
            },
            timeout: Some(Duration::from_secs(30)),
        });
        
        servers
    }
    
    /// 🔥 保存默认配置到文件
    pub async fn save_default_config<P: AsRef<Path>>(path: P) -> Result<(), ConfigError> {
        let config = Self::generate_claude_code_acp_config();
        let json = serde_json::to_string_pretty(&config)
            .map_err(|e| ConfigError::SerializationError(e.to_string()))?;
        
        tokio::fs::write(path, json)
            .await
            .map_err(|e| ConfigError::IoError(e.to_string()))?;
        
        Ok(())
    }
    
    /// 🔥 检查并生成默认配置(如果不存在)
    pub async fn ensure_default_config<P: AsRef<Path>>(config_path: P) -> Result<AgentServersConfig, ConfigError> {
        let path = config_path.as_ref();
        
        if path.exists() {
            // 配置文件已存在,直接加载
            AgentServersConfig::from_file(path).await
        } else {
            // 配置文件不存在,生成默认配置
            log::info!("配置文件不存在,生成默认配置: {:?}", path);
            Self::save_default_config(path).await?;
            Self::generate_claude_code_acp_config().into()
        }
    }
}

7.1.3 🔄 兼容层实现

🔥 零中断兼容层:

/// 🔥 Claude Code ACP Agent 兼容层
/// 
/// 保持现有接口完全不变,内部使用新的配置系统
pub struct ClaudeCodeAcpAgent {
    /// 🔥 内部配置管理器
    config_manager: Arc<AgentConfigManager>,
    
    /// 🔥 ACP 连接池管理器
    acp_connection_manager: Arc<AcpConnectionManager>,
    
    /// 🔥 默认 Agent ID
    default_agent_id: String,
}

impl ClaudeCodeAcpAgent {
    /// 🔥 创建兼容的 Claude Code ACP Agent
    pub async fn new() -> Result<Self, AcpError> {
        // 🔥 自动生成或加载配置(用户无感知)
        let config_path = PathBuf::from("/etc/rcoder/agents.json");
        let agent_config = DefaultConfigGenerator::ensure_default_config(&config_path).await?;
        
        let config_manager = Arc::new(AgentConfigManager::new(agent_config));
        let acp_connection_manager = Arc::new(AcpConnectionManager::new(AcpConnectionConfig::default()));
        
        Ok(Self {
            config_manager,
            acp_connection_manager,
            default_agent_id: "claude-code-acp".to_string(),
        })
    }
}

// 🔥 保持现有 AcpAgentService 接口完全不变
#[async_trait::async_trait(?Send)]
impl AcpAgentService for ClaudeCodeAcpAgent {
    async fn start_agent_service(
        &self,
        chat_prompt: ChatPrompt,
        model_provider: Option<ModelProviderConfig>,
    ) -> Result<AcpConnectionInfo, AcpError> {
        // 🔥 使用新的配置系统,但对外接口保持不变
        self.start_claude_code_acp_agent_service(chat_prompt, model_provider).await
    }
    
    fn agent_type_name(&self) -> &'static str {
        "claude-code-acp"
    }
}

7.1.4 🚀 迁移执行策略

🔥 渐进式迁移步骤:

  1. 阶段 1兼容层实现

    // 保持现有调用方式完全不变
    let connection_info = start_claude_code_acp_agent_service(chat_prompt, model_provider).await?;
    
  2. 阶段 2自动配置生成

    // 首次运行时自动生成默认配置文件
    DefaultConfigGenerator::ensure_default_config("/etc/rcoder/agents.json").await?;
    
  3. 阶段 3内部重构

    // 现有接口保持不变,内部使用新配置系统
    impl ClaudeCodeAcpAgent {
        pub async fn start_claude_code_acp_agent_service(...) -> Result<AcpConnectionInfo> {
            // 新的内部实现
        }
    }
    
  4. 阶段 4用户可选配置

    # 用户可以修改生成的配置文件来定制行为
    vim /etc/rcoder/agents.json
    

🎯 迁移成功验证:

  • HTTP 接口无变化:所有现有 API 调用保持不变
  • 功能 100% 兼容:现有功能完全保持
  • 性能无影响:内部优化不影响外部性能
  • 配置向后兼容:默认配置与硬编码行为一致
  • 用户无感知:自动生成配置,无需手动干预

7.2 传统迁移步骤(保留作为参考)

  1. 保留现有接口:现有的 AcpAgentService trait 继续支持
  2. 渐进式迁移:新功能使用新的抽象层,现有代码逐步迁移
  3. 适配器模式:为现有实现提供适配器

7.3 🔄 新旧系统对比映射

硬编码逻辑 → 配置文件映射表:

当前代码位置 硬编码逻辑 配置文件映射 说明
command_path = "claude-code-acp" 固定命令 command: "claude-code-acp" 直接映射
command_args = Vec::<String>::new() 空参数 args: [] 直接映射
AgentType::claude_model_provider() 环境变量生成 env: { ... } 完全映射
create_default_mcp_servers(None) MCP 服务器 context_servers.* 功能映射
chat_prompt.project_path 工作目录 项目上下文 自动注入
4. 第四阶段:优化和扩展新功能

8. 风险评估和缓解

8.1 技术风险

风险: 抽象层可能引入性能开销 缓解:

  • 使用零成本抽象设计
  • 性能测试和基准对比
  • 关键路径优化

风险: 进程管理复杂性增加 缓解:

  • 充分的测试覆盖
  • 渐进式实现
  • 错误处理和恢复机制

8.2 兼容性风险

风险: 新抽象层可能与现有代码不兼容 缓解:

  • 保持向后兼容性
  • 提供迁移指南和工具
  • 充分的集成测试

9. 总结

本设计方案提供了一个可扩展、可维护的 Agent 抽象层,具有以下优势:

  1. 高度可扩展:支持新 Agent 类型的轻松添加
  2. 配置灵活:支持多种配置方式和动态更新
  3. 进程隔离:确保系统稳定性和安全性
  4. 统一接口:简化 Agent 的使用和管理
  5. 可观测性:完整的监控和日志支持
  6. 向后兼容:平滑的迁移路径

通过分阶段实施,可以在不破坏现有功能的前提下,逐步构建起强大的 Agent 管理系统,为 RCoder 项目的长期发展奠定坚实基础。


扩展:自动 MCP 服务器集成

为了实现所有 Agent 自动使用所有启用的 context_servers需要在 AgentFactory 中集成 MCP 管理器:

Agent 集成示例

/// Agent 上下文
#[derive(Debug, Clone)]
pub struct AgentContext {
    pub project_id: String,
    pub project_path: PathBuf,
    pub timestamp: DateTime<Utc>,
}

impl AgentContext {
    pub fn new(project_id: &str, project_path: PathBuf) -> Self {
        Self {
            project_id: project_id.to_string(),
            project_path,
            timestamp: Utc::now(),
        }
    }
}

/// 扩展的 Agent 配置管理器
impl AgentConfigManager {
    /// 获取所有启用的 MCP 服务器名称
    pub async fn get_enabled_mcp_servers(&self) -> Result<Vec<String>, ConfigError> {
        let mut enabled_servers = Vec::new();
        
        for (server_name, server_config) in &self.config.context_servers {
            if server_config.enabled {
                enabled_servers.push(server_name.clone());
            }
        }
        
        Ok(enabled_servers)
    }
    
    /// 获取 MCP 服务器配置
    pub fn get_mcp_server_config(&self, server_name: &str) -> Result<McpServerConfig, ConfigError> {
        let server_config = self.config.context_servers.get(server_name)
            .ok_or_else(|| ConfigError::ServerError(format!("MCP server '{}' not found", server_name)))?;
        
        Ok(McpServerConfig {
            name: server_name.to_string(),
            source: match server_config.source.as_str() {
                "custom" => McpServerSource::Custom,
                "local" => McpServerSource::Local,
                _ => McpServerSource::Custom,
            },
            enabled: server_config.enabled,
            command: server_config.command.clone(),
            args: server_config.args.clone(),
            env: server_config.env.clone(),
            timeout: Some(Duration::from_secs(30)),
        })
    }
}

使用流程

  1. 配置解析:读取 context_servers 配置
  2. 启用筛选:获取所有 enabled: true 的服务器
  3. 自动启动:为每个 Agent 启动这些 MCP 服务器
  4. 统一管理:所有 Agent 共享相同的 MCP 服务器实例

这样,无论用户选择哪个 Agent都能自动获得所有可用的 MCP 工具支持。


简化的配置结构定义

/// Agent 服务器配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentServersConfig {
    /// Agent 服务器配置
    pub agent_servers: HashMap<String, AgentServerConfig>,
    /// MCP 上下文服务器配置
    pub context_servers: HashMap<String, ContextServerConfig>,
}

/// Agent 服务器配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentServerConfig {
    /// 命令
    pub command: Option<String>,
    /// 命令参数
    pub args: Option<Vec<String>>,
    /// 环境变量
    pub env: Option<HashMap<String, String>>,
    /// 安装配置
    pub installation: Option<InstallationConfig>,
}

/// 安装配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InstallationConfig {
    /// 包管理器类型
    pub package_manager: String,
    /// 包名
    pub package_name: Option<String>,
    /// 版本约束
    pub version: Option<String>,
    /// 安装源
    pub source: Option<String>,
    /// 验证命令
    pub validate_command: Option<Vec<String>>,
}

/// 上下文服务器配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContextServerConfig {
    /// 服务器来源类型
    pub source: String,
    /// 是否启用
    pub enabled: bool,
    /// 启动命令
    pub command: Option<String>,
    /// 命令参数
    pub args: Option<Vec<String>>,
    /// 环境变量
    pub env: Option<HashMap<String, String>>,
}