1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use std::collections::BTreeSet;
use std::sync::Arc;
use crate::agent::core::budget::TokenBudget;
use crate::agent::core::composition::CompositionExecutor;
use crate::agent::core::storage::AttachmentReader;
use crate::agent::core::storage::Storage;
use crate::agent::core::tools::ToolSchema;
use crate::agent::metrics::MetricsCollector;
use crate::agent::skill::SkillManager;
use crate::agent::tools::ToolRegistry;
use crate::core::ReasoningEffort;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImageFallbackMode {
Placeholder,
Error,
Ocr,
/// Use a vision-capable LLM to describe the image, then replace the image
/// with the textual description so that text-only models can understand
/// the content.
Vision,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImageFallbackConfig {
pub mode: ImageFallbackMode,
/// Vision model name for `Vision` mode. Falls back to the session's main model
/// when `None`.
pub vision_model: Option<String>,
}
/// Configuration for the agent loop.
pub struct AgentLoopConfig {
pub max_rounds: usize,
pub system_prompt: Option<String>,
/// Skill IDs that are disabled globally for this execution.
pub disabled_skill_ids: BTreeSet<String>,
/// Optional explicit skill selection for this execution.
/// When set, only these skill IDs are considered for skill context and allowlists.
pub selected_skill_ids: Option<Vec<String>>,
/// Optional active skill mode for this execution.
///
/// When set, skill discovery prefers `skills-<mode>` directories over generic
/// directories for the same skill id.
pub selected_skill_mode: Option<String>,
pub additional_tool_schemas: Vec<ToolSchema>,
pub tool_registry: Arc<ToolRegistry>,
pub composition_executor: Option<Arc<CompositionExecutor>>,
pub skill_manager: Option<Arc<SkillManager>>,
/// If true, skip appending the initial user message (already present in session).
pub skip_initial_user_message: bool,
/// Optional storage for persisting session changes
pub storage: Option<Arc<dyn Storage>>,
/// Optional attachment reader for resolving `bamboo-attachment://...` references
/// into `data:` URLs for upstream providers. This must not mutate session storage.
pub attachment_reader: Option<Arc<dyn AttachmentReader>>,
/// Optional asynchronous metrics collector
pub metrics_collector: Option<MetricsCollector>,
/// Model name used for metrics attribution
pub model_name: Option<String>,
/// Optional explicit fast/cheap model name for lightweight foreground tasks
/// such as task evaluation.
///
/// Call sites may fall back to `model_name` when this is unset.
pub fast_model_name: Option<String>,
/// Dedicated background summarization model for host-side context compression
/// and other non-interactive maintenance work.
///
/// Unlike `fast_model_name`, this must not silently fall back to the main
/// interaction model.
pub background_model_name: Option<String>,
/// Provider name used for provider-specific request behavior.
pub provider_name: Option<String>,
/// Optional request-time reasoning effort override.
pub reasoning_effort: Option<ReasoningEffort>,
/// Tool names that should be excluded from schemas sent to the LLM.
pub disabled_tools: BTreeSet<String>,
/// Token budget for context management (optional, defaults to model's limits)
pub token_budget: Option<TokenBudget>,
/// Optional image fallback behavior applied to *LLM requests only* (never persisted).
///
/// This is intended for text-only provider paths where image parts must be degraded
/// (placeholder / OCR / error) without leaking into stored session history or UI.
pub image_fallback: Option<ImageFallbackConfig>,
}
impl Default for AgentLoopConfig {
fn default() -> Self {
Self {
max_rounds: 200,
system_prompt: None,
disabled_skill_ids: BTreeSet::new(),
selected_skill_ids: None,
selected_skill_mode: None,
additional_tool_schemas: Vec::new(),
tool_registry: Arc::new(ToolRegistry::new()),
composition_executor: None,
skill_manager: None,
skip_initial_user_message: false,
storage: None,
attachment_reader: None,
metrics_collector: None,
model_name: None,
fast_model_name: None,
background_model_name: None,
provider_name: None,
reasoning_effort: None,
disabled_tools: BTreeSet::new(),
token_budget: None,
image_fallback: None,
}
}
}
#[cfg(test)]
mod tests;