widget_intelligence/
lib.rs1pub mod kyma_extractor;
44pub mod persistence;
45pub mod similarity_engine;
46pub mod tauri_examples;
47
48pub use similarity_engine::{
50 FilteredWidgetDescription, Preset, Suggestion, ValueStats, Widget, WidgetFeatures,
51 WidgetRecord, WidgetSuggestionEngine, WidgetValue,
52};
53
54pub use persistence::{
55 ExportData, PersistentWidgetSuggestionEngine, SledPersistenceError, SledPersistenceManager,
56};
57
58pub use kyma_extractor::{KymaWidgetExtractor, WidgetMetadata};
59
60pub use tauri_examples::{
61 IntelligenceStats, PresetData, StandaloneIntelligenceService, SuggestionResponse,
62 WidgetInsightResponse,
63};
64
65impl Default for Widget {
66 fn default() -> Self {
67 Self {
68 label: None,
69 minimum: None,
70 maximum: None,
71 current_value: None,
72 is_generated: None,
73 display_type: None,
74 event_id: None,
75 values: Vec::new(),
76 }
77 }
78}
79
80pub fn init_intelligence_system<P: AsRef<std::path::Path>>(
82 db_path: P,
83) -> Result<PersistentWidgetSuggestionEngine, persistence::SledPersistenceError> {
84 PersistentWidgetSuggestionEngine::new(db_path)
85}
86
87pub fn init_standalone_service(db_path: &str) -> Result<StandaloneIntelligenceService, String> {
89 StandaloneIntelligenceService::new(db_path)
90}
91
92pub fn validate_widget(widget: &Widget) -> Result<(), String> {
94 if let (Some(min), Some(max)) = (widget.minimum, widget.maximum) {
95 if min >= max {
96 return Err("Minimum value must be less than maximum value".to_string());
97 }
98
99 if let Some(current) = widget.current_value {
100 if current < min || current > max {
101 return Err("Current value must be within minimum and maximum bounds".to_string());
102 }
103 }
104 }
105
106 Ok(())
107}
108
109pub fn create_test_widget(label: &str, min: f64, max: f64, current: f64) -> Widget {
111 Widget {
112 label: Some(label.to_string()),
113 minimum: Some(min),
114 maximum: Some(max),
115 current_value: Some(current),
116 is_generated: Some(false),
117 display_type: Some("slider".to_string()),
118 event_id: None,
119 values: vec![current],
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126 use std::{thread, time::Duration};
127 use tempfile::tempdir;
128
129 #[test]
130 fn test_persistent_system() -> Result<(), Box<dyn std::error::Error>> {
131 let temp_dir = tempdir()?;
132 let db_path = temp_dir.path().join("test_persistent_lib");
133
134 thread::sleep(Duration::from_millis(100));
136
137 let mut system = init_intelligence_system(&db_path)?;
138
139 let widget = create_test_widget("Test Widget", 0.0, 100.0, 50.0);
140 system.store_widget(widget)?;
141
142 let stats = system.get_stats();
143 assert_eq!(stats.get("total_widgets"), Some(&1));
144
145 system.flush()?;
147 drop(system);
148
149 thread::sleep(Duration::from_millis(100));
150
151 let system2 = init_intelligence_system(&db_path)?;
152 let stats2 = system2.get_stats();
153 assert_eq!(stats2.get("total_widgets"), Some(&1));
154
155 drop(system2);
157 temp_dir.close()?;
158
159 Ok(())
160 }
161}