use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; use crate::bus::{MessageBus, OutboundMessage}; use crate::channels::base::{Channel, ChannelError}; use crate::channels::feishu::FeishuChannel; use crate::config::Config; /// ChannelManager manages all Channel instances and the MessageBus #[derive(Clone)] pub struct ChannelManager { channels: Arc>>>, bus: Arc, } impl ChannelManager { pub fn new() -> Self { Self { channels: Arc::new(RwLock::new(HashMap::new())), bus: MessageBus::new(100), } } /// Get a reference to the MessageBus pub fn bus(&self) -> Arc { self.bus.clone() } /// Initialize all Channel instances from config pub async fn init(&self, config: &Config, _provider_config: crate::config::LLMProviderConfig) -> Result<(), ChannelError> { // Initialize Feishu channel if enabled if let Some(feishu_config) = config.channels.get("feishu") { if feishu_config.enabled { let channel = FeishuChannel::new(feishu_config.clone(), _provider_config) .map_err(|e| ChannelError::Other(format!("Failed to create Feishu channel: {}", e)))?; self.channels .write() .await .insert("feishu".to_string(), Arc::new(channel)); tracing::info!("Feishu channel registered"); } else { tracing::info!("Feishu channel disabled in config"); } } Ok(()) } pub async fn start_all(&self) -> Result<(), ChannelError> { let channels = self.channels.read().await; let bus = self.bus.clone(); for (name, channel) in channels.iter() { tracing::info!(channel = %name, "Starting channel"); if let Err(e) = channel.start(bus.clone()).await { tracing::error!(channel = %name, error = %e, "Failed to start channel"); } } Ok(()) } pub async fn stop_all(&self) -> Result<(), ChannelError> { let mut channels = self.channels.write().await; for (name, channel) in channels.iter() { tracing::info!(channel = %name, "Stopping channel"); if let Err(e) = channel.stop().await { tracing::error!(channel = %name, error = %e, "Error stopping channel"); } } channels.clear(); Ok(()) } pub async fn get_channel(&self, name: &str) -> Option> { self.channels.read().await.get(name).cloned() } /// Dispatch an outbound message to the appropriate channel pub async fn dispatch(&self, msg: OutboundMessage) -> Result<(), ChannelError> { let channel_name = &msg.channel; if let Some(channel) = self.get_channel(channel_name).await { channel.send(msg).await } else { Err(ChannelError::Other(format!("Channel not found: {}", channel_name))) } } }