Skip to main content

saorsa_agent/
config.rs

1//! Agent configuration.
2
3use crate::context::ContextBundle;
4
5/// Configuration for the agent loop.
6#[derive(Clone, Debug)]
7pub struct AgentConfig {
8    /// The LLM model to use.
9    pub model: String,
10    /// The system prompt.
11    pub system_prompt: String,
12    /// Maximum number of agent turns before stopping.
13    pub max_turns: u32,
14    /// Maximum tokens per response.
15    pub max_tokens: u32,
16    /// Context bundle (AGENTS.md, SYSTEM.md, user context).
17    pub context: ContextBundle,
18}
19
20impl AgentConfig {
21    /// Create a new agent config with the given model.
22    pub fn new(model: impl Into<String>) -> Self {
23        Self {
24            model: model.into(),
25            system_prompt: "You are a helpful assistant.".into(),
26            max_turns: 10,
27            max_tokens: 4096,
28            context: ContextBundle::new(),
29        }
30    }
31
32    /// Set the system prompt.
33    #[must_use]
34    pub fn system_prompt(mut self, prompt: impl Into<String>) -> Self {
35        self.system_prompt = prompt.into();
36        self
37    }
38
39    /// Set the maximum number of turns.
40    #[must_use]
41    pub fn max_turns(mut self, max: u32) -> Self {
42        self.max_turns = max;
43        self
44    }
45
46    /// Set the maximum tokens per response.
47    #[must_use]
48    pub fn max_tokens(mut self, max: u32) -> Self {
49        self.max_tokens = max;
50        self
51    }
52
53    /// Set the context bundle.
54    #[must_use]
55    pub fn context(mut self, context: ContextBundle) -> Self {
56        self.context = context;
57        self
58    }
59}
60
61impl Default for AgentConfig {
62    fn default() -> Self {
63        Self::new("claude-sonnet-4-5-20250929")
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn default_config() {
73        let config = AgentConfig::default();
74        assert_eq!(config.model, "claude-sonnet-4-5-20250929");
75        assert_eq!(config.max_turns, 10);
76        assert_eq!(config.max_tokens, 4096);
77        assert!(!config.system_prompt.is_empty());
78    }
79
80    #[test]
81    fn builder_pattern() {
82        let config = AgentConfig::new("claude-opus-4-20250514")
83            .system_prompt("Be concise")
84            .max_turns(5)
85            .max_tokens(8192);
86        assert_eq!(config.model, "claude-opus-4-20250514");
87        assert_eq!(config.system_prompt, "Be concise");
88        assert_eq!(config.max_turns, 5);
89        assert_eq!(config.max_tokens, 8192);
90    }
91
92    #[test]
93    fn new_custom_model() {
94        let config = AgentConfig::new("gpt-4");
95        assert_eq!(config.model, "gpt-4");
96    }
97}