use std::collections::HashMap;
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::sync::{Mutex, RwLock, broadcast};
use super::event::WebEvent;
use super::routes_swarm::SwarmAgentNode;
use crate::agent::approval::{ApproveMode, SharedApproveMode};
use crate::agent::context::ConversationContext;
use crate::agent::swarm::knowledge::SharedKnowledge;
use crate::api::provider::OpenAiCompatibleProvider;
use crate::config::Config;
pub struct AppState {
pub config: Config,
pub client: OpenAiCompatibleProvider,
pub event_bus: broadcast::Sender<WebEvent>,
pub agent_active: AtomicBool,
pub approve_mode: SharedApproveMode,
pub context: Mutex<Option<ConversationContext>>,
pub swarm_agents: RwLock<HashMap<String, SwarmAgentNode>>,
working_dir: RwLock<String>,
pub knowledge: RwLock<Option<SharedKnowledge>>,
}
impl AppState {
pub fn new(
config: Config,
client: OpenAiCompatibleProvider,
event_bus: broadcast::Sender<WebEvent>,
working_dir: String,
) -> Self {
let initial_mode = if config.yolo {
ApproveMode::Yolo
} else {
ApproveMode::Auto
};
Self {
config,
client,
event_bus,
agent_active: AtomicBool::new(false),
approve_mode: SharedApproveMode::new(initial_mode),
context: Mutex::new(None),
swarm_agents: RwLock::new(HashMap::new()),
working_dir: RwLock::new(working_dir),
knowledge: RwLock::new(None),
}
}
pub async fn working_dir(&self) -> String {
self.working_dir.read().await.clone()
}
pub async fn set_working_dir(&self, dir: String) {
*self.working_dir.write().await = dir;
}
pub fn is_agent_active(&self) -> bool {
self.agent_active.load(Ordering::SeqCst)
}
pub fn set_agent_active(&self, active: bool) {
self.agent_active.store(active, Ordering::SeqCst);
}
pub fn try_claim_agent(&self) -> bool {
self.agent_active
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
.is_ok()
}
}