PicoBot/src/channels/manager.rs
xiaoski a051f83050 Refactor AgentLoop to manage history externally via SessionManager
- Removed internal history management from AgentLoop.
- Updated process method to accept conversation history as a parameter.
- Adjusted continue_with_tool_results to work with external history.
- Added OutboundDispatcher for handling outbound messages from MessageBus.
- Introduced InboundMessage and OutboundMessage structs for message handling.
- Updated Channel trait to include message handling and publishing to MessageBus.
- Refactored Session to manage chat histories instead of AgentLoop instances.
- Enhanced GatewayState to start message processing loops for inbound and outbound messages.
2026-04-07 21:53:37 +08:00

88 lines
3.1 KiB
Rust

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<RwLock<HashMap<String, Arc<dyn Channel + Send + Sync>>>>,
bus: Arc<MessageBus>,
}
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<MessageBus> {
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<Arc<dyn Channel + Send + Sync>> {
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)))
}
}
}