Skip to main content

bamboo_engine/runtime/
config.rs

1use std::collections::BTreeSet;
2use std::sync::Arc;
3
4use crate::metrics::MetricsCollector;
5use crate::skills::SkillManager;
6use bamboo_agent_core::composition::CompositionExecutor;
7use bamboo_agent_core::storage::AttachmentReader;
8use bamboo_agent_core::storage::Storage;
9use bamboo_agent_core::tools::ToolSchema;
10use bamboo_compression::TokenBudget;
11use bamboo_domain::ReasoningEffort;
12use bamboo_infrastructure::config::PermissionMode;
13use bamboo_infrastructure::LLMProvider;
14use bamboo_infrastructure::MemoryConfig;
15use bamboo_tools::ToolRegistry;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum ImageFallbackMode {
19    Placeholder,
20    Error,
21    Ocr,
22    /// Use a vision-capable LLM to describe the image, then replace the image
23    /// with the textual description so that text-only models can understand
24    /// the content.
25    Vision,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct ImageFallbackConfig {
30    pub mode: ImageFallbackMode,
31    /// Vision model name for `Vision` mode. Falls back to the session's main model
32    /// when `None`.
33    pub vision_model: Option<String>,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub struct PromptMemoryFlags {
38    pub project_prompt_injection: bool,
39    pub relevant_recall: bool,
40    pub relevant_recall_rerank: bool,
41    pub project_first_dream: bool,
42}
43
44impl Default for PromptMemoryFlags {
45    fn default() -> Self {
46        Self {
47            project_prompt_injection: true,
48            relevant_recall: true,
49            relevant_recall_rerank: false,
50            project_first_dream: true,
51        }
52    }
53}
54
55impl From<&MemoryConfig> for PromptMemoryFlags {
56    fn from(value: &MemoryConfig) -> Self {
57        Self {
58            project_prompt_injection: value.project_prompt_injection,
59            relevant_recall: value.relevant_recall,
60            relevant_recall_rerank: value.relevant_recall_rerank,
61            project_first_dream: value.project_first_dream,
62        }
63    }
64}
65
66/// Configuration for the agent loop.
67pub struct AgentLoopConfig {
68    pub max_rounds: usize,
69    pub system_prompt: Option<String>,
70    /// Skill IDs that are disabled globally for this execution.
71    pub disabled_skill_ids: BTreeSet<String>,
72    /// Optional explicit skill selection for this execution.
73    /// When set, only these skill IDs are considered for skill context and allowlists.
74    pub selected_skill_ids: Option<Vec<String>>,
75    /// Optional active skill mode for this execution.
76    ///
77    /// When set, skill discovery prefers `skills-<mode>` directories over generic
78    /// directories for the same skill id.
79    pub selected_skill_mode: Option<String>,
80    pub additional_tool_schemas: Vec<ToolSchema>,
81    pub tool_registry: Arc<ToolRegistry>,
82    pub composition_executor: Option<Arc<CompositionExecutor>>,
83    pub skill_manager: Option<Arc<SkillManager>>,
84    /// If true, skip appending the initial user message (already present in session).
85    pub skip_initial_user_message: bool,
86    /// Optional storage for persisting session changes
87    pub storage: Option<Arc<dyn Storage>>,
88    /// Optional attachment reader for resolving `bamboo-attachment://...` references
89    /// into `data:` URLs for upstream providers. This must not mutate session storage.
90    pub attachment_reader: Option<Arc<dyn AttachmentReader>>,
91    /// Optional asynchronous metrics collector
92    pub metrics_collector: Option<MetricsCollector>,
93    /// Model name used for metrics attribution
94    pub model_name: Option<String>,
95    /// Optional explicit fast/cheap model name for lightweight foreground tasks
96    /// such as task evaluation.
97    ///
98    /// Call sites may fall back to `model_name` when this is unset.
99    pub fast_model_name: Option<String>,
100    /// Dedicated background summarization model for host-side context compression
101    /// and other non-interactive maintenance work.
102    ///
103    /// Unlike `fast_model_name`, this must not silently fall back to the main
104    /// interaction model.
105    pub background_model_name: Option<String>,
106    /// Model for planning/coordination tasks (task decomposition, architecture).
107    /// Falls back to `model_name` when unset.
108    pub planning_model_name: Option<String>,
109    /// Model for search/navigation tasks (grep, file listing, symbol resolution).
110    /// Falls back to `fast_model_name` when unset.
111    pub search_model_name: Option<String>,
112    /// Custom instructions for conversation summarization, injected into the
113    /// LLM summary prompt. Lets users control what the summary focuses on.
114    ///
115    /// Resolution order: session-level > config-level > built-in defaults.
116    pub compression_instructions: Option<String>,
117    /// Dedicated model for summarization. Falls back to `background_model_name`.
118    pub summarization_model_name: Option<String>,
119    /// Optional provider override for background/fast model LLM calls.
120    ///
121    /// When set, context compression, summarization, and other background
122    /// model calls use this provider instead of the shared agent loop provider.
123    pub background_model_provider: Option<Arc<dyn LLMProvider>>,
124    /// Provider name used for provider-specific request behavior.
125    pub provider_name: Option<String>,
126    /// Optional request-time reasoning effort override.
127    pub reasoning_effort: Option<ReasoningEffort>,
128    /// Tool names that should be excluded from schemas sent to the LLM.
129    pub disabled_tools: BTreeSet<String>,
130    /// Token budget for context management (optional, defaults to model's limits)
131    pub token_budget: Option<TokenBudget>,
132    /// Optional image fallback behavior applied to *LLM requests only* (never persisted).
133    ///
134    /// This is intended for text-only provider paths where image parts must be degraded
135    /// (placeholder / OCR / error) without leaking into stored session history or UI.
136    pub image_fallback: Option<ImageFallbackConfig>,
137    /// Feature flags controlling prompt-time memory injection behavior.
138    pub prompt_memory_flags: PromptMemoryFlags,
139    /// Maximum tool calls allowed per round (default: 80).
140    pub max_tool_calls_per_round: usize,
141    /// Maximum consecutive failures per tool before circuit breaker (default: 3).
142    pub max_consecutive_failures_per_tool: usize,
143    /// Tool names that require strict argument validation.
144    pub strict_argument_tool_names: Vec<String>,
145    /// Per-tool execution timeout in seconds (default: 120).
146    pub per_tool_timeout_secs: u64,
147    /// Parallel batch execution timeout in seconds (default: 300).
148    pub parallel_batch_timeout_secs: u64,
149    /// Permission mode for this execution (default: None = use PermissionConfig's mode).
150    pub permission_mode: Option<PermissionMode>,
151    /// Enable dynamic per-round model routing based on task complexity.
152    /// When true, the pipeline classifies complexity at each round end and
153    /// stores the result in session metadata.
154    pub features_dynamic_model_routing: bool,
155}
156
157impl Default for AgentLoopConfig {
158    fn default() -> Self {
159        Self {
160            max_rounds: 200,
161            system_prompt: None,
162            disabled_skill_ids: BTreeSet::new(),
163            selected_skill_ids: None,
164            selected_skill_mode: None,
165            additional_tool_schemas: Vec::new(),
166            tool_registry: Arc::new(ToolRegistry::new()),
167            composition_executor: None,
168            skill_manager: None,
169            skip_initial_user_message: false,
170            storage: None,
171            attachment_reader: None,
172            metrics_collector: None,
173            model_name: None,
174            fast_model_name: None,
175            background_model_name: None,
176            planning_model_name: None,
177            search_model_name: None,
178            compression_instructions: None,
179            summarization_model_name: None,
180            background_model_provider: None,
181            provider_name: None,
182            reasoning_effort: None,
183            disabled_tools: BTreeSet::new(),
184            token_budget: None,
185            image_fallback: None,
186            prompt_memory_flags: PromptMemoryFlags::default(),
187            max_tool_calls_per_round: 80,
188            max_consecutive_failures_per_tool: 3,
189            strict_argument_tool_names: vec![
190                "Write".into(),
191                "Edit".into(),
192                "NotebookEdit".into(),
193                "apply_patch".into(),
194                "Bash".into(),
195                "Task".into(),
196                "SubSession".into(),
197                "scheduler".into(),
198                "sub_session_manager".into(),
199                "session_note".into(),
200                "memory_note".into(),
201            ],
202            per_tool_timeout_secs: 120,
203            parallel_batch_timeout_secs: 300,
204            permission_mode: None,
205            features_dynamic_model_routing: false,
206        }
207    }
208}
209
210#[cfg(test)]
211mod tests;