praxis_graph/
builder.rs

1use std::sync::Arc;
2use anyhow::{Result, anyhow};
3
4use praxis_llm::LLMClient;
5use praxis_mcp::MCPToolExecutor;
6use crate::types::GraphConfig;
7
8use crate::graph::Graph;
9
10/// Configuration for optional persistence
11pub struct PersistenceConfig {
12    pub client: Arc<dyn praxis_persist::PersistenceClient>,
13}
14
15/// Configuration for optional observability
16#[cfg(feature = "observability")]
17pub struct ObserverConfig {
18    pub observer: Arc<dyn praxis_observability::Observer>,
19}
20
21/// Builder for constructing a Graph with optional components
22pub struct GraphBuilder {
23    llm_client: Option<Arc<dyn LLMClient>>,
24    reasoning_client: Option<Arc<dyn praxis_llm::ReasoningClient>>,
25    mcp_executor: Option<Arc<MCPToolExecutor>>,
26    config: GraphConfig,
27    persistence_config: Option<PersistenceConfig>,
28    #[cfg(feature = "observability")]
29    observer_config: Option<ObserverConfig>,
30}
31
32impl GraphBuilder {
33    pub fn new() -> Self {
34        Self {
35            llm_client: None,
36            reasoning_client: None,
37            mcp_executor: None,
38            config: GraphConfig::default(),
39            persistence_config: None,
40            #[cfg(feature = "observability")]
41            observer_config: None,
42        }
43    }
44    
45    /// Set the LLM client
46    pub fn llm_client(mut self, client: Arc<dyn LLMClient>) -> Self {
47        self.llm_client = Some(client);
48        self
49    }
50    
51    /// Set the Reasoning client (for gpt-5, o1 models)
52    pub fn reasoning_client(mut self, client: Arc<dyn praxis_llm::ReasoningClient>) -> Self {
53        self.reasoning_client = Some(client);
54        self
55    }
56    
57    /// Set the MCP tool executor
58    pub fn mcp_executor(mut self, executor: Arc<MCPToolExecutor>) -> Self {
59        self.mcp_executor = Some(executor);
60        self
61    }
62    
63    /// Set the graph configuration
64    pub fn config(mut self, config: GraphConfig) -> Self {
65        self.config = config;
66        self
67    }
68    
69    /// Enable persistence with a PersistenceClient
70    pub fn with_persistence(mut self, client: Arc<dyn praxis_persist::PersistenceClient>) -> Self {
71        self.persistence_config = Some(PersistenceConfig { client });
72        self
73    }
74    
75    /// Enable observability with an Observer
76    #[cfg(feature = "observability")]
77    pub fn with_observer(mut self, observer: Arc<dyn praxis_observability::Observer>) -> Self {
78        self.observer_config = Some(ObserverConfig { observer });
79        self
80    }
81    
82    /// Build the Graph
83    pub fn build(self) -> Result<Graph> {
84        let llm_client = self.llm_client
85            .ok_or_else(|| anyhow!("LLM client is required"))?;
86        let mcp_executor = self.mcp_executor
87            .ok_or_else(|| anyhow!("MCP executor is required"))?;
88        
89        Ok(Graph::new_with_config(
90            llm_client,
91            self.reasoning_client,
92            mcp_executor,
93            self.config,
94            self.persistence_config,
95            #[cfg(feature = "observability")]
96            self.observer_config,
97        ))
98    }
99}
100
101impl Default for GraphBuilder {
102    fn default() -> Self {
103        Self::new()
104    }
105}
106