use super::memory::{AgentMemoryManager, MemoryConfig};
use super::{Agent, AgentConfig, ConversationMode, ToolExecutor};
use crate::error::RragResult;
#[cfg(feature = "rexis-llm-client")]
use rexis_llm::tools::{Tool, ToolRegistry};
#[cfg(feature = "rexis-llm-client")]
use rexis_llm::Client;
pub struct AgentBuilder {
llm_client: Option<Client>,
tools: Vec<Box<dyn Tool>>,
config: AgentConfig,
memory_config: Option<MemoryConfig>,
}
impl AgentBuilder {
pub fn new() -> Self {
Self {
llm_client: None,
tools: Vec::new(),
config: AgentConfig::default(),
memory_config: None,
}
}
pub fn with_llm(mut self, client: Client) -> Self {
self.llm_client = Some(client);
self
}
pub fn with_tool(mut self, tool: Box<dyn Tool>) -> Self {
self.tools.push(tool);
self
}
pub fn with_tools(mut self, tools: Vec<Box<dyn Tool>>) -> Self {
self.tools.extend(tools);
self
}
pub fn with_system_prompt(mut self, prompt: impl Into<String>) -> Self {
self.config.system_prompt = prompt.into();
self
}
pub fn with_max_iterations(mut self, max: usize) -> Self {
self.config.max_iterations = max;
self
}
pub fn verbose(mut self, verbose: bool) -> Self {
self.config.verbose = verbose;
self
}
pub fn with_conversation_mode(mut self, mode: ConversationMode) -> Self {
self.config.conversation_mode = mode;
self
}
pub fn stateful(mut self) -> Self {
self.config.conversation_mode = ConversationMode::Stateful;
self
}
pub fn stateless(mut self) -> Self {
self.config.conversation_mode = ConversationMode::Stateless;
self
}
pub fn with_max_conversation_length(mut self, length: usize) -> Self {
self.config.max_conversation_length = length;
self
}
pub fn with_memory(mut self, memory_config: MemoryConfig) -> Self {
self.memory_config = Some(memory_config);
self
}
pub fn build(self) -> RragResult<Agent> {
let llm_client = self
.llm_client
.ok_or_else(|| crate::error::RragError::Agent {
agent_id: "builder".to_string(),
message: "LLM client is required. Use with_llm()".to_string(),
source: None,
})?;
let mut registry = ToolRegistry::new();
for tool in self.tools {
registry
.register(tool)
.map_err(|e| crate::error::RragError::Agent {
agent_id: "builder".to_string(),
message: format!("Failed to register tool: {}", e),
source: Some(Box::new(e)),
})?;
}
let tool_executor = ToolExecutor::new(registry);
if let Some(memory_config) = self.memory_config {
let memory_manager = AgentMemoryManager::new(memory_config);
Agent::new_with_memory(llm_client, tool_executor, memory_manager, self.config)
} else {
Agent::new(llm_client, tool_executor, self.config)
}
}
}
impl Default for AgentBuilder {
fn default() -> Self {
Self::new()
}
}