pub(crate) const BLOCKED_STATUS_NEEDLE: &str = "[BLOCKED]";
pub(crate) const BLOCKED_LEFT_NEEDLE: &str = "blocked";
pub(crate) const TOOLS_DISABLED_NEEDLE: &str = "tools disabled";
pub(crate) const RECOVERY_NEEDLE: &str = "recovery";
pub(crate) fn right_status_is_blocked(right_status: &str) -> bool {
right_status.contains(BLOCKED_STATUS_NEEDLE)
}
pub(crate) fn left_status_is_blocked(left_status: &str) -> bool {
left_status.to_ascii_lowercase().contains(BLOCKED_LEFT_NEEDLE)
}
pub(crate) fn left_status_mentions_tools_disabled(left_status: &str) -> bool {
left_status.to_ascii_lowercase().contains(TOOLS_DISABLED_NEEDLE)
}
pub(crate) fn left_status_is_recovery(left_status: &str) -> bool {
let lowered = left_status.to_ascii_lowercase();
lowered.contains(RECOVERY_NEEDLE) || lowered.contains(TOOLS_DISABLED_NEEDLE)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn right_status_needle_matches_blocked_chip_only() {
assert!(right_status_is_blocked("[BLOCKED] 84% context left"));
assert!(!right_status_is_blocked("84% context left"));
assert!(!right_status_is_blocked("blocked 84% context left"));
}
#[test]
fn left_status_needle_is_case_insensitive() {
assert!(left_status_is_blocked("Blocked — Type 'continue' to retry..."));
assert!(left_status_is_blocked("turn blocked by policy"));
assert!(!left_status_is_blocked("Running tool: edit_file"));
assert!(!left_status_is_blocked(""));
}
#[test]
fn recovery_needles_match_recovery_wording() {
assert!(left_status_is_recovery("Recovery: tools disabled..."));
assert!(left_status_is_recovery("recovery pass running"));
assert!(left_status_mentions_tools_disabled("Recovery: tools disabled..."));
assert!(!left_status_is_recovery("Running command: ls"));
}
}