249 lines
6.7 KiB
Rust
Raw Normal View History

//! 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<String>,
/// Available infrastructures and their status
pub infrastructures: Vec<InfrastructureState>,
/// Installed taskservs
pub installed_taskservs: Vec<String>,
/// Installed providers
pub installed_providers: Vec<String>,
/// Recent deployments (last N)
pub recent_deployments: Vec<DeploymentInfo>,
/// Capabilities of the workspace
pub capabilities: CapabilitySet,
/// Custom metadata
pub metadata: HashMap<String, String>,
}
/// 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<String>,
/// Deployed clusters
pub clusters: Vec<String>,
/// Last updated timestamp
pub last_updated: Option<String>,
}
/// 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<u64>,
/// Error message (if failed)
pub error_message: Option<String>,
}
/// Capability set for workspace
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CapabilitySet {
/// Can deploy to these providers
pub deployable_providers: Vec<String>,
/// Can create these resource types
pub creatable_resources: Vec<String>,
/// Installed tools
pub installed_tools: Vec<String>,
/// Supported features
pub features: Vec<String>,
}
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"));
}
}