agent_tui/detection/
registry.rs1use 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}