use super::types::{InboundMessage, OutboundMessage};
use crate::agent::AgentManager;
use crate::config::loader::ConfigLoader;
use anyhow::Result;
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct MessageRouter {
agent_manager: Arc<RwLock<AgentManager>>,
}
impl MessageRouter {
pub fn new(agent_manager: Arc<RwLock<AgentManager>>) -> Self {
Self { agent_manager }
}
pub async fn route(&self, message: InboundMessage) -> Result<OutboundMessage> {
let manager = self.agent_manager.read().await;
let agent_name = self.resolve_agent(&message).await;
let agent = match manager.get(&agent_name).await {
Some(agent) => agent,
None => {
tracing::info!("Auto-creating agent '{}'", agent_name);
drop(manager);
let manager = self.agent_manager.write().await;
let config = crate::agent::AgentConfig {
name: agent_name.clone(),
model: Arc::from("gpt-4"),
system_prompt: Arc::from("You are a helpful assistant."),
max_tokens: 4096,
memory_limit_mb: 512,
};
match manager.create(config).await {
Ok(_) => manager.get(&agent_name).await.unwrap(),
Err(e) => {
return Ok(OutboundMessage::error(format!("Failed to create agent: {}", e)));
}
}
}
};
match self.process_message(&agent, &message).await {
Ok(response) => Ok(OutboundMessage::ok(response)),
Err(e) => Ok(OutboundMessage::error(format!("Processing error: {}", e))),
}
}
async fn resolve_agent(&self, _message: &InboundMessage) -> Arc<str> {
let config = ConfigLoader::load().unwrap_or_default();
config.agents.list
.iter()
.find(|a| a.default)
.map(|a| a.name.clone())
.unwrap_or_else(|| Arc::from("default"))
}
async fn process_message(
&self,
agent: &crate::agent::AgentRuntime,
message: &InboundMessage,
) -> Result<String> {
let manager = self.agent_manager.read().await;
if let Some(provider) = manager.provider() {
agent.chat(&message.text, provider).await
} else {
Ok(format!(
"Agent '{}' received: {} (no LLM provider configured)",
agent.name(),
message.text
))
}
}
}
impl Default for MessageRouter {
fn default() -> Self {
let config = ConfigLoader::load().unwrap_or_default();
let manager = AgentManager::new(config.memory.max_concurrent_agents);
Self::new(Arc::new(RwLock::new(manager)))
}
}