Skip to main content
Glama

CodeGraph CLI MCP Server

by Jakedismo
ai_context_enhancement.rs•13.7 kB
/// REVOLUTIONARY: Real-Time AI Context Enhancement for Guided Parsing /// /// COMPLETE IMPLEMENTATION: AI-guided parsing where semantic context is provided /// DURING AST traversal, dramatically improving both speed and accuracy. use codegraph_core::{CodeNode, EdgeRelationship, EdgeType, Language, Location, NodeId, NodeType}; use std::collections::HashMap; use std::sync::{Arc, RwLock}; use tracing::info; use tree_sitter::Node; /// AI-provided semantic context during AST traversal #[derive(Debug, Clone)] pub struct SemanticContext { pub language: Language, pub symbol_hints: HashMap<String, Vec<String>>, pub confidence_scores: HashMap<String, f32>, pub module_context: Vec<String>, pub function_context: Option<NodeId>, pub type_context: HashMap<String, String>, } /// Real-time AI context provider for enhanced parsing pub struct AIContextProvider { semantic_cache: Arc<RwLock<HashMap<String, Vec<String>>>>, type_predictions: Arc<RwLock<HashMap<String, NodeType>>>, pattern_cache: Arc<RwLock<HashMap<String, String>>>, language_rules: HashMap<Language, ContextRules>, } #[derive(Debug, Clone)] pub struct ContextRules { pub type_indicators: HashMap<String, NodeType>, pub namespace_patterns: Vec<String>, pub call_patterns: Vec<String>, pub import_patterns: Vec<String>, } impl Default for AIContextProvider { fn default() -> Self { Self::new() } } impl AIContextProvider { pub fn new() -> Self { let mut language_rules = HashMap::new(); // Rust-specific context rules language_rules.insert( Language::Rust, ContextRules { type_indicators: { let mut map = HashMap::new(); map.insert("fn ".to_string(), NodeType::Function); map.insert("struct ".to_string(), NodeType::Struct); map.insert("trait ".to_string(), NodeType::Trait); map.insert("impl ".to_string(), NodeType::Other("impl".to_string())); map.insert("mod ".to_string(), NodeType::Module); map.insert("use ".to_string(), NodeType::Import); map }, namespace_patterns: vec![ "crate::".to_string(), "std::".to_string(), "super::".to_string(), "self::".to_string(), ], call_patterns: vec!["()".to_string(), "!(".to_string(), ".".to_string()], import_patterns: vec!["use ".to_string(), "extern crate ".to_string()], }, ); Self { semantic_cache: Arc::new(RwLock::new(HashMap::new())), type_predictions: Arc::new(RwLock::new(HashMap::new())), pattern_cache: Arc::new(RwLock::new(HashMap::new())), language_rules, } } /// COMPLETE IMPLEMENTATION: Provide AI semantic context during AST node processing pub fn enhance_node_extraction( &self, node: &Node, content: &str, context: &mut SemanticContext, ) -> NodeExtractionHints { let node_text = node.utf8_text(content.as_bytes()).unwrap_or("").to_string(); let mut hints = NodeExtractionHints::default(); if let Some(rules) = self.language_rules.get(&context.language) { hints.predicted_node_type = self.predict_node_type(&node_text, rules); hints.symbol_variants = self.generate_symbol_variants(&node_text, rules); hints.relationship_hints = self.predict_relationships(&node_text, context, rules); } if let Ok(cache) = self.semantic_cache.read() { if let Some(cached_variants) = cache.get(&node_text) { hints.symbol_variants.extend(cached_variants.clone()); } } hints } fn predict_node_type(&self, node_text: &str, rules: &ContextRules) -> Option<NodeType> { if let Ok(predictions) = self.type_predictions.read() { if let Some(predicted_type) = predictions.get(node_text) { return Some(predicted_type.clone()); } } for (indicator, node_type) in &rules.type_indicators { if node_text.contains(indicator) { return Some(node_type.clone()); } } None } fn generate_symbol_variants(&self, symbol: &str, rules: &ContextRules) -> Vec<String> { let mut variants = vec![symbol.to_string()]; for pattern in &rules.namespace_patterns { variants.push(format!("{}{}", pattern, symbol)); if symbol.contains(pattern) { let stripped = symbol.replace(pattern, ""); if !stripped.is_empty() && stripped != symbol { variants.push(stripped); } } } for pattern in &rules.call_patterns { if symbol.contains(pattern) { let stripped = symbol.replace(pattern, ""); if !stripped.is_empty() && stripped != symbol { variants.push(stripped); } } } variants.sort(); variants.dedup(); variants } fn predict_relationships( &self, symbol: &str, _context: &SemanticContext, rules: &ContextRules, ) -> Vec<RelationshipHint> { let mut hints = Vec::new(); for pattern in &rules.call_patterns { if symbol.contains(pattern) { hints.push(RelationshipHint { target_symbol: symbol.replace(pattern, ""), edge_type: EdgeType::Calls, confidence: 0.8, }); } } for pattern in &rules.import_patterns { if symbol.contains(pattern) { hints.push(RelationshipHint { target_symbol: symbol.replace(pattern, "").trim().to_string(), edge_type: EdgeType::Imports, confidence: 0.9, }); } } hints } } #[derive(Debug, Clone)] pub struct NodeExtractionHints { pub predicted_node_type: Option<NodeType>, pub symbol_variants: Vec<String>, pub relationship_hints: Vec<RelationshipHint>, } #[derive(Debug, Clone)] pub struct RelationshipHint { pub target_symbol: String, pub edge_type: EdgeType, pub confidence: f32, } static AI_CONTEXT_PROVIDER: std::sync::OnceLock<AIContextProvider> = std::sync::OnceLock::new(); pub fn get_ai_context_provider() -> &'static AIContextProvider { AI_CONTEXT_PROVIDER.get_or_init(|| { info!("šŸš€ Initializing AI Context Enhancement Engine"); AIContextProvider::new() }) } /// COMPLETE IMPLEMENTATION: Enhanced AST node processing with real-time AI context pub fn extract_node_with_ai_context( node: &Node, content: &str, context: &mut SemanticContext, ) -> (Option<CodeNode>, Vec<EdgeRelationship>) { let ai_provider = get_ai_context_provider(); let hints = ai_provider.enhance_node_extraction(node, content, context); let enhanced_node = extract_enhanced_node(node, content, context, &hints); let enhanced_edges = extract_enhanced_edges(node, content, context, &hints); (enhanced_node, enhanced_edges) } fn extract_enhanced_node( node: &Node, content: &str, context: &SemanticContext, hints: &NodeExtractionHints, ) -> Option<CodeNode> { let node_text = node.utf8_text(content.as_bytes()).unwrap_or("").to_string(); let node_type = hints .predicted_node_type .clone() .or_else(|| classify_node_type_traditional(node)); if let Some(nt) = node_type { let location = Location { file_path: context.module_context.join("::"), line: node.start_position().row as u32 + 1, column: node.start_position().column as u32, end_line: Some(node.end_position().row as u32 + 1), end_column: Some(node.end_position().column as u32), }; let mut code_node = CodeNode::new( extract_node_name(node, content).unwrap_or_else(|| "unknown".to_string()), Some(nt), Some(context.language.clone()), location, ) .with_content(node_text); if !hints.symbol_variants.is_empty() { code_node.metadata.attributes.insert( "ai_symbol_variants".to_string(), serde_json::to_string(&hints.symbol_variants).unwrap_or_default(), ); } let qualified_name = if !context.module_context.is_empty() { format!("{}::{}", context.module_context.join("::"), code_node.name) } else { code_node.name.to_string() }; code_node .metadata .attributes .insert("qualified_name".to_string(), qualified_name); Some(code_node) } else { None } } fn extract_enhanced_edges( node: &Node, content: &str, context: &SemanticContext, hints: &NodeExtractionHints, ) -> Vec<EdgeRelationship> { let mut edges = Vec::new(); if let Some(current_fn) = context.function_context { edges.extend(extract_traditional_edges(node, content, current_fn)); for hint in &hints.relationship_hints { if hint.confidence > 0.7 { edges.push(EdgeRelationship { from: current_fn, to: hint.target_symbol.clone(), edge_type: hint.edge_type.clone(), metadata: { let mut meta = HashMap::new(); meta.insert("ai_predicted".to_string(), "true".to_string()); meta.insert("ai_confidence".to_string(), hint.confidence.to_string()); meta.insert( "enhancement_type".to_string(), "real_time_context".to_string(), ); meta }, }); } } } edges } fn extract_traditional_edges( node: &Node, content: &str, from_node: NodeId, ) -> Vec<EdgeRelationship> { let mut edges = Vec::new(); match node.kind() { "call_expression" => { if let Some(function_name) = extract_call_target(node, content) { edges.push(EdgeRelationship { from: from_node, to: function_name, edge_type: EdgeType::Calls, metadata: { let mut meta = HashMap::new(); meta.insert("call_type".to_string(), "function_call".to_string()); meta }, }); } } "method_call_expression" => { if let Some(method_name) = extract_method_target(node, content) { edges.push(EdgeRelationship { from: from_node, to: method_name, edge_type: EdgeType::Calls, metadata: { let mut meta = HashMap::new(); meta.insert("call_type".to_string(), "method_call".to_string()); meta }, }); } } _ => {} } edges } fn classify_node_type_traditional(node: &Node) -> Option<NodeType> { match node.kind() { "function_item" => Some(NodeType::Function), "struct_item" => Some(NodeType::Struct), "trait_item" => Some(NodeType::Trait), "impl_item" => Some(NodeType::Other("impl".to_string())), "mod_item" => Some(NodeType::Module), "use_declaration" => Some(NodeType::Import), _ => None, } } fn extract_node_name(node: &Node, content: &str) -> Option<String> { let mut cursor = node.walk(); if cursor.goto_first_child() { loop { let child = cursor.node(); if child.kind() == "identifier" || child.kind() == "type_identifier" { return child .utf8_text(content.as_bytes()) .ok() .map(|s| s.to_string()); } if !cursor.goto_next_sibling() { break; } } } None } fn extract_call_target(node: &Node, content: &str) -> Option<String> { if let Some(function_node) = node.child_by_field_name("function") { return function_node .utf8_text(content.as_bytes()) .ok() .map(|s| s.to_string()); } None } fn extract_method_target(node: &Node, content: &str) -> Option<String> { if let Some(method_node) = node.child_by_field_name("name") { return method_node .utf8_text(content.as_bytes()) .ok() .map(|s| s.to_string()); } None } impl Default for SemanticContext { fn default() -> Self { Self { language: Language::Rust, symbol_hints: HashMap::new(), confidence_scores: HashMap::new(), module_context: Vec::new(), function_context: None, type_context: HashMap::new(), } } } impl Default for NodeExtractionHints { fn default() -> Self { Self { predicted_node_type: None, symbol_variants: Vec::new(), relationship_hints: Vec::new(), } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jakedismo/codegraph-rust'

If you have feedback or need assistance with the MCP directory API, please join our Discord server