vtcode_core/core/agent/
semantic.rs

1//! Semantic analysis for message content
2
3use crate::core::agent::types::{MessagePriority, MessageType};
4
5/// Semantic analyzer for message content
6#[derive(Debug)]
7pub struct SemanticAnalyzer {
8    security_keywords: Vec<String>,
9    code_keywords: Vec<String>,
10    decision_keywords: Vec<String>,
11}
12
13impl SemanticAnalyzer {
14    /// Create a new semantic analyzer
15    pub fn new() -> Self {
16        Self {
17            security_keywords: vec![
18                "password".to_string(),
19                "token".to_string(),
20                "key".to_string(),
21                "secret".to_string(),
22                "auth".to_string(),
23                "login".to_string(),
24                "permission".to_string(),
25            ],
26            code_keywords: vec![
27                "function".to_string(),
28                "class".to_string(),
29                "struct".to_string(),
30                "enum".to_string(),
31                "impl".to_string(),
32                "trait".to_string(),
33                "mod".to_string(),
34                "use".to_string(),
35            ],
36            decision_keywords: vec![
37                "decision".to_string(),
38                "choose".to_string(),
39                "select".to_string(),
40                "option".to_string(),
41                "alternative".to_string(),
42                "recommend".to_string(),
43            ],
44        }
45    }
46
47    /// Analyze message priority based on content and type
48    pub fn analyze_message_priority(
49        &self,
50        content: &str,
51        message_type: &MessageType,
52    ) -> MessagePriority {
53        // Security-related content is always critical
54        if self.contains_security_keywords(content) {
55            return MessagePriority::Critical;
56        }
57
58        match message_type {
59            MessageType::UserMessage => {
60                if self.contains_decision_keywords(content) {
61                    MessagePriority::High
62                } else if self.contains_code_keywords(content) {
63                    MessagePriority::High
64                } else {
65                    MessagePriority::Medium
66                }
67            }
68            MessageType::AssistantResponse => {
69                if self.contains_decision_keywords(content) {
70                    MessagePriority::High
71                } else {
72                    MessagePriority::Medium
73                }
74            }
75            MessageType::ToolCall => {
76                if content.contains("error") || content.contains("fail") {
77                    MessagePriority::High
78                } else {
79                    MessagePriority::Low
80                }
81            }
82            MessageType::ToolResponse => {
83                if content.contains("error") || content.contains("fail") {
84                    MessagePriority::High
85                } else {
86                    MessagePriority::Low
87                }
88            }
89            MessageType::SystemMessage => MessagePriority::Critical,
90        }
91    }
92
93    /// Extract semantic tags from message content
94    pub fn extract_semantic_tags(&self, content: &str) -> Vec<String> {
95        let mut tags = Vec::new();
96
97        if self.contains_security_keywords(content) {
98            tags.push("security".to_string());
99        }
100
101        if self.contains_code_keywords(content) {
102            tags.push("code".to_string());
103        }
104
105        if self.contains_decision_keywords(content) {
106            tags.push("decision".to_string());
107        }
108
109        if content.contains("error") || content.contains("fail") {
110            tags.push("error".to_string());
111        }
112
113        if content.contains("success") || content.contains("complete") {
114            tags.push("success".to_string());
115        }
116
117        tags
118    }
119
120    fn contains_security_keywords(&self, content: &str) -> bool {
121        let content_lower = content.to_lowercase();
122        self.security_keywords
123            .iter()
124            .any(|keyword| content_lower.contains(keyword))
125    }
126
127    fn contains_code_keywords(&self, content: &str) -> bool {
128        let content_lower = content.to_lowercase();
129        self.code_keywords
130            .iter()
131            .any(|keyword| content_lower.contains(keyword))
132    }
133
134    fn contains_decision_keywords(&self, content: &str) -> bool {
135        let content_lower = content.to_lowercase();
136        self.decision_keywords
137            .iter()
138            .any(|keyword| content_lower.contains(keyword))
139    }
140}