aboutsummaryrefslogtreecommitdiff
path: root/src/detect/agents/cursor.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-10 15:24:24 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-10 15:33:45 +0300
commit36a1b7f86444871f0c38ff36510a6e3c2eec48c6 (patch)
tree4a2d100eef7f26af7feaa93ce661423c3994c54e /src/detect/agents/cursor.rs
parent8d13492926829c5cf0ea42c8613344cd65ff59fa (diff)
feat: distribute agent detection manifests
Diffstat (limited to 'src/detect/agents/cursor.rs')
-rw-r--r--src/detect/agents/cursor.rs79
1 files changed, 0 insertions, 79 deletions
diff --git a/src/detect/agents/cursor.rs b/src/detect/agents/cursor.rs
deleted file mode 100644
index f0f00b9b..00000000
--- a/src/detect/agents/cursor.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-use super::super::AgentState;
-
-pub(super) fn detect(content: &str) -> AgentState {
- let lower = content.to_lowercase();
-
- // Blocked
- if has_visible_blocker(content) {
- return AgentState::Blocked;
- }
-
- // Working
- if lower.contains("ctrl+c to stop") {
- return AgentState::Working;
- }
- if has_cursor_spinner(content) {
- return AgentState::Working;
- }
-
- AgentState::Idle
-}
-
-pub(super) fn has_visible_blocker(content: &str) -> bool {
- let lower = content.to_lowercase();
- if lower.contains("waiting for approval")
- && lower.contains("run this command?")
- && (lower.contains("run (once) (y)") || lower.contains("skip (esc or n)"))
- {
- return true;
- }
-
- if lower.contains("(y) (enter)")
- || lower.contains("keep (n)")
- || lower.contains("skip (esc or n)")
- {
- return true;
- }
-
- content.lines().any(|line| {
- let line = line.trim().to_lowercase();
- let has_yes_action = line.contains("(y)");
- has_yes_action
- && (line.contains("allow")
- || line.contains("run (once)")
- || line.contains("→ run")
- || line.starts_with("run "))
- })
-}
-
-/// Cursor status line: spinner glyphs followed by a live action label.
-pub(in crate::detect) fn has_cursor_spinner(content: &str) -> bool {
- content.lines().any(|line| {
- let trimmed = line.trim_start();
- let mut chars = trimmed.chars();
- let Some(first) = chars.next() else {
- return false;
- };
- let rest = chars.as_str().trim_start();
-
- if matches!(first, '⬡' | '⬢') {
- return cursor_status_word_is_active(rest);
- }
-
- if ('\u{2800}'..='\u{28FF}').contains(&first) {
- let rest = rest.trim_start_matches(|c| ('\u{2800}'..='\u{28FF}').contains(&c));
- return cursor_status_word_is_active(rest.trim_start());
- }
-
- false
- })
-}
-
-fn cursor_status_word_is_active(rest: &str) -> bool {
- let Some(word) = rest.split_whitespace().next() else {
- return false;
- };
- word.trim_end_matches(|c: char| !c.is_alphabetic())
- .to_ascii_lowercase()
- .ends_with("ing")
-}