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 config_snapshot = config.read().await.clone();
200 let external_runner =
201 crate::external_agents::runtime::build_external_child_runner(&config_snapshot);
202 let spawn_scheduler = build_spawn_scheduler(
203 agent.clone(),
204 child_tools,
205 sessions.clone(),
206 agent_runners.clone(),
207 session_event_senders.clone(),
208 external_runner,
209 Some(provider_router.clone()),
210 );
211
212 let tools_with_task = base_tools.clone();
213
214 let schedule_store = init_schedule_store(&data_dir).await?;
215 let schedule_manager = build_schedule_manager(
216 schedule_store.clone(),
217 agent.clone(),
218 tools_with_task.clone(),
219 sessions.clone(),
220 agent_runners.clone(),
221 session_event_senders.clone(),
222 config.clone(),
223 );
224
225 crate::services::auto_dream::spawn_auto_dream_task(
226 crate::services::auto_dream::AutoDreamContext {
227 session_store: session_store.clone(),
228 storage: storage.clone(),
229 provider: provider_handle.clone(),
230 config: config.clone(),
231 provider_registry: provider_registry.clone(),
232 },
233 );
234
235 let config_for_resolver = config.clone();
236 let subagent_model_resolver: OptionalSubagentModelResolver = {
237 let registry = provider_registry.clone();
238 Some(Arc::new(
239 move |subagent_type: String| -> futures::future::BoxFuture<
240 'static,
241 Option<bamboo_domain::ProviderModelRef>,
242 > {
243 let config_for_resolver = config_for_resolver.clone();
244 let registry = registry.clone();
245 Box::pin(async move {
246 let config_snap = config_for_resolver.read().await.clone();
247 crate::model_config_helper::resolve_subagent_model_ref(
248 &config_snap,
249 &config_snap.provider,
250 ®istry,
251 &subagent_type,
252 )
253 })
254 },
255 ))
256 };
257
258 let tools = build_root_tools(
259 tools_with_task.clone(),
260 schedule_store.clone(),
261 schedule_manager.clone(),
262 session_store.clone(),
263 storage.clone(),
264 spawn_scheduler.clone(),
265 sessions.clone(),
266 agent_runners.clone(),
267 session_event_senders.clone(),
268 subagent_model_resolver,
269 config.clone(),
270 subagent_profiles.clone(),
271 );
272
273 let tool_factory =
274 crate::tools::ToolSurfaceFactory::new(base_tools, tools_with_task, tools);
275
276 Ok(Self {
277 app_data_dir: bamboo_home_dir,
278 config,
279 provider: provider_lock,
280 provider_handle,
281 sessions,
282 storage,
283 session_store,
284 spawn_scheduler,
285 schedule_store,
286 schedule_manager,
287 tool_factory,
288 subagent_profiles,
289 cancel_tokens: Arc::new(RwLock::new(HashMap::new())),
290 skill_manager,
291 mcp_manager,
292 metrics_service,
293 agent_runners,
294 session_event_senders,
295 process_registry,
296 metrics_bus: None, agent,
298 provider_registry,
299 provider_router,
300 model_catalog,
301 })
302 }
303}