← back to initia-group__maestro

Function bodies 848 total

All specs Real LLM only Function bodies
main function · rust · L9-L36 (28 LOC)
examples/keytest.rs
fn main() -> io::Result<()> {
    enable_raw_mode()?;
    print!("Maestro key event diagnostic\r\n");
    print!("Press keys to see crossterm events. Ctrl+C to quit.\r\n");
    print!("Try pressing Shift+Tab — expect BackTab.\r\n\r\n");

    loop {
        match event::read()? {
            Event::Key(key) => {
                print!(
                    "KeyEvent {{ code: {:?}, modifiers: {:?}, kind: {:?} }}\r\n",
                    key.code, key.modifiers, key.kind
                );
                io::stdout().flush()?;

                if key.code == KeyCode::Char('c') && key.modifiers.contains(KeyModifiers::CONTROL) {
                    break;
                }
            }
            _ => {}
        }
    }

    disable_raw_mode()?;
    print!("\r\nDone.\r\n");
    Ok(())
}
Maestro class · ruby · L3-L13 (11 LOC)
homebrew/maestro.rb
class Maestro < Formula
  desc "TUI agent dashboard for Claude Code"
  homepage "https://github.com/initia-group/maestro"
  version "0.1.0"
  license "MIT"

  on_macos do
    on_arm do
      url "https://github.com/initia-group/maestro/releases/download/v#{version}/maestro-v#{version}-aarch64-apple-darwin.tar.gz"
      sha256 "PLACEHOLDER"
    end
install function · ruby · L31-L33 (3 LOC)
homebrew/maestro.rb
  def install
    bin.install "maestro"
  end
from_config function · rust · L35-L95 (61 LOC)
src/agent/detector.rs
    pub fn from_config(config: &DetectionConfig) -> Self {
        let mut tool_approval = vec![
            Regex::new(r"Allow\s+(\w+)").unwrap(),
            Regex::new(r"\[Y/n\]").unwrap(),
            Regex::new(r"\[y/N\]").unwrap(),
        ];
        for pattern in &config.tool_approval_patterns {
            match Regex::new(pattern) {
                Ok(re) => tool_approval.push(re),
                Err(e) => warn!("Invalid tool_approval regex {pattern:?}: {e}"),
            }
        }

        let mut error = vec![
            Regex::new(r"(?i)error:").unwrap(),
            Regex::new(r"(?i)api\s+error").unwrap(),
            Regex::new(r"(?i)rate\s+limit").unwrap(),
            Regex::new(r"(?i)connection\s+refused").unwrap(),
            Regex::new(r"(?i)ECONNREFUSED").unwrap(),
            Regex::new(r"(?i)timeout").unwrap(),
        ];
        for pattern in &config.error_patterns {
            match Regex::new(pattern) {
                Ok(re) => error.push(re),
        
scan_lines function · rust · L98-L100 (3 LOC)
src/agent/detector.rs
    pub fn scan_lines(&self) -> usize {
        self.scan_lines
    }
detect_state function · rust · L131-L255 (125 LOC)
src/agent/detector.rs
pub fn detect_state(patterns: &DetectionPatterns, signals: &DetectionSignals) -> AgentState {
    // --- Priority 1: Process exit (most reliable) ---
    if let Some(exit) = &signals.process_exited {
        let at = Utc::now();
        return match exit.exit_code {
            Some(0) => AgentState::Completed {
                at,
                exit_code: Some(0),
            },
            Some(code) => AgentState::Errored {
                at,
                error_hint: extract_error_hint(&signals.screen_lines)
                    .or_else(|| Some(format!("exit code {code}"))),
            },
            None => {
                if exit.signal {
                    AgentState::Errored {
                        at,
                        error_hint: Some("Killed by signal".to_string()),
                    }
                } else {
                    AgentState::Completed {
                        at,
                        exit_code: None,
                    }
             
detect_tool_approval function · rust · L258-L280 (23 LOC)
src/agent/detector.rs
fn detect_tool_approval(patterns: &DetectionPatterns, lines: &[String]) -> Option<String> {
    // Quick check: do any lines match any tool_approval pattern?
    let has_match = lines
        .iter()
        .any(|line| patterns.tool_approval.iter().any(|re| re.is_match(line)));

    if !has_match {
        return None;
    }

    // Try to extract the tool name from "Allow <ToolName>"
    for line in lines {
        for re in &patterns.tool_approval {
            if let Some(captures) = re.captures(line) {
                if let Some(tool_match) = captures.get(1) {
                    return Some(tool_match.as_str().to_string());
                }
            }
        }
    }

    Some("Unknown".to_string())
}
All rows above produced by Repobility · https://repobility.com
detect_input_prompt function · rust · L283-L294 (12 LOC)
src/agent/detector.rs
fn detect_input_prompt(patterns: &DetectionPatterns, lines: &[String]) -> bool {
    // Check the very last non-empty line
    let last_line = lines.iter().rev().find(|l| !l.trim().is_empty());
    if let Some(line) = last_line {
        for re in &patterns.input_prompt {
            if re.is_match(line.trim()) {
                return true;
            }
        }
    }
    false
}
detect_ask_user_question function · rust · L301-L348 (48 LOC)
src/agent/detector.rs
fn detect_ask_user_question(patterns: &DetectionPatterns, lines: &[String]) -> Option<String> {
    let numbered_option_re = &patterns.ask_user_question[0]; // ❯?\s*\d+[.:]\s+.+

    // Count how many lines match the numbered option pattern
    let option_count = lines
        .iter()
        .filter(|l| numbered_option_re.is_match(l.trim()))
        .count();

    // Need at least 2 numbered option lines to consider this an AskUserQuestion
    if option_count < 2 {
        return None;
    }

    // Find the first numbered option line index
    let first_option_idx = lines
        .iter()
        .position(|l| numbered_option_re.is_match(l.trim()));

    // Try to extract the question text from lines above the options
    if let Some(opt_idx) = first_option_idx {
        for i in (0..opt_idx).rev() {
            let trimmed = lines[i].trim();
            if trimmed.is_empty() {
                continue;
            }
            if trimmed.ends_with('?') {
                // Found a q
detect_question function · rust · L351-L364 (14 LOC)
src/agent/detector.rs
fn detect_question(lines: &[String]) -> bool {
    for line in lines.iter().rev() {
        let trimmed = line.trim();
        if trimmed.is_empty() {
            continue;
        }
        // A line ending with '?' that isn't trivially short
        if trimmed.ends_with('?') && trimmed.len() > 1 {
            return true;
        }
        break; // Only check the last non-empty line
    }
    false
}
extract_error_hint function · rust · L367-L382 (16 LOC)
src/agent/detector.rs
fn extract_error_hint(lines: &[String]) -> Option<String> {
    for line in lines.iter().rev() {
        let trimmed = line.trim();
        if trimmed.is_empty() {
            continue;
        }
        // Return the last non-empty line as the error hint (truncated to 80 chars)
        let hint = if trimmed.len() > 80 {
            format!("{}...", &trimmed[..77])
        } else {
            trimmed.to_string()
        };
        return Some(hint);
    }
    None
}
extract_screen_lines function · rust · L388-L393 (6 LOC)
src/agent/detector.rs
pub fn extract_screen_lines(screen: &vt100::Screen, n: usize) -> Vec<String> {
    let contents = screen.contents();
    let all_lines: Vec<&str> = contents.lines().collect();
    let start = all_lines.len().saturating_sub(n);
    all_lines[start..].iter().map(|s| s.to_string()).collect()
}
new function · rust · L411-L417 (7 LOC)
src/agent/detector.rs
    pub fn new() -> Self {
        Self {
            pending: None,
            count: 0,
            threshold: 2,
        }
    }
with_threshold function · rust · L420-L426 (7 LOC)
src/agent/detector.rs
    pub fn with_threshold(threshold: u8) -> Self {
        Self {
            pending: None,
            count: 0,
            threshold,
        }
    }
process function · rust · L430-L464 (35 LOC)
src/agent/detector.rs
    pub fn process(&mut self, detected: AgentState, current: &AgentState) -> Option<AgentState> {
        // Terminal states bypass debounce — always immediate
        if detected.is_terminal() {
            self.pending = None;
            self.count = 0;
            return Some(detected);
        }

        // If same as current state, no transition needed
        if detected.same_variant(current) {
            self.pending = None;
            self.count = 0;
            return None;
        }

        // Check if this matches the pending detection
        match &self.pending {
            Some(pending) if pending.same_variant(&detected) => {
                self.count += 1;
                if self.count >= self.threshold {
                    self.pending = None;
                    self.count = 0;
                    Some(detected)
                } else {
                    None
                }
            }
            _ => {
                // New detection — start debounce
 
All rows scored by the Repobility analyzer (https://repobility.com)
default function · rust · L468-L470 (3 LOC)
src/agent/detector.rs
    fn default() -> Self {
        Self::new()
    }
default_patterns function · rust · L477-L480 (4 LOC)
src/agent/detector.rs
    fn default_patterns() -> DetectionPatterns {
        DetectionPatterns::from_config(&DetectionConfig::default())
    }
test_patterns_from_default_config function · rust · L485-L492 (8 LOC)
src/agent/detector.rs
    fn test_patterns_from_default_config() {
        let patterns = default_patterns();
        assert!(!patterns.tool_approval.is_empty());
        assert!(!patterns.error.is_empty());
        assert!(!patterns.input_prompt.is_empty());
        assert!(!patterns.ask_user_question.is_empty());
        assert_eq!(patterns.scan_lines, 10);
    }
test_patterns_with_user_additions function · rust · L495-L513 (19 LOC)
src/agent/detector.rs
    fn test_patterns_with_user_additions() {
        let config = DetectionConfig {
            tool_approval_patterns: vec!["approve\\?".into()],
            error_patterns: vec!["FATAL".into()],
            input_prompt_patterns: vec![">>>".into()],
            ask_user_question_patterns: vec!["custom_ask".into()],
            scan_lines: 10,
        };
        let patterns = DetectionPatterns::from_config(&config);
        // Built-in (3) + user (1) = 4
        assert_eq!(patterns.tool_approval.len(), 4);
        // Built-in (6) + user (1) = 7
        assert_eq!(patterns.error.len(), 7);
        // Built-in (2) + user (1) = 3
        assert_eq!(patterns.input_prompt.len(), 3);
        // Built-in (2) + user (1) = 3
        assert_eq!(patterns.ask_user_question.len(), 3);
        assert_eq!(patterns.scan_lines, 10);
    }
test_invalid_user_regex_skipped function · rust · L516-L527 (12 LOC)
src/agent/detector.rs
    fn test_invalid_user_regex_skipped() {
        let config = DetectionConfig {
            tool_approval_patterns: vec!["[invalid".into()],
            error_patterns: vec![],
            input_prompt_patterns: vec![],
            ask_user_question_patterns: vec![],
            scan_lines: 5,
        };
        let patterns = DetectionPatterns::from_config(&config);
        // Only built-in patterns (invalid one skipped)
        assert_eq!(patterns.tool_approval.len(), 3);
    }
test_detect_process_exit_success function · rust · L532-L552 (21 LOC)
src/agent/detector.rs
    fn test_detect_process_exit_success() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: Some(ProcessExit {
                exit_code: Some(0),
                signal: false,
            }),
            screen_lines: vec![],
            seconds_since_output: 0.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        assert!(matches!(
            state,
            AgentState::Completed {
                exit_code: Some(0),
                ..
            }
        ));
    }
test_detect_process_exit_error function · rust · L555-L574 (20 LOC)
src/agent/detector.rs
    fn test_detect_process_exit_error() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: Some(ProcessExit {
                exit_code: Some(1),
                signal: false,
            }),
            screen_lines: vec!["Error: API connection failed".into()],
            seconds_since_output: 0.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        match state {
            AgentState::Errored { error_hint, .. } => {
                assert!(error_hint.unwrap().contains("API connection failed"));
            }
            _ => panic!("Expected Errored state"),
        }
    }
test_detect_process_exit_signal function · rust · L577-L596 (20 LOC)
src/agent/detector.rs
    fn test_detect_process_exit_signal() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: Some(ProcessExit {
                exit_code: None,
                signal: true,
            }),
            screen_lines: vec![],
            seconds_since_output: 0.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        match state {
            AgentState::Errored { error_hint, .. } => {
                assert_eq!(error_hint.unwrap(), "Killed by signal");
            }
            _ => panic!("Expected Errored state"),
        }
    }
Repobility — the code-quality scanner for AI-generated software · https://repobility.com
test_detect_process_exit_none_no_signal function · rust · L599-L613 (15 LOC)
src/agent/detector.rs
    fn test_detect_process_exit_none_no_signal() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: Some(ProcessExit {
                exit_code: None,
                signal: false,
            }),
            screen_lines: vec![],
            seconds_since_output: 0.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        assert!(matches!(state, AgentState::Completed { .. }));
    }
test_detect_tool_approval function · rust · L616-L639 (24 LOC)
src/agent/detector.rs
    fn test_detect_tool_approval() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec![
                "I'll edit the file now.".into(),
                "".into(),
                "Allow Edit to src/main.rs? [Y/n]".into(),
            ],
            seconds_since_output: 1.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        match state {
            AgentState::WaitingForInput {
                prompt_type: PromptType::ToolApproval { tool_name },
                ..
            } => {
                assert_eq!(tool_name, "Edit");
            }
            _ => panic!("Expected WaitingForInput(ToolApproval), got {state:?}"),
        }
    }
test_detect_tool_approval_yn_lowercase function · rust · L642-L654 (13 LOC)
src/agent/detector.rs
    fn test_detect_tool_approval_yn_lowercase() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec!["Proceed? [y/N]".into()],
            seconds_since_output: 1.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        // Should detect as waiting (the [y/N] pattern matches)
        assert!(matches!(state, AgentState::WaitingForInput { .. }));
    }
test_detect_input_prompt function · rust · L657-L674 (18 LOC)
src/agent/detector.rs
    fn test_detect_input_prompt() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec!["some output".into(), ">".into()],
            seconds_since_output: 1.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        assert!(matches!(
            state,
            AgentState::WaitingForInput {
                prompt_type: PromptType::InputPrompt,
                ..
            }
        ));
    }
test_detect_question function · rust · L677-L694 (18 LOC)
src/agent/detector.rs
    fn test_detect_question() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec!["Would you like to proceed with this change?".into()],
            seconds_since_output: 1.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        assert!(matches!(
            state,
            AgentState::WaitingForInput {
                prompt_type: PromptType::Question,
                ..
            }
        ));
    }
test_detect_idle function · rust · L697-L708 (12 LOC)
src/agent/detector.rs
    fn test_detect_idle() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec!["some old output".into()],
            seconds_since_output: 5.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        assert!(matches!(state, AgentState::Idle { .. }));
    }
test_detect_running function · rust · L711-L722 (12 LOC)
src/agent/detector.rs
    fn test_detect_running() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec!["working on things...".into()],
            seconds_since_output: 0.5,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        assert!(matches!(state, AgentState::Running { .. }));
    }
test_detect_running_from_spawning function · rust · L725-L736 (12 LOC)
src/agent/detector.rs
    fn test_detect_running_from_spawning() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec!["first output".into()],
            seconds_since_output: 0.1,
            current_state: &AgentState::Spawning { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        assert!(matches!(state, AgentState::Running { .. }));
    }
Source: Repobility analyzer · https://repobility.com
test_hysteresis_preserves_timestamp function · rust · L739-L757 (19 LOC)
src/agent/detector.rs
    fn test_hysteresis_preserves_timestamp() {
        let original_since = Utc::now() - chrono::Duration::seconds(10);
        let patterns = default_patterns();
        let current = AgentState::Running {
            since: original_since,
        };
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec![],
            seconds_since_output: 0.5,
            current_state: &current,
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        match state {
            AgentState::Running { since } => assert_eq!(since, original_since),
            _ => panic!("Expected Running with original timestamp"),
        }
    }
test_hysteresis_idle_preserves_timestamp function · rust · L760-L778 (19 LOC)
src/agent/detector.rs
    fn test_hysteresis_idle_preserves_timestamp() {
        let original_since = Utc::now() - chrono::Duration::seconds(30);
        let patterns = default_patterns();
        let current = AgentState::Idle {
            since: original_since,
        };
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec!["old".into()],
            seconds_since_output: 10.0,
            current_state: &current,
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        match state {
            AgentState::Idle { since } => assert_eq!(since, original_since),
            _ => panic!("Expected Idle with original timestamp"),
        }
    }
test_hysteresis_waiting_preserves_timestamp function · rust · L781-L802 (22 LOC)
src/agent/detector.rs
    fn test_hysteresis_waiting_preserves_timestamp() {
        let original_since = Utc::now() - chrono::Duration::seconds(5);
        let patterns = default_patterns();
        let current = AgentState::WaitingForInput {
            since: original_since,
            prompt_type: PromptType::ToolApproval {
                tool_name: "Edit".into(),
            },
        };
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec!["Allow Edit to foo.rs? [Y/n]".into()],
            seconds_since_output: 1.0,
            current_state: &current,
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        match &state {
            AgentState::WaitingForInput { since, .. } => assert_eq!(*since, original_since),
            _ => panic!("Expected WaitingForInput with original timestamp"),
        }
    }
test_terminal_state_not_overridden function · rust · L805-L820 (16 LOC)
src/agent/detector.rs
    fn test_terminal_state_not_overridden() {
        let patterns = default_patterns();
        let current = AgentState::Completed {
            at: Utc::now(),
            exit_code: Some(0),
        };
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec!["some output".into()],
            seconds_since_output: 0.5,
            current_state: &current,
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        assert!(matches!(state, AgentState::Completed { .. }));
    }
test_process_exit_overrides_screen_patterns function · rust · L823-L838 (16 LOC)
src/agent/detector.rs
    fn test_process_exit_overrides_screen_patterns() {
        let patterns = default_patterns();
        // Even though screen shows a tool approval prompt, process exit takes priority
        let signals = DetectionSignals {
            process_exited: Some(ProcessExit {
                exit_code: Some(0),
                signal: false,
            }),
            screen_lines: vec!["Allow Edit to foo.rs? [Y/n]".into()],
            seconds_since_output: 0.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        assert!(matches!(state, AgentState::Completed { .. }));
    }
test_extract_error_hint_last_line function · rust · L843-L851 (9 LOC)
src/agent/detector.rs
    fn test_extract_error_hint_last_line() {
        let lines = vec![
            "some output".into(),
            "Error: connection refused".into(),
            "".into(),
        ];
        let hint = extract_error_hint(&lines);
        assert_eq!(hint.unwrap(), "Error: connection refused");
    }
test_extract_error_hint_truncated function · rust · L854-L860 (7 LOC)
src/agent/detector.rs
    fn test_extract_error_hint_truncated() {
        let long_line = "x".repeat(100);
        let lines = vec![long_line];
        let hint = extract_error_hint(&lines).unwrap();
        assert_eq!(hint.len(), 80); // 77 chars + "..."
        assert!(hint.ends_with("..."));
    }
test_extract_error_hint_empty function · rust · L863-L866 (4 LOC)
src/agent/detector.rs
    fn test_extract_error_hint_empty() {
        let lines: Vec<String> = vec!["".into(), "  ".into()];
        assert!(extract_error_hint(&lines).is_none());
    }
All rows above produced by Repobility · https://repobility.com
test_question_detection function · rust · L871-L878 (8 LOC)
src/agent/detector.rs
    fn test_question_detection() {
        assert!(detect_question(&["Are you sure?".into()]));
        assert!(detect_question(&["".into(), "Continue?".into(), "".into()]));
        // Single "?" is not a question (too short)
        assert!(!detect_question(&["?".into()]));
        // Empty lines only
        assert!(!detect_question(&["".into()]));
    }
test_ask_user_question_detection function · rust · L883-L894 (12 LOC)
src/agent/detector.rs
    fn test_ask_user_question_detection() {
        let patterns = default_patterns();
        let lines = vec![
            "Format: How should I format the output?".into(),
            "❯ 1. Summary - Brief overview".into(),
            "  2. Detailed - Full explanation".into(),
            "  3. Type something else...".into(),
        ];
        let result = detect_ask_user_question(&patterns, &lines);
        assert!(result.is_some());
        assert!(result.unwrap().contains("How should I format"));
    }
test_ask_user_question_without_cursor function · rust · L897-L907 (11 LOC)
src/agent/detector.rs
    fn test_ask_user_question_without_cursor() {
        let patterns = default_patterns();
        let lines = vec![
            "Which approach do you prefer?".into(),
            "  1. Option A - First approach".into(),
            "  2. Option B - Second approach".into(),
        ];
        let result = detect_ask_user_question(&patterns, &lines);
        assert!(result.is_some());
        assert!(result.unwrap().contains("Which approach"));
    }
test_ask_user_question_too_few_options function · rust · L910-L916 (7 LOC)
src/agent/detector.rs
    fn test_ask_user_question_too_few_options() {
        let patterns = default_patterns();
        // Only 1 option line — not enough for AskUserQuestion
        let lines = vec!["Some question?".into(), "  1. Only option".into()];
        let result = detect_ask_user_question(&patterns, &lines);
        assert!(result.is_none());
    }
test_ask_user_question_in_detect_state function · rust · L919-L943 (25 LOC)
src/agent/detector.rs
    fn test_ask_user_question_in_detect_state() {
        let patterns = default_patterns();
        let signals = DetectionSignals {
            process_exited: None,
            screen_lines: vec![
                "How should we proceed?".into(),
                "❯ 1. Refactor - Clean up the code".into(),
                "  2. Leave as-is - Skip changes".into(),
                "  3. Type something else...".into(),
            ],
            seconds_since_output: 1.0,
            current_state: &AgentState::Running { since: Utc::now() },
            idle_timeout_secs: 3,
        };
        let state = detect_state(&patterns, &signals);
        match state {
            AgentState::WaitingForInput {
                prompt_type: PromptType::AskUserQuestion { question },
                ..
            } => {
                assert!(question.contains("How should we proceed"));
            }
            _ => panic!("Expected WaitingForInput(AskUserQuestion), got {state:?}"),
        }
   
test_input_prompt_detection function · rust · L948-L962 (15 LOC)
src/agent/detector.rs
    fn test_input_prompt_detection() {
        let patterns = default_patterns();
        assert!(detect_input_prompt(&patterns, &[">".into()]));
        assert!(detect_input_prompt(&patterns, &["> ".into()]));
        assert!(detect_input_prompt(&patterns, &["$".into()]));
        assert!(detect_input_prompt(
            &patterns,
            &["some output".into(), "$ ".into()]
        ));
        // Not a prompt
        assert!(!detect_input_prompt(
            &patterns,
            &["working on code...".into()]
        ));
    }
test_extract_screen_lines_empty_screen function · rust · L967-L972 (6 LOC)
src/agent/detector.rs
    fn test_extract_screen_lines_empty_screen() {
        let parser = vt100::Parser::new(24, 80, 0);
        let lines = extract_screen_lines(parser.screen(), 5);
        // Empty screen with contents() returns empty string, so no lines
        assert!(lines.is_empty());
    }
test_extract_screen_lines_with_content function · rust · L975-L981 (7 LOC)
src/agent/detector.rs
    fn test_extract_screen_lines_with_content() {
        let mut parser = vt100::Parser::new(24, 80, 0);
        parser.process(b"Hello, world!\r\nSecond line\r\nThird line");
        let lines = extract_screen_lines(parser.screen(), 3);
        // We should get the bottom 3 lines from the content
        assert_eq!(lines.len(), 3);
    }
All rows scored by the Repobility analyzer (https://repobility.com)
test_extract_screen_lines_content_fewer_than_requested function · rust · L984-L991 (8 LOC)
src/agent/detector.rs
    fn test_extract_screen_lines_content_fewer_than_requested() {
        let mut parser = vt100::Parser::new(24, 80, 0);
        parser.process(b"One line");
        let lines = extract_screen_lines(parser.screen(), 100);
        // Only 1 line of content exists
        assert_eq!(lines.len(), 1);
        assert_eq!(lines[0], "One line");
    }
test_extract_screen_lines_returns_bottom_n function · rust · L994-L1001 (8 LOC)
src/agent/detector.rs
    fn test_extract_screen_lines_returns_bottom_n() {
        let mut parser = vt100::Parser::new(24, 80, 0);
        parser.process(b"Line 1\r\nLine 2\r\nLine 3\r\nLine 4\r\nLine 5");
        let lines = extract_screen_lines(parser.screen(), 2);
        assert_eq!(lines.len(), 2);
        assert_eq!(lines[0], "Line 4");
        assert_eq!(lines[1], "Line 5");
    }
test_debounce_requires_two_ticks function · rust · L1006-L1019 (14 LOC)
src/agent/detector.rs
    fn test_debounce_requires_two_ticks() {
        let mut debounce = DetectionDebounce::new();
        let current = AgentState::Running { since: Utc::now() };
        let waiting = AgentState::WaitingForInput {
            prompt_type: PromptType::InputPrompt,
            since: Utc::now(),
        };

        // First tick — should not transition yet
        assert!(debounce.process(waiting.clone(), &current).is_none());

        // Second tick — should transition now
        assert!(debounce.process(waiting, &current).is_some());
    }
page 1 / 17next ›