agent_tui/detection/
registry.rs

1use super::frameworks::{
2    BubbleTeaDetector, GenericDetector, InkDetector, InquirerDetector, RatatuiDetector,
3    TextualDetector,
4};
5use super::pattern::PatternMatch;
6use super::traits::{DetectionContext, ElementDetectorImpl};
7
8pub enum FrameworkDetector {
9    Generic(GenericDetector),
10    Ink(InkDetector),
11    Inquirer(InquirerDetector),
12    BubbleTea(BubbleTeaDetector),
13    Textual(TextualDetector),
14    Ratatui(RatatuiDetector),
15}
16
17impl FrameworkDetector {
18    pub fn detect(ctx: &DetectionContext) -> Self {
19        if InquirerDetector::looks_like_inquirer(ctx) {
20            return FrameworkDetector::Inquirer(InquirerDetector::new());
21        }
22
23        if InkDetector::looks_like_ink(ctx) {
24            return FrameworkDetector::Ink(InkDetector::new());
25        }
26
27        if BubbleTeaDetector::looks_like_bubbletea(ctx) {
28            return FrameworkDetector::BubbleTea(BubbleTeaDetector::new());
29        }
30
31        if TextualDetector::looks_like_textual(ctx) {
32            return FrameworkDetector::Textual(TextualDetector::new());
33        }
34
35        if RatatuiDetector::looks_like_ratatui(ctx) {
36            return FrameworkDetector::Ratatui(RatatuiDetector::new());
37        }
38
39        FrameworkDetector::Generic(GenericDetector::new())
40    }
41}
42
43impl Default for FrameworkDetector {
44    fn default() -> Self {
45        FrameworkDetector::Generic(GenericDetector::new())
46    }
47}
48
49macro_rules! delegate_to_detector {
50    ($self:expr, $method:ident $(, $arg:expr)*) => {
51        match $self {
52            FrameworkDetector::Generic(d) => d.$method($($arg),*),
53            FrameworkDetector::Ink(d) => d.$method($($arg),*),
54            FrameworkDetector::Inquirer(d) => d.$method($($arg),*),
55            FrameworkDetector::BubbleTea(d) => d.$method($($arg),*),
56            FrameworkDetector::Textual(d) => d.$method($($arg),*),
57            FrameworkDetector::Ratatui(d) => d.$method($($arg),*),
58        }
59    };
60}
61
62impl ElementDetectorImpl for FrameworkDetector {
63    fn detect_patterns(&self, ctx: &DetectionContext) -> Vec<PatternMatch> {
64        delegate_to_detector!(self, detect_patterns, ctx)
65    }
66
67    fn framework_name(&self) -> &'static str {
68        delegate_to_detector!(self, framework_name)
69    }
70
71    fn priority(&self) -> i32 {
72        delegate_to_detector!(self, priority)
73    }
74
75    fn can_detect(&self, ctx: &DetectionContext) -> bool {
76        delegate_to_detector!(self, can_detect, ctx)
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_framework_detector_default() {
86        let detector = FrameworkDetector::default();
87        assert_eq!(detector.framework_name(), "generic");
88    }
89
90    #[test]
91    fn test_framework_detector_auto_detect_generic() {
92        let ctx = DetectionContext::new("[Submit]", None);
93        let detector = FrameworkDetector::detect(&ctx);
94        assert_eq!(detector.framework_name(), "generic");
95    }
96
97    #[test]
98    fn test_framework_detector_auto_detect_ink() {
99        let ctx = DetectionContext::new("? Select:\n  ❯ Option 1\n    Option 2", None);
100        let detector = FrameworkDetector::detect(&ctx);
101        assert_eq!(detector.framework_name(), "ink");
102    }
103
104    #[test]
105    fn test_framework_detector_auto_detect_inquirer() {
106        let ctx = DetectionContext::new("? Choose:\n  ◯ Option 1\n  ◉ Option 2", None);
107        let detector = FrameworkDetector::detect(&ctx);
108        assert_eq!(detector.framework_name(), "inquirer");
109    }
110
111    #[test]
112    fn test_framework_detector_priority() {
113        let generic = FrameworkDetector::default();
114        assert!(generic.priority() < 0);
115
116        let ink = FrameworkDetector::Ink(InkDetector::new());
117        assert!(ink.priority() > 0);
118
119        let inquirer = FrameworkDetector::Inquirer(InquirerDetector::new());
120        assert!(inquirer.priority() > ink.priority());
121    }
122
123    #[test]
124    fn test_framework_detector_can_detect() {
125        let ctx = DetectionContext::new("  ❯ Red\n    Blue", None);
126        let ink = FrameworkDetector::Ink(InkDetector::new());
127        assert!(ink.can_detect(&ctx));
128
129        let generic = FrameworkDetector::default();
130        assert!(generic.can_detect(&ctx));
131    }
132}