ceylon_runtime/config/
mesh_config.rs1use super::AgentConfig;
4use crate::core::error::{Error, Result};
5use serde::{Deserialize, Serialize};
6use std::path::Path;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct MeshConfig {
31 pub name: String,
33
34 #[serde(default)]
36 pub agents: Vec<AgentConfig>,
37}
38
39impl Default for MeshConfig {
40 fn default() -> Self {
41 Self {
42 name: "mesh".to_string(),
43 agents: Vec::new(),
44 }
45 }
46}
47
48impl MeshConfig {
49 pub fn new(name: impl Into<String>) -> Self {
51 Self {
52 name: name.into(),
53 agents: Vec::new(),
54 }
55 }
56
57 pub fn from_toml(toml_str: &str) -> Result<Self> {
77 toml::from_str(toml_str)
78 .map_err(|e| Error::ConfigError(format!("Failed to parse TOML: {}", e)))
79 }
80
81 pub fn from_file(path: impl AsRef<Path>) -> Result<Self> {
91 let content = std::fs::read_to_string(path.as_ref()).map_err(|e| {
92 Error::ConfigError(format!(
93 "Failed to read file '{}': {}",
94 path.as_ref().display(),
95 e
96 ))
97 })?;
98 Self::from_toml(&content)
99 }
100
101 pub fn add_agent(mut self, agent: AgentConfig) -> Self {
103 self.agents.push(agent);
104 self
105 }
106
107 pub fn get_agent(&self, name: &str) -> Option<&AgentConfig> {
109 self.agents.iter().find(|a| a.name == name)
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn test_parse_mesh_config() {
119 let toml = r#"
120 name = "test_mesh"
121
122 [[agents]]
123 name = "agent1"
124 model = "ollama::llama2"
125 system_prompt = "First agent"
126
127 [[agents]]
128 name = "agent2"
129 model = "openai::gpt-4"
130 temperature = 0.8
131 "#;
132
133 let config = MeshConfig::from_toml(toml).unwrap();
134 assert_eq!(config.name, "test_mesh");
135 assert_eq!(config.agents.len(), 2);
136 assert_eq!(config.agents[0].name, "agent1");
137 assert_eq!(config.agents[1].name, "agent2");
138 assert_eq!(config.agents[1].temperature, Some(0.8));
139 }
140
141 #[test]
142 fn test_get_agent() {
143 let config = MeshConfig::new("test")
144 .add_agent(AgentConfig::new("agent1", "ollama::llama2"))
145 .add_agent(AgentConfig::new("agent2", "ollama::llama2"));
146
147 assert!(config.get_agent("agent1").is_some());
148 assert!(config.get_agent("agent2").is_some());
149 assert!(config.get_agent("nonexistent").is_none());
150 }
151
152 #[test]
153 fn test_empty_agents() {
154 let toml = r#"
155 name = "empty_mesh"
156 "#;
157
158 let config = MeshConfig::from_toml(toml).unwrap();
159 assert_eq!(config.name, "empty_mesh");
160 assert!(config.agents.is_empty());
161 }
162}