use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use async_trait::async_trait;
use tokio::sync::{broadcast, RwLock};
use tokio_util::sync::CancellationToken;
use crate::error::AppError;
use crate::schedule_app::{ScheduleManager, ScheduleStore};
use bamboo_agent_core::storage::Storage;
use bamboo_agent_core::AgentEvent;
use bamboo_agent_core::{tools::ToolSchema, Message};
use bamboo_engine::execution::spawn::SpawnScheduler;
use bamboo_infrastructure::process::registry::ProcessRegistry;
use bamboo_llm::Config;
use bamboo_llm::{LLMError, LLMProvider, LLMStream};
use bamboo_mcp::manager::McpServerManager;
use bamboo_metrics::metrics_service::MetricsService;
use bamboo_skills::SkillManager;
use bamboo_storage::LockedSessionStore;
use bamboo_storage::SessionStoreV2;
pub use bamboo_engine::context::{
build_env_prompt_context, build_workspace_prompt_context, workspace_prompt_guidance,
DEFAULT_BASE_PROMPT, ENV_CONTEXT_END_MARKER, ENV_CONTEXT_START_MARKER,
WORKSPACE_CONTEXT_END_MARKER, WORKSPACE_CONTEXT_PREFIX, WORKSPACE_CONTEXT_START_MARKER,
};
struct UnconfiguredProvider {
message: String,
}
#[async_trait]
impl LLMProvider for UnconfiguredProvider {
async fn chat_stream(
&self,
_messages: &[Message],
_tools: &[ToolSchema],
_max_output_tokens: Option<u32>,
_model: &str,
) -> bamboo_llm::provider::Result<LLMStream> {
Err(LLMError::Auth(format!(
"LLM provider is not configured: {}",
self.message
)))
}
async fn list_models(&self) -> bamboo_llm::provider::Result<Vec<String>> {
Err(LLMError::Auth(format!(
"LLM provider is not configured: {}",
self.message
)))
}
}
pub use bamboo_engine::execution::runner_state::{AgentRunner, AgentStatus};
pub struct AppState {
pub app_data_dir: PathBuf,
pub config: Arc<RwLock<Config>>,
pub config_io_lock: Arc<tokio::sync::Mutex<()>>,
pub fabric_deployer: Arc<bamboo_server_tools::FabricDeployer>,
#[allow(dead_code)]
embedded_broker: Option<builder::EmbeddedBroker>,
#[allow(dead_code)]
health_monitor: Option<builder::HealthMonitor>,
pub provider: Arc<RwLock<Arc<dyn LLMProvider>>>,
provider_handle: Arc<dyn LLMProvider>,
pub sessions: bamboo_engine::SessionCache,
pub storage: Arc<dyn Storage>,
pub session_store: Arc<SessionStoreV2>,
pub persistence: Arc<LockedSessionStore>,
pub session_repo: bamboo_engine::SessionRepository,
pub spawn_scheduler: Arc<SpawnScheduler>,
pub child_completion_coordinator: Arc<bamboo_engine::ChildCompletionCoordinator>,
pub guardian_spawner: Arc<dyn bamboo_engine::GuardianSpawner>,
pub bash_resume_hook: Arc<dyn bamboo_engine::BashResumeHook>,
pub schedule_store: Arc<ScheduleStore>,
pub schedule_manager: Arc<ScheduleManager>,
pub tool_factory: crate::tools::ToolSurfaceFactory,
pub permission_checker: Arc<dyn bamboo_tools::permission::PermissionChecker>,
pub notification_service: Arc<bamboo_notification::NotificationService>,
pub session_watchers: Arc<watchers::SessionWatchers>,
pub cancel_tokens: Arc<RwLock<HashMap<String, CancellationToken>>>,
pub mcp_proxy_shutdown: CancellationToken,
pub skill_manager: Arc<SkillManager>,
pub mcp_manager: Arc<McpServerManager>,
pub metrics_service: Arc<MetricsService>,
pub agent_runners: Arc<RwLock<HashMap<String, AgentRunner>>>,
pub session_event_senders: Arc<RwLock<HashMap<String, broadcast::Sender<AgentEvent>>>>,
pub account_sink: Arc<bamboo_engine::events::AccountEventSink>,
pub process_registry: Arc<ProcessRegistry>,
pub metrics_bus: Option<bamboo_metrics::bus::MetricsBus>,
pub agent: Arc<bamboo_engine::Agent>,
pub provider_registry: Arc<bamboo_llm::ProviderRegistry>,
pub provider_router: Arc<bamboo_llm::ProviderModelRouter>,
pub model_catalog: Arc<bamboo_llm::ModelCatalogService>,
pub title_gen_in_flight: Arc<dashmap::DashSet<String>>,
pub pairing_codes: Arc<dashmap::DashMap<String, crate::handlers::settings::PairingCodeEntry>>,
pub pairing_code_guard: Arc<crate::handlers::settings::PairingCodeGuard>,
pub root_password_guard: Arc<crate::handlers::settings::RootPasswordGuard>,
}
impl AppState {
pub fn title_gen_acquire(&self, session_id: &str) -> bool {
self.title_gen_in_flight.insert(session_id.to_string())
}
pub fn title_gen_release(&self, session_id: &str) {
self.title_gen_in_flight.remove(session_id);
}
}
mod agent_session_context;
mod builder;
mod config_runtime;
pub mod init;
mod persistence;
mod provider_api;
pub mod resume_adapter;
pub mod runner_lifecycle;
pub mod session_events;
mod session_loader;
mod tools;
pub mod watchers;
#[cfg(test)]
mod tests;
#[derive(Debug, Clone, Copy, Default)]
pub struct ConfigUpdateEffects {
pub reload_provider: bool,
pub reconcile_mcp: bool,
}