//! Workspace context extraction and management use std::collections::HashMap; use serde::{Deserialize, Serialize}; /// Workspace context for RAG enrichment #[derive(Debug, Clone, Serialize, Deserialize)] pub struct WorkspaceContext { /// Active workspace name pub workspace_name: String, /// Workspace path pub workspace_path: String, /// Active infrastructure pub active_infrastructure: Option, /// Available infrastructures and their status pub infrastructures: Vec, /// Installed taskservs pub installed_taskservs: Vec, /// Installed providers pub installed_providers: Vec, /// Recent deployments (last N) pub recent_deployments: Vec, /// Capabilities of the workspace pub capabilities: CapabilitySet, /// Custom metadata pub metadata: HashMap, } /// Infrastructure state within a workspace #[derive(Debug, Clone, Serialize, Deserialize)] pub struct InfrastructureState { /// Infrastructure name pub name: String, /// Provider (upcloud, aws, local) pub provider: String, /// Number of servers pub server_count: usize, /// Deployment phase (New, Configured, Deploying, Running, Stopping, Error) pub deployment_phase: String, /// Deployed taskservs pub taskservs: Vec, /// Deployed clusters pub clusters: Vec, /// Last updated timestamp pub last_updated: Option, } /// Deployment information #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DeploymentInfo { /// Unique deployment ID pub id: String, /// Infrastructure name pub infrastructure: String, /// Deployment type (server_create, taskserv_install, cluster_deploy) pub event_type: String, /// Status (success, failed, partial) pub status: String, /// Timestamp pub timestamp: String, /// Duration in seconds pub duration_seconds: Option, /// Error message (if failed) pub error_message: Option, } /// Capability set for workspace #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CapabilitySet { /// Can deploy to these providers pub deployable_providers: Vec, /// Can create these resource types pub creatable_resources: Vec, /// Installed tools pub installed_tools: Vec, /// Supported features pub features: Vec, } impl WorkspaceContext { /// Create a new workspace context pub fn new(workspace_name: String, workspace_path: String) -> Self { Self { workspace_name, workspace_path, active_infrastructure: None, infrastructures: Vec::new(), installed_taskservs: Vec::new(), installed_providers: Vec::new(), recent_deployments: Vec::new(), capabilities: CapabilitySet::default(), metadata: HashMap::new(), } } /// Add infrastructure state pub fn add_infrastructure(&mut self, infra: InfrastructureState) { self.infrastructures.push(infra); } /// Add taskserv to installed list pub fn add_taskserv(&mut self, name: String) { if !self.installed_taskservs.contains(&name) { self.installed_taskservs.push(name); } } /// Add provider to installed list pub fn add_provider(&mut self, name: String) { if !self.installed_providers.contains(&name) { self.installed_providers.push(name); } } /// Add deployment to recent list pub fn add_deployment(&mut self, deployment: DeploymentInfo) { self.recent_deployments.insert(0, deployment); // Keep only last 10 deployments if self.recent_deployments.len() > 10 { self.recent_deployments.truncate(10); } } /// Get context summary as human-readable string pub fn summarize(&self) -> String { let mut summary = format!( "Workspace: {} (Path: {})\n", self.workspace_name, self.workspace_path ); if let Some(active) = &self.active_infrastructure { summary.push_str(&format!("Active Infrastructure: {}\n", active)); } if !self.installed_taskservs.is_empty() { summary.push_str(&format!( "Taskservs: {}\n", self.installed_taskservs.join(", ") )); } if !self.installed_providers.is_empty() { summary.push_str(&format!( "Providers: {}\n", self.installed_providers.join(", ") )); } if !self.recent_deployments.is_empty() { let recent = &self.recent_deployments[0]; summary.push_str(&format!( "Latest deployment: {} ({}) - {}\n", recent.event_type, recent.infrastructure, recent.status )); } summary } /// Enrich a query with workspace context pub fn enrich_query(&self, query: &str) -> String { format!("{}\n\nWorkspace Context:\n{}\n", query, self.summarize()) } } impl Default for CapabilitySet { fn default() -> Self { Self { deployable_providers: vec![], creatable_resources: vec![ "servers".to_string(), "taskservs".to_string(), "clusters".to_string(), ], installed_tools: vec![], features: vec![], } } } #[cfg(test)] mod tests { use super::*; #[test] fn test_workspace_context_creation() { let ctx = WorkspaceContext::new( "test-workspace".to_string(), "/path/to/workspace".to_string(), ); assert_eq!(ctx.workspace_name, "test-workspace"); assert_eq!(ctx.workspace_path, "/path/to/workspace"); assert!(ctx.infrastructures.is_empty()); } #[test] fn test_add_taskserv() { let mut ctx = WorkspaceContext::new("test".to_string(), "/path".to_string()); ctx.add_taskserv("kubernetes".to_string()); ctx.add_taskserv("prometheus".to_string()); assert_eq!(ctx.installed_taskservs.len(), 2); assert!(!ctx.installed_taskservs.contains(&"redis".to_string())); } #[test] fn test_enrich_query() { let mut ctx = WorkspaceContext::new( "librecloud".to_string(), "/workspace/librecloud".to_string(), ); ctx.add_taskserv("kubernetes".to_string()); let enriched = ctx.enrich_query("How do I add monitoring?"); assert!(enriched.contains("How do I add monitoring?")); assert!(enriched.contains("Workspace Context")); assert!(enriched.contains("librecloud")); assert!(enriched.contains("kubernetes")); } }