use parking_lot::Mutex; use std::collections::HashMap; use std::sync::Arc; use tauri::AppHandle; use crate::config::ClaudeStartOptions; use crate::stats::UsageStats; use crate::wsl_bridge::WslBridge; pub struct BridgeManager { bridges: HashMap, app_handle: Option, } impl BridgeManager { pub fn new() -> Self { BridgeManager { bridges: HashMap::new(), app_handle: None, } } pub fn set_app_handle(&mut self, app: AppHandle) { self.app_handle = Some(app); } pub fn start_claude( &mut self, conversation_id: &str, options: ClaudeStartOptions, ) -> Result<(), String> { // Check if a bridge already exists for this conversation if self.bridges.get(conversation_id).map(|b| b.is_running()).unwrap_or(false) { return Err("Claude is already running for this conversation".to_string()); } let app = self.app_handle.as_ref() .ok_or_else(|| "App handle not set".to_string())? .clone(); // Create a new bridge for this conversation let mut bridge = WslBridge::new_with_conversation_id(conversation_id.to_string()); // Start the Claude process bridge.start(app, options)?; // Store the bridge self.bridges.insert(conversation_id.to_string(), bridge); Ok(()) } pub fn stop_claude(&mut self, conversation_id: &str) -> Result<(), String> { if let Some(bridge) = self.bridges.get_mut(conversation_id) { let app = self.app_handle.as_ref() .ok_or_else(|| "App handle not set".to_string())?; bridge.stop(app); Ok(()) } else { Err("No Claude instance found for this conversation".to_string()) } } pub fn interrupt_claude(&mut self, conversation_id: &str) -> Result<(), String> { if let Some(bridge) = self.bridges.get_mut(conversation_id) { let app = self.app_handle.as_ref() .ok_or_else(|| "App handle not set".to_string())?; bridge.interrupt(app) } else { Err("No Claude instance found for this conversation".to_string()) } } pub fn send_prompt(&mut self, conversation_id: &str, message: String) -> Result<(), String> { if let Some(bridge) = self.bridges.get_mut(conversation_id) { bridge.send_message(&message) } else { Err("No Claude instance found for this conversation".to_string()) } } pub fn is_claude_running(&self, conversation_id: &str) -> bool { self.bridges.get(conversation_id) .map(|b| b.is_running()) .unwrap_or(false) } pub fn get_working_directory(&self, conversation_id: &str) -> Result { self.bridges.get(conversation_id) .map(|b| b.get_working_directory().to_string()) .ok_or_else(|| "No Claude instance found for this conversation".to_string()) } pub fn get_usage_stats(&self, conversation_id: &str) -> Result { self.bridges.get(conversation_id) .map(|b| b.get_stats()) .ok_or_else(|| "No Claude instance found for this conversation".to_string()) } pub fn cleanup_stopped_bridges(&mut self) { // Remove bridges that are no longer running self.bridges.retain(|_, bridge| bridge.is_running()); } pub fn stop_all(&mut self) { if let Some(app) = &self.app_handle { for (_, bridge) in self.bridges.iter_mut() { bridge.stop(app); } } self.bridges.clear(); } pub fn get_active_conversations(&self) -> Vec { self.bridges.keys() .filter(|id| self.bridges.get(*id).map(|b| b.is_running()).unwrap_or(false)) .cloned() .collect() } } impl Default for BridgeManager { fn default() -> Self { Self::new() } } pub type SharedBridgeManager = Arc>; pub fn create_shared_bridge_manager() -> SharedBridgeManager { Arc::new(Mutex::new(BridgeManager::new())) }