Skip to main content

matrixcode_core/agent/
builder.rs

1//! Agent builder implementation.
2
3use std::path::PathBuf;
4use std::sync::Arc;
5
6use crate::approval::ApproveMode;
7use crate::compress::CompressionConfig;
8use crate::constants::QUICK_ACTION_MAX_TOKENS;
9use crate::event::AgentEvent;
10use crate::prompt::PromptProfile;
11use crate::providers::Provider;
12use crate::skills::Skill;
13use crate::tools::Tool;
14use crate::tools::toolproxy::{ProxyToolDef, ProxyToolExecutor};
15
16use super::types::{Agent, AgentBuilder};
17
18impl AgentBuilder {
19    pub fn new(provider: Box<dyn Provider>) -> Self {
20        Self {
21            provider,
22            model_name: "unknown".to_string(),
23            tools: Vec::new(),
24            max_tokens: QUICK_ACTION_MAX_TOKENS,
25            context_size_override: None,
26            think: false,
27            compression_config: CompressionConfig::default(),
28            profile: PromptProfile::Default,
29            skills: Vec::new(),
30            project_overview: None,
31            memory_summary: None,
32            project_path: None,
33            event_tx: None,
34            pending_input_rx: None,
35            approve_mode: ApproveMode::Ask,
36            proxy_tool_defs: Vec::new(),
37            proxy_executor: None,
38            mcp_registry: None,
39            lsp_registry: None,
40        }
41    }
42
43    pub fn model_name(mut self, name: impl Into<String>) -> Self {
44        self.model_name = name.into();
45        self
46    }
47
48    pub fn max_tokens(mut self, tokens: u32) -> Self {
49        self.max_tokens = tokens;
50        self
51    }
52
53    /// Override provider-inferred context window size.
54    pub fn context_size(mut self, context_size: Option<u32>) -> Self {
55        self.context_size_override = context_size;
56        self
57    }
58
59    /// Set compression config
60    pub fn compression_config(mut self, config: CompressionConfig) -> Self {
61        self.compression_config = config;
62        self
63    }
64
65    pub fn think(mut self, enabled: bool) -> Self {
66        self.think = enabled;
67        self
68    }
69
70    pub fn approve_mode(mut self, mode: ApproveMode) -> Self {
71        self.approve_mode = mode;
72        self
73    }
74
75    pub fn tool(mut self, tool: Arc<dyn Tool>) -> Self {
76        self.tools.push(tool);
77        self
78    }
79
80    /// Add multiple tools
81    pub fn tools(mut self, tools: Vec<Box<dyn Tool>>) -> Self {
82        self.tools.extend(tools.into_iter().map(Arc::from));
83        self
84    }
85
86    /// Add multiple tools with provider support
87    pub fn tools_with_provider(mut self, tools: Vec<Box<dyn Tool>>) -> Self {
88        self.tools.extend(tools.into_iter().map(Arc::from));
89        self
90    }
91
92    /// Set external event sender for streaming events
93    pub fn event_tx(mut self, tx: tokio::sync::mpsc::Sender<AgentEvent>) -> Self {
94        self.event_tx = Some(tx);
95        self
96    }
97
98    /// Add skills
99    pub fn skills(mut self, skills: Vec<Skill>) -> Self {
100        self.skills = skills;
101        self
102    }
103
104    /// Set prompt profile
105    pub fn profile(mut self, profile: PromptProfile) -> Self {
106        self.profile = profile;
107        self
108    }
109
110    /// Set project overview
111    pub fn overview(mut self, overview: impl Into<String>) -> Self {
112        self.project_overview = Some(overview.into());
113        self
114    }
115
116    /// Set memory summary
117    pub fn memory(mut self, summary: impl Into<String>) -> Self {
118        self.memory_summary = Some(summary.into());
119        self
120    }
121
122    /// Set system prompt directly (overrides auto-generated prompt).
123    /// Use with caution - this bypasses the normal prompt building process.
124    pub fn system_prompt(mut self, prompt: String) -> Self {
125        // Store as project_overview to be used in prompt building
126        // This is a workaround since system_prompt is built from context
127        self.project_overview = Some(prompt);
128        self
129    }
130
131    /// Set project path (for dynamic tool injection like CodeGraph)
132    pub fn project_path(mut self, path: PathBuf) -> Self {
133        self.project_path = Some(path);
134        self
135    }
136
137    /// 设置代理工具执行器
138    ///
139    /// # Example
140    /// ```ignore
141    /// use std::sync::Arc;
142    /// use serde_json::json;
143    /// use matrixcode_core::tools::toolproxy::{ProxyToolExecutor, ProxyToolDef};
144    ///
145    /// let executor = Arc::new(MyProxyExecutor);
146    /// let tool_def = ProxyToolDef::new("image_search", "搜索图片", json!({...}))
147    ///     .with_priority(true);
148    ///
149    /// builder.proxy_executor(executor, vec![tool_def])
150    /// ```
151    pub fn proxy_executor(
152        mut self,
153        executor: Arc<dyn ProxyToolExecutor>,
154        tool_defs: Vec<ProxyToolDef>,
155    ) -> Self {
156        self.proxy_executor = Some(executor);
157        self.proxy_tool_defs = tool_defs;
158        self
159    }
160
161    pub fn build(self) -> Agent {
162        Agent::new(self)
163    }
164
165    /// 设置 MCP 工具注册表
166    ///
167    /// # Example
168    /// ```ignore
169    /// use std::sync::Arc;
170    /// use matrixcode_core::mcp::McpToolRegistry;
171    ///
172    /// let registry = Arc::new(tokio::sync::RwLock::new(McpToolRegistry::new()));
173    /// builder.mcp_registry(registry)
174    /// ```
175    pub fn mcp_registry(
176        mut self,
177        registry: Arc<tokio::sync::RwLock<crate::mcp::McpToolRegistry>>,
178    ) -> Self {
179        self.mcp_registry = Some(registry);
180        self
181    }
182
183    /// 设置 LSP 客户端注册表
184    ///
185    /// # Example
186    /// ```ignore
187    /// use std::sync::Arc;
188    /// use matrixcode_core::lsp::LspClientRegistry;
189    ///
190    /// let registry = Arc::new(LspClientRegistry::new());
191    /// // 启动 LSP 服务器
192    /// registry.register(&config, &project_root).await?;
193    /// builder.lsp_registry(registry)
194    /// ```
195    pub fn lsp_registry(mut self, registry: Arc<crate::lsp::LspClientRegistry>) -> Self {
196        self.lsp_registry = Some(registry);
197        self
198    }
199
200    /// 设置实时追加消息接收器
201    ///
202    /// 允许在 Agent 处理过程中接收新消息,实现实时追加功能。
203    ///
204    /// # Example
205    /// ```ignore
206    /// let (pending_tx, pending_rx) = tokio::sync::mpsc::channel::<String>(100);
207    /// builder.pending_input_rx(pending_rx)
208    /// ```
209    pub fn pending_input_rx(mut self, rx: tokio::sync::mpsc::Receiver<String>) -> Self {
210        self.pending_input_rx = Some(rx);
211        self
212    }
213}