mofa_foundation/
config.rs1use mofa_kernel::config::{from_str, load_config};
33use serde::{Deserialize, Serialize};
34use std::collections::HashMap;
35use std::path::Path;
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct AgentYamlConfig {
40 pub agent: AgentInfo,
42 #[serde(default)]
44 pub llm: Option<LLMYamlConfig>,
45 #[serde(default)]
47 pub tools: Option<Vec<ToolConfig>>,
48 #[serde(default)]
50 pub runtime: Option<RuntimeConfig>,
51 #[serde(default)]
53 pub inputs: Option<Vec<String>>,
54 #[serde(default)]
56 pub outputs: Option<Vec<String>>,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct AgentInfo {
62 pub id: String,
64 pub name: String,
66 #[serde(default)]
68 pub description: Option<String>,
69 #[serde(default)]
71 pub capabilities: Vec<String>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct LLMYamlConfig {
77 #[serde(default = "default_provider")]
79 pub provider: String,
80 #[serde(default)]
82 pub model: Option<String>,
83 #[serde(default)]
85 pub api_key: Option<String>,
86 #[serde(default)]
88 pub base_url: Option<String>,
89 #[serde(default)]
91 pub deployment: Option<String>,
92 #[serde(default)]
94 pub temperature: Option<f32>,
95 #[serde(default)]
97 pub max_tokens: Option<u32>,
98 #[serde(default)]
100 pub system_prompt: Option<String>,
101}
102
103fn default_provider() -> String {
104 "openai".to_string()
105}
106
107impl Default for LLMYamlConfig {
108 fn default() -> Self {
109 Self {
110 provider: "openai".to_string(),
111 model: None,
112 api_key: None,
113 base_url: None,
114 deployment: None,
115 temperature: Some(0.7),
116 max_tokens: Some(4096),
117 system_prompt: None,
118 }
119 }
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct ToolConfig {
125 pub name: String,
127 #[serde(default = "default_true")]
129 pub enabled: bool,
130 #[serde(default)]
132 pub config: HashMap<String, serde_json::Value>,
133}
134
135fn default_true() -> bool {
136 true
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct RuntimeConfig {
142 #[serde(default = "default_max_concurrent")]
144 pub max_concurrent_tasks: usize,
145 #[serde(default = "default_timeout")]
147 pub default_timeout_secs: u64,
148}
149
150fn default_max_concurrent() -> usize {
151 10
152}
153
154fn default_timeout() -> u64 {
155 30
156}
157
158impl Default for RuntimeConfig {
159 fn default() -> Self {
160 Self {
161 max_concurrent_tasks: 10,
162 default_timeout_secs: 30,
163 }
164 }
165}
166
167impl AgentYamlConfig {
168 pub fn from_file(path: impl AsRef<Path>) -> anyhow::Result<Self> {
170 let path_str = path.as_ref().to_string_lossy().to_string();
171 load_config(&path_str).map_err(|e| anyhow::anyhow!("Failed to load config: {}", e))
172 }
173
174 pub fn from_str_with_format(content: &str, format: &str) -> anyhow::Result<Self> {
176 use config::FileFormat;
177
178 let file_format = match format.to_lowercase().as_str() {
179 "yaml" | "yml" => FileFormat::Yaml,
180 "toml" => FileFormat::Toml,
181 "json" => FileFormat::Json,
182 "ini" => FileFormat::Ini,
183 "ron" => FileFormat::Ron,
184 "json5" => FileFormat::Json5,
185 _ => return Err(anyhow::anyhow!("Unsupported config format: {}", format)),
186 };
187
188 from_str(content, file_format).map_err(|e| anyhow::anyhow!("Failed to parse config: {}", e))
189 }
190
191 pub fn from_str(content: &str) -> anyhow::Result<Self> {
193 Self::from_str_with_format(content, "yaml")
194 }
195}