1use super::init::{
2 build_provider_handles, build_schedule_manager, build_spawn_scheduler, init_mcp_manager,
3 init_metrics_service, init_schedule_store, init_skill_manager, init_storage,
4 load_permission_checker, spawn_runner_cleanup_task,
5};
6use super::tools::{build_base_tools, build_root_tools};
7use super::*;
8use crate::tools::OptionalSubagentModelResolver;
9
10impl AppState {
11 pub async fn new(bamboo_home_dir: PathBuf) -> Result<Self, AppError> {
46 bamboo_infrastructure::paths::init_bamboo_dir(bamboo_home_dir.clone());
49
50 let config = Config::from_data_dir(Some(bamboo_home_dir.clone()));
52
53 let provider =
55 match bamboo_infrastructure::create_provider_with_dir(&config, bamboo_home_dir.clone())
56 .await
57 {
58 Ok(p) => p,
59 Err(e) => {
60 tracing::error!("Failed to create provider: {}.", e);
63 Arc::new(UnconfiguredProvider {
64 message: e.to_string(),
65 })
66 }
67 };
68
69 Self::new_with_provider(bamboo_home_dir, config, provider).await
70 }
71
72 pub async fn new_with_provider(
87 bamboo_home_dir: PathBuf,
88 config: Config,
89 provider: Arc<dyn LLMProvider>,
90 ) -> Result<Self, AppError> {
91 let data_dir = bamboo_home_dir.clone();
92 let (session_store, storage) = init_storage(&data_dir).await?;
93
94 let sessions: Arc<RwLock<HashMap<String, bamboo_agent_core::Session>>> =
96 Arc::new(RwLock::new(HashMap::new()));
97
98 let config = Arc::new(RwLock::new(config));
99
100 let permission_checker = load_permission_checker(&bamboo_home_dir).await;
101 let mcp_manager = init_mcp_manager(config.clone());
102 let skill_manager = init_skill_manager(&data_dir).await;
103 let metrics_service = init_metrics_service(&data_dir).await?;
104
105 let agent_runners: Arc<RwLock<HashMap<String, AgentRunner>>> =
106 Arc::new(RwLock::new(HashMap::new()));
107 spawn_runner_cleanup_task(agent_runners.clone(), None);
108
109 let process_registry = Arc::new(ProcessRegistry::new());
110 let (provider_lock, provider_handle) = build_provider_handles(provider);
111
112 let config_snapshot = config.read().await;
114 let provider_registry = match bamboo_infrastructure::ProviderRegistry::from_config(
115 &config_snapshot,
116 bamboo_home_dir.clone(),
117 )
118 .await
119 {
120 Ok(registry) => Arc::new(registry),
121 Err(e) => {
122 tracing::error!("Failed to create provider registry: {}", e);
123 Arc::new(
124 bamboo_infrastructure::ProviderRegistry::from_config(
125 &Config::default(),
126 bamboo_home_dir.clone(),
127 )
128 .await
129 .expect("Cannot create even an empty provider registry"),
130 )
131 }
132 };
133 drop(config_snapshot);
134
135 let provider_router = Arc::new(bamboo_infrastructure::ProviderModelRouter::new(
136 provider_registry.clone(),
137 ));
138 let model_catalog = Arc::new(bamboo_infrastructure::ModelCatalogService::new(
139 provider_registry.clone(),
140 ));
141
142 let base_tools = build_base_tools(
143 config.clone(),
144 permission_checker,
145 mcp_manager.clone(),
146 skill_manager.clone(),
147 storage.clone(),
148 sessions.clone(),
149 bamboo_home_dir.clone(),
150 );
151
152 let session_event_senders: Arc<RwLock<HashMap<String, broadcast::Sender<AgentEvent>>>> =
154 Arc::new(RwLock::new(HashMap::new()));
155
156 let child_tools: Arc<dyn bamboo_agent_core::tools::ToolExecutor> = base_tools.clone();
158
159 let agent = Arc::new(
164 bamboo_engine::Agent::builder()
165 .storage(storage.clone())
166 .attachment_reader(session_store.clone())
167 .skill_manager(skill_manager.clone())
168 .metrics_collector(metrics_service.collector())
169 .config(config.clone())
170 .provider(provider_handle.clone())
171 .default_tools(base_tools.clone())
172 .build()
173 .expect("agent runtime should be fully configured"),
174 );
175
176 let spawn_scheduler = build_spawn_scheduler(
178 agent.clone(),
179 child_tools,
180 sessions.clone(),
181 agent_runners.clone(),
182 session_event_senders.clone(),
183 );
184
185 let tools_with_task = base_tools.clone();
186
187 let schedule_store = init_schedule_store(&data_dir).await?;
188 let schedule_manager = build_schedule_manager(
189 schedule_store.clone(),
190 agent.clone(),
191 tools_with_task.clone(),
192 sessions.clone(),
193 agent_runners.clone(),
194 session_event_senders.clone(),
195 config.clone(),
196 );
197
198 crate::services::auto_dream::spawn_auto_dream_task(
199 crate::services::auto_dream::AutoDreamContext {
200 session_store: session_store.clone(),
201 storage: storage.clone(),
202 provider: provider_handle.clone(),
203 config: config.clone(),
204 provider_registry: provider_registry.clone(),
205 },
206 );
207
208 let config_for_resolver = config.clone();
209 let subagent_model_resolver: OptionalSubagentModelResolver = {
210 let config_snap = config.read().await.clone();
211 let registry = provider_registry.clone();
212 if config_snap.features.provider_model_ref && config_snap.defaults.is_some() {
213 Some(Arc::new(move |subagent_type: &str| -> Option<String> {
214 let config_snap = config_for_resolver.blocking_read().clone();
215 crate::model_config_helper::resolve_subagent_model(
216 &config_snap,
217 &config_snap.provider,
218 ®istry,
219 subagent_type,
220 )
221 .map(|m| m.model_name)
222 }))
223 } else {
224 None
225 }
226 };
227
228 let tools = build_root_tools(
229 tools_with_task.clone(),
230 schedule_store.clone(),
231 schedule_manager.clone(),
232 session_store.clone(),
233 storage.clone(),
234 spawn_scheduler.clone(),
235 sessions.clone(),
236 agent_runners.clone(),
237 session_event_senders.clone(),
238 subagent_model_resolver,
239 );
240
241 let tool_factory =
242 crate::tools::ToolSurfaceFactory::new(base_tools, tools_with_task, tools);
243
244 Ok(Self {
245 app_data_dir: bamboo_home_dir,
246 config,
247 provider: provider_lock,
248 provider_handle,
249 sessions,
250 storage,
251 session_store,
252 spawn_scheduler,
253 schedule_store,
254 schedule_manager,
255 tool_factory,
256 cancel_tokens: Arc::new(RwLock::new(HashMap::new())),
257 skill_manager,
258 mcp_manager,
259 metrics_service,
260 agent_runners,
261 session_event_senders,
262 process_registry,
263 metrics_bus: None, agent,
265 provider_registry,
266 provider_router,
267 model_catalog,
268 })
269 }
270}