Skip to main content
Glama
assembler.rs5.96 kB
//! Terminal State Tree (TST) assembler. use terminal_mcp_core::{Dimensions, Position, TerminalStateTree}; use crate::detection::DetectedElement; /// TST assembler for building element hierarchy. pub struct TSTAssembler; impl TSTAssembler { /// Create a new TST assembler. pub fn new() -> Self { Self } /// Assemble detected elements into a Terminal State Tree. /// /// This converts raw DetectedElement results into a structured TST /// with proper hierarchy and containment relationships. /// /// # Arguments /// * `detected` - Detected elements with bounds and confidence /// * `session_id` - Session identifier /// * `dimensions` - Terminal dimensions /// * `cursor` - Current cursor position /// * `raw_text` - Raw text content pub fn assemble( &self, detected: Vec<DetectedElement>, session_id: String, dimensions: Dimensions, cursor: Position, raw_text: String, ) -> TerminalStateTree { // Extract elements (ignoring bounds and confidence for now) // TODO: Build proper hierarchy based on containment let elements = detected.into_iter().map(|d| d.element).collect(); TerminalStateTree { session_id, dimensions, cursor, timestamp: chrono::Utc::now().to_rfc3339(), elements, raw_text, ansi_buffer: None, } } /// Assemble with confidence filtering. /// /// Only includes elements meeting the minimum confidence threshold. pub fn assemble_with_confidence( &self, detected: Vec<DetectedElement>, min_confidence: crate::detection::Confidence, session_id: String, dimensions: Dimensions, cursor: Position, raw_text: String, ) -> TerminalStateTree { let filtered: Vec<DetectedElement> = detected .into_iter() .filter(|d| d.confidence >= min_confidence) .collect(); self.assemble(filtered, session_id, dimensions, cursor, raw_text) } } impl Default for TSTAssembler { fn default() -> Self { Self::new() } } #[cfg(test)] mod tests { use super::*; use crate::detection::Confidence; use terminal_mcp_core::{Bounds, Element, MenuItem}; #[test] fn test_assembler_basic() { let assembler = TSTAssembler::new(); let detected = vec![ DetectedElement { element: Element::Menu { ref_id: "menu_1".to_string(), bounds: Bounds::new(0, 0, 10, 5), items: vec![MenuItem { text: "Item 1".to_string(), ref_id: "item_1".to_string(), selected: false, }], selected: 0, }, bounds: Bounds::new(0, 0, 10, 5), confidence: Confidence::High, }, DetectedElement { element: Element::Button { ref_id: "button_1".to_string(), bounds: Bounds::new(0, 10, 5, 1), label: "OK".to_string(), }, bounds: Bounds::new(0, 10, 5, 1), confidence: Confidence::Medium, }, ]; let tst = assembler.assemble( detected, "test_session".to_string(), Dimensions::new(24, 80), Position::new(0, 0), "test content".to_string(), ); assert_eq!(tst.elements.len(), 2); assert_eq!(tst.session_id, "test_session"); } #[test] fn test_assembler_confidence_filtering() { let assembler = TSTAssembler::new(); let detected = vec![ DetectedElement { element: Element::Button { ref_id: "button_high".to_string(), bounds: Bounds::new(0, 0, 5, 1), label: "High".to_string(), }, bounds: Bounds::new(0, 0, 5, 1), confidence: Confidence::High, }, DetectedElement { element: Element::Button { ref_id: "button_medium".to_string(), bounds: Bounds::new(0, 10, 5, 1), label: "Medium".to_string(), }, bounds: Bounds::new(0, 10, 5, 1), confidence: Confidence::Medium, }, DetectedElement { element: Element::Button { ref_id: "button_low".to_string(), bounds: Bounds::new(0, 20, 5, 1), label: "Low".to_string(), }, bounds: Bounds::new(0, 20, 5, 1), confidence: Confidence::Low, }, ]; // Filter for high confidence only let tst = assembler.assemble_with_confidence( detected.clone(), Confidence::High, "test".to_string(), Dimensions::new(24, 80), Position::new(0, 0), "".to_string(), ); assert_eq!(tst.elements.len(), 1); // Filter for medium or higher let tst = assembler.assemble_with_confidence( detected.clone(), Confidence::Medium, "test".to_string(), Dimensions::new(24, 80), Position::new(0, 0), "".to_string(), ); assert_eq!(tst.elements.len(), 2); // Filter for low or higher (all) let tst = assembler.assemble_with_confidence( detected, Confidence::Low, "test".to_string(), Dimensions::new(24, 80), Position::new(0, 0), "".to_string(), ); assert_eq!(tst.elements.len(), 3); } }

Latest Blog Posts

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/aybelatchane/mcp-server-terminal'

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