227 lines
7.6 KiB
Rust
227 lines
7.6 KiB
Rust
//! Agent servers configuration structure.
|
||
//!
|
||
//! 此模块负责配置的查询和管理。
|
||
//! 默认配置从 `default_agent_config` 模块加载(来源于 `configs/default_agents.json`)。
|
||
|
||
use serde::{Deserialize, Serialize};
|
||
use std::collections::HashMap;
|
||
use std::path::Path;
|
||
|
||
use super::default_agent_config::{
|
||
default_agent_servers, default_agent_servers_for_service, default_context_servers,
|
||
default_context_servers_for_service,
|
||
};
|
||
use crate::types::agent_config::AgentConfig;
|
||
use crate::types::error::{ConfigError, Result};
|
||
use crate::types::mcp_config::ContextServerConfig;
|
||
use crate::types::system_prompt::DEFAULT_SYSTEM_PROMPT;
|
||
|
||
/// Agent servers configuration
|
||
///
|
||
/// 包含所有 Agent 和 Context Server 的配置集合。
|
||
/// 默认配置来自 `configs/default_agents.json`(编译时嵌入)。
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct AgentServersConfig {
|
||
/// Agent servers configuration
|
||
pub agent_servers: HashMap<String, AgentConfig>,
|
||
|
||
/// Context servers configuration (MCP servers)
|
||
#[serde(default)]
|
||
pub context_servers: HashMap<String, ContextServerConfig>,
|
||
}
|
||
|
||
impl AgentServersConfig {
|
||
/// 获取默认配置
|
||
///
|
||
/// 返回从 `configs/default_agents.json` 加载的配置。
|
||
///
|
||
/// # 已弃用
|
||
///
|
||
/// 此方法已弃用,请使用 `load_or_default_for_service` 以支持多服务类型。
|
||
#[deprecated(
|
||
since = "0.2.0",
|
||
note = "请使用 load_or_default_for_service 以支持多服务类型"
|
||
)]
|
||
pub async fn load_or_default() -> Self {
|
||
Self::default()
|
||
}
|
||
|
||
/// 根据服务类型加载或使用默认配置
|
||
///
|
||
/// # 参数
|
||
/// - `service_type`: 服务类型(RCoder 或 ComputerAgentRunner)
|
||
///
|
||
/// # 返回
|
||
/// 对应服务类型的默认配置
|
||
pub async fn load_or_default_for_service(service_type: &shared_types::ServiceType) -> Self {
|
||
Self::default_for_service(service_type)
|
||
}
|
||
|
||
/// 根据服务类型创建默认配置
|
||
///
|
||
/// # 参数
|
||
/// - `service_type`: 服务类型
|
||
///
|
||
/// # 返回
|
||
/// 对应服务类型的默认配置实例
|
||
pub fn default_for_service(service_type: &shared_types::ServiceType) -> Self {
|
||
Self {
|
||
agent_servers: default_agent_servers_for_service(service_type),
|
||
context_servers: default_context_servers_for_service(service_type),
|
||
}
|
||
}
|
||
|
||
/// 从外部文件加载配置
|
||
///
|
||
/// 用于加载用户自定义的配置文件,覆盖默认配置。
|
||
pub async fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||
let path = path.as_ref();
|
||
if !path.exists() {
|
||
return Err(ConfigError::file_not_found(path.display()).into());
|
||
}
|
||
|
||
let content = tokio::fs::read_to_string(path)
|
||
.await
|
||
.map_err(|e| ConfigError::Read(format!("{}: {}", path.display(), e)))?;
|
||
|
||
Self::from_json(&content)
|
||
}
|
||
|
||
/// 从 JSON 字符串加载配置
|
||
///
|
||
/// 用于解析用户传入的 JSON 配置。
|
||
pub fn from_json(json: &str) -> Result<Self> {
|
||
serde_json::from_str(json).map_err(|e| ConfigError::Deserialization(e.to_string()).into())
|
||
}
|
||
|
||
/// Validate configuration
|
||
pub fn validate(&self) -> Result<()> {
|
||
// Validate agent servers
|
||
for (name, config) in &self.agent_servers {
|
||
if config.agent_id.is_empty() {
|
||
return Err(
|
||
ConfigError::missing_field(format!("agent_servers.{}.agent_id", name)).into(),
|
||
);
|
||
}
|
||
if config.command.is_empty() {
|
||
return Err(
|
||
ConfigError::missing_field(format!("agent_servers.{}.command", name)).into(),
|
||
);
|
||
}
|
||
}
|
||
|
||
// Validate context servers
|
||
for (name, config) in &self.context_servers {
|
||
if config.command.is_none() {
|
||
return Err(ConfigError::missing_field(format!(
|
||
"context_servers.{}.command",
|
||
name
|
||
))
|
||
.into());
|
||
}
|
||
}
|
||
|
||
Ok(())
|
||
}
|
||
|
||
/// Get all enabled agents
|
||
pub fn get_enabled_agents(&self) -> Vec<&AgentConfig> {
|
||
self.agent_servers
|
||
.values()
|
||
.filter(|config| config.enabled)
|
||
.collect()
|
||
}
|
||
|
||
/// Get an agent configuration by ID
|
||
pub fn get_agent(&self, agent_id: &str) -> Option<&AgentConfig> {
|
||
self.agent_servers.get(agent_id)
|
||
}
|
||
|
||
/// 获取系统提示词(优先使用配置,否则使用默认值)
|
||
///
|
||
/// # 参数
|
||
/// - `agent_id`: Agent 标识符
|
||
///
|
||
/// # 返回
|
||
/// 根据配置的 source 字段决定返回内容:
|
||
/// - `source: "embedded"` -> 返回编译时嵌入的默认提示词
|
||
/// - `source: "custom"` 且 template 非空 -> 返回自定义模板内容
|
||
/// - 其他情况 -> 回退到编译时嵌入的默认提示词
|
||
///
|
||
/// 注意:此方法始终返回有效的系统提示词,不受 enabled 字段影响。
|
||
/// 如需检查是否启用,请直接调用 `SystemPromptConfig::get_prompt()`。
|
||
pub fn get_system_prompt(&self, agent_id: &str) -> String {
|
||
if let Some(agent) = self.get_agent(agent_id) {
|
||
// 如果有系统提示词配置,使用 get_prompt_or_default() 确保始终返回有效提示词
|
||
if let Some(ref prompt_config) = agent.system_prompt {
|
||
return prompt_config.get_prompt_or_default().to_string();
|
||
}
|
||
}
|
||
// 回退到编译时嵌入的默认值
|
||
DEFAULT_SYSTEM_PROMPT.to_string()
|
||
}
|
||
|
||
/// Get all enabled context servers
|
||
pub fn get_enabled_context_servers(&self) -> Vec<&ContextServerConfig> {
|
||
self.context_servers
|
||
.values()
|
||
.filter(|config| config.enabled)
|
||
.collect()
|
||
}
|
||
|
||
/// Get a context server configuration by name
|
||
pub fn get_context_server(&self, name: &str) -> Option<&ContextServerConfig> {
|
||
self.context_servers.get(name)
|
||
}
|
||
|
||
/// 创建默认配置
|
||
///
|
||
/// 从 `configs/default_agents.json` 加载的配置(编译时嵌入)。
|
||
/// 修改 JSON 文件后重新编译即可生效。
|
||
pub fn default() -> Self {
|
||
Self {
|
||
agent_servers: default_agent_servers(),
|
||
context_servers: default_context_servers(),
|
||
}
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[tokio::test]
|
||
async fn test_load_or_default_for_service() {
|
||
// 测试 RCoder
|
||
let rcoder_config =
|
||
AgentServersConfig::load_or_default_for_service(&shared_types::ServiceType::RCoder)
|
||
.await;
|
||
assert!(!rcoder_config.agent_servers.is_empty());
|
||
|
||
// 测试 ComputerAgentRunner
|
||
let car_config = AgentServersConfig::load_or_default_for_service(
|
||
&shared_types::ServiceType::ComputerAgentRunner,
|
||
)
|
||
.await;
|
||
assert!(!car_config.agent_servers.is_empty());
|
||
}
|
||
|
||
#[test]
|
||
fn test_default_for_service() {
|
||
// 测试 RCoder
|
||
let rcoder_config =
|
||
AgentServersConfig::default_for_service(&shared_types::ServiceType::RCoder);
|
||
assert!(!rcoder_config.agent_servers.is_empty());
|
||
|
||
// 测试 ComputerAgentRunner
|
||
let car_config = AgentServersConfig::default_for_service(
|
||
&shared_types::ServiceType::ComputerAgentRunner,
|
||
);
|
||
assert!(!car_config.agent_servers.is_empty());
|
||
|
||
// 验证配置不同
|
||
// ComputerAgentRunner 应该有更多或不同的 context servers
|
||
assert!(car_config.context_servers.len() >= rcoder_config.context_servers.len());
|
||
}
|
||
}
|