use std::sync::Arc; use crate::agent::{AgentError, AgentLoop, SkillProvider}; use crate::config::LLMProviderConfig; use crate::storage::{SessionStore, persistent_session_id}; use crate::tools::{ToolContext, ToolRegistry}; use super::skill_event_sink::PersistentSkillEventSink; #[derive(Clone)] pub(crate) struct AgentFactory { tools: Arc, skills: Arc, store: Arc, } pub(crate) struct AgentBuildRequest<'a> { pub(crate) channel_name: &'a str, pub(crate) chat_id: &'a str, pub(crate) sender_id: Option<&'a str>, pub(crate) message_id: Option<&'a str>, pub(crate) provider_config: LLMProviderConfig, } impl AgentFactory { pub(crate) fn new( tools: Arc, skills: Arc, store: Arc, ) -> Self { Self { tools, skills, store, } } pub(crate) fn create(&self, request: AgentBuildRequest<'_>) -> Result { let session_id = persistent_session_id(request.channel_name, request.chat_id); AgentLoop::with_tools_and_skill_provider( request.provider_config, self.tools.clone(), self.skills.clone(), ) .map(|agent| { let skill_event_sink = Arc::new(PersistentSkillEventSink::new( self.store.clone(), session_id.clone(), )); agent .with_skill_event_sink(skill_event_sink) .with_tool_context(ToolContext { channel_name: Some(request.channel_name.to_string()), sender_id: request.sender_id.map(str::to_string), chat_id: Some(request.chat_id.to_string()), session_id: Some(session_id), message_id: request.message_id.map(str::to_string), message_seq: None, }) }) } }