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 subagent_profiles = crate::subagent_profiles::load_registry(&bamboo_home_dir, None)
164 .map_err(|e| {
165 crate::error::AppError::InternalError(anyhow::anyhow!(
166 "failed to load subagent profile registry: {e}"
167 ))
168 })?;
169
170 let child_tools: Arc<dyn bamboo_agent_core::tools::ToolExecutor> =
175 Arc::new(crate::tools::PolicyAwareToolExecutor::new(
176 base_tools.clone(),
177 subagent_profiles.clone(),
178 sessions.clone(),
179 ));
180
181 let agent = Arc::new(
186 bamboo_engine::Agent::builder()
187 .storage(storage.clone())
188 .attachment_reader(session_store.clone())
189 .skill_manager(skill_manager.clone())
190 .metrics_collector(metrics_service.collector())
191 .config(config.clone())
192 .provider(provider_handle.clone())
193 .default_tools(base_tools.clone())
194 .build()
195 .expect("agent runtime should be fully configured"),
196 );
197
198 let child_completion_coordinator = Arc::new(
199 super::child_completion_coordinator::ChildCompletionCoordinator::new(
200 storage.clone(),
201 sessions.clone(),
202 agent_runners.clone(),
203 session_event_senders.clone(),
204 agent.clone(),
205 config.clone(),
206 provider_registry.clone(),
207 provider_router.clone(),
208 ),
209 );
210
211 let config_snapshot = config.read().await.clone();
213 let external_runner =
214 crate::external_agents::runtime::build_external_child_runner(&config_snapshot);
215 let spawn_scheduler = build_spawn_scheduler(
216 agent.clone(),
217 child_tools,
218 sessions.clone(),
219 agent_runners.clone(),
220 session_event_senders.clone(),
221 external_runner,
222 Some(provider_router.clone()),
223 Some(child_completion_coordinator.clone()),
224 );
225
226 let tools_with_task = base_tools.clone();
227
228 let schedule_store = init_schedule_store(&data_dir).await?;
229 let schedule_manager = build_schedule_manager(
230 schedule_store.clone(),
231 agent.clone(),
232 tools_with_task.clone(),
233 sessions.clone(),
234 agent_runners.clone(),
235 session_event_senders.clone(),
236 config.clone(),
237 );
238
239 crate::services::auto_dream::spawn_auto_dream_task(
240 crate::services::auto_dream::AutoDreamContext {
241 session_store: session_store.clone(),
242 storage: storage.clone(),
243 provider: provider_handle.clone(),
244 config: config.clone(),
245 provider_registry: provider_registry.clone(),
246 },
247 );
248
249 let config_for_resolver = config.clone();
250 let subagent_model_resolver: OptionalSubagentModelResolver = {
251 let registry = provider_registry.clone();
252 Some(Arc::new(
253 move |subagent_type: String| -> futures::future::BoxFuture<
254 'static,
255 Option<bamboo_domain::ProviderModelRef>,
256 > {
257 let config_for_resolver = config_for_resolver.clone();
258 let registry = registry.clone();
259 Box::pin(async move {
260 let config_snap = config_for_resolver.read().await.clone();
261 crate::model_config_helper::resolve_subagent_model_ref(
262 &config_snap,
263 &config_snap.provider,
264 ®istry,
265 &subagent_type,
266 )
267 })
268 },
269 ))
270 };
271
272 let tools = build_root_tools(
273 tools_with_task.clone(),
274 schedule_store.clone(),
275 schedule_manager.clone(),
276 session_store.clone(),
277 storage.clone(),
278 spawn_scheduler.clone(),
279 sessions.clone(),
280 agent_runners.clone(),
281 session_event_senders.clone(),
282 subagent_model_resolver,
283 config.clone(),
284 subagent_profiles.clone(),
285 );
286
287 child_completion_coordinator
288 .set_root_tools(tools.clone())
289 .await;
290
291 let tool_factory =
292 crate::tools::ToolSurfaceFactory::new(base_tools, tools_with_task, tools);
293
294 Ok(Self {
295 app_data_dir: bamboo_home_dir,
296 config,
297 provider: provider_lock,
298 provider_handle,
299 sessions,
300 storage,
301 session_store,
302 spawn_scheduler,
303 child_completion_coordinator,
304 schedule_store,
305 schedule_manager,
306 tool_factory,
307 subagent_profiles,
308 cancel_tokens: Arc::new(RwLock::new(HashMap::new())),
309 skill_manager,
310 mcp_manager,
311 metrics_service,
312 agent_runners,
313 session_event_senders,
314 process_registry,
315 metrics_bus: None, agent,
317 provider_registry,
318 provider_router,
319 model_catalog,
320 })
321 }
322}