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::constants::QUICK_ACTION_MAX_TOKENS;
8use crate::event::AgentEvent;
9use crate::prompt::PromptProfile;
10use crate::providers::Provider;
11use crate::skills::Skill;
12use crate::tools::Tool;
13use crate::tools::toolproxy::{ProxyToolDef, ProxyToolExecutor};
14
15use super::types::{Agent, AgentBuilder};
16
17impl AgentBuilder {
18    pub fn new(provider: Box<dyn Provider>) -> Self {
19        Self {
20            provider,
21            model_name: "unknown".to_string(),
22            tools: Vec::new(),
23            system_prompt: "You are a helpful AI coding assistant.".to_string(),
24            max_tokens: QUICK_ACTION_MAX_TOKENS,
25            context_size_override: None,
26            think: false,
27            approve_mode: ApproveMode::Ask,
28            event_tx: None,
29            skills: Vec::new(),
30            profile: PromptProfile::Default,
31            project_overview: None,
32            memory_summary: None,
33            project_path: None,
34            proxy_tool_defs: Vec::new(),
35            proxy_executor: None,
36            mcp_registry: None,
37            pending_input_rx: None,
38        }
39    }
40
41    pub fn system_prompt(mut self, prompt: impl Into<String>) -> Self {
42        self.system_prompt = prompt.into();
43        self
44    }
45
46    pub fn model_name(mut self, name: impl Into<String>) -> Self {
47        self.model_name = name.into();
48        self
49    }
50
51    pub fn max_tokens(mut self, tokens: u32) -> Self {
52        self.max_tokens = tokens;
53        self
54    }
55
56    /// Override provider-inferred context window size.
57    pub fn context_size(mut self, context_size: Option<u32>) -> Self {
58        self.context_size_override = context_size;
59        self
60    }
61
62    pub fn think(mut self, enabled: bool) -> Self {
63        self.think = enabled;
64        self
65    }
66
67    pub fn approve_mode(mut self, mode: ApproveMode) -> Self {
68        self.approve_mode = mode;
69        self
70    }
71
72    pub fn tool(mut self, tool: Arc<dyn Tool>) -> Self {
73        self.tools.push(tool);
74        self
75    }
76
77    /// Add multiple tools
78    pub fn tools(mut self, tools: Vec<Box<dyn Tool>>) -> Self {
79        self.tools.extend(tools.into_iter().map(Arc::from));
80        self
81    }
82
83    /// Add multiple tools with provider support
84    pub fn tools_with_provider(mut self, tools: Vec<Box<dyn Tool>>) -> Self {
85        self.tools.extend(tools.into_iter().map(Arc::from));
86        self
87    }
88
89    /// Set external event sender for streaming events
90    pub fn event_tx(mut self, tx: tokio::sync::mpsc::Sender<AgentEvent>) -> Self {
91        self.event_tx = Some(tx);
92        self
93    }
94
95    /// Add skills
96    pub fn skills(mut self, skills: Vec<Skill>) -> Self {
97        self.skills = skills;
98        self
99    }
100
101    /// Set prompt profile
102    pub fn profile(mut self, profile: PromptProfile) -> Self {
103        self.profile = profile;
104        self
105    }
106
107    /// Set project overview
108    pub fn overview(mut self, overview: impl Into<String>) -> Self {
109        self.project_overview = Some(overview.into());
110        self
111    }
112
113    /// Set memory summary
114    pub fn memory(mut self, summary: impl Into<String>) -> Self {
115        self.memory_summary = Some(summary.into());
116        self
117    }
118
119    /// Set project path (for dynamic tool injection like CodeGraph)
120    pub fn project_path(mut self, path: PathBuf) -> Self {
121        self.project_path = Some(path);
122        self
123    }
124
125    /// 设置代理工具执行器
126    ///
127    /// # Example
128    /// ```ignore
129    /// use std::sync::Arc;
130    /// use serde_json::json;
131    /// use matrixcode_core::tools::toolproxy::{ProxyToolExecutor, ProxyToolDef};
132    ///
133    /// let executor = Arc::new(MyProxyExecutor);
134    /// let tool_def = ProxyToolDef::new("image_search", "搜索图片", json!({...}))
135    ///     .with_priority(true);
136    ///
137    /// builder.proxy_executor(executor, vec![tool_def])
138    /// ```
139    pub fn proxy_executor(
140        mut self,
141        executor: Arc<dyn ProxyToolExecutor>,
142        tool_defs: Vec<ProxyToolDef>,
143    ) -> Self {
144        self.proxy_executor = Some(executor);
145        self.proxy_tool_defs = tool_defs;
146        self
147    }
148
149    pub fn build(self) -> Agent {
150        Agent::new(self)
151    }
152
153    /// 设置 MCP 工具注册表
154    ///
155    /// # Example
156    /// ```ignore
157    /// use std::sync::Arc;
158    /// use matrixcode_core::mcp::McpToolRegistry;
159    ///
160    /// let registry = Arc::new(tokio::sync::RwLock::new(McpToolRegistry::new()));
161    /// builder.mcp_registry(registry)
162    /// ```
163    pub fn mcp_registry(
164        mut self,
165        registry: Arc<tokio::sync::RwLock<crate::mcp::McpToolRegistry>>,
166    ) -> Self {
167        self.mcp_registry = Some(registry);
168        self
169    }
170
171    /// 设置实时追加消息接收器
172    ///
173    /// 允许在 Agent 处理过程中接收新消息,实现实时追加功能。
174    ///
175    /// # Example
176    /// ```ignore
177    /// let (pending_tx, pending_rx) = tokio::sync::mpsc::channel::<String>(100);
178    /// builder.pending_input_rx(pending_rx)
179    /// ```
180    pub fn pending_input_rx(mut self, rx: tokio::sync::mpsc::Receiver<String>) -> Self {
181        self.pending_input_rx = Some(rx);
182        self
183    }
184}