diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-30 23:54:41 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-30 23:54:41 +0300 |
| commit | d477341e6af816ff4396042b084a0378ef437b4a (patch) | |
| tree | e332b6f7a0d23d9effd21c3ca8ab27698ed83444 /src/detect/agents/mod.rs | |
| parent | 8df1639048529b383358000879b5ee078a90b9f9 (diff) | |
refactor: split agent detection by agent
Move screen detection into per-agent modules and keep visible-state arbitration centralized in terminal state.
Tighten Codex prompt-scoped working detection and Claude hook/screen recovery for stale blocked and idle reports.
Add a focused just recipe for single-test runs.
refs #349
refs #352
Diffstat (limited to 'src/detect/agents/mod.rs')
| -rw-r--r-- | src/detect/agents/mod.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/detect/agents/mod.rs b/src/detect/agents/mod.rs new file mode 100644 index 00000000..87b4043f --- /dev/null +++ b/src/detect/agents/mod.rs @@ -0,0 +1,86 @@ +pub(super) mod amp; +pub(super) mod antigravity; +pub(super) mod claude_code; +pub(super) mod cline; +pub(super) mod codex; +pub(super) mod cursor; +pub(super) mod droid; +pub(super) mod gemini; +pub(super) mod github_copilot; +pub(super) mod grok; +pub(super) mod hermes; +pub(super) mod kimi; +pub(super) mod kiro; +pub(super) mod opencode; +pub(super) mod pi; +pub(super) mod qodercli; + +use super::{Agent, AgentDetection, AgentState}; + +pub(super) fn detect(agent: Agent, screen_content: &str) -> AgentDetection { + let state = match agent { + Agent::Pi => pi::detect(screen_content), + Agent::Claude => claude_code::detect(screen_content), + Agent::Codex => codex::detect(screen_content), + Agent::Gemini => gemini::detect(screen_content), + Agent::Cursor => cursor::detect(screen_content), + Agent::Antigravity => antigravity::detect(screen_content), + Agent::Cline => cline::detect(screen_content), + Agent::OpenCode => opencode::detect(screen_content), + Agent::GithubCopilot => github_copilot::detect(screen_content), + Agent::Kimi => kimi::detect(screen_content), + Agent::Kiro => kiro::detect(screen_content), + Agent::Droid => droid::detect(screen_content), + Agent::Amp => amp::detect(screen_content), + Agent::Grok => grok::detect(screen_content), + Agent::Hermes => hermes::detect(screen_content), + Agent::Qodercli => qodercli::detect(screen_content), + }; + + AgentDetection { + state, + visible_blocker: has_visible_blocker(agent, screen_content, state), + visible_idle: has_visible_idle(agent, screen_content, state), + visible_working: has_visible_working(agent, screen_content, state), + } +} + +fn has_visible_blocker(agent: Agent, content: &str, state: AgentState) -> bool { + if state != AgentState::Blocked { + return false; + } + + match agent { + // Strong visible blockers are opt-in because this flag can override + // hook authority. Plain blocked heuristics remain valid fallback state, + // but they must not become hook overrides unless the current UI chrome + // is known to be structural and live. + Agent::Claude => claude_code::has_visible_blocker(content), + Agent::Codex => codex::has_visible_blocker(content), + _ => false, + } +} + +fn has_visible_idle(agent: Agent, content: &str, state: AgentState) -> bool { + if state != AgentState::Idle { + return false; + } + + match agent { + Agent::Claude => claude_code::has_prompt_box(content), + Agent::Codex => codex::has_prompt(content), + _ => false, + } +} + +fn has_visible_working(agent: Agent, content: &str, state: AgentState) -> bool { + if state != AgentState::Working { + return false; + } + + match agent { + Agent::Claude => claude_code::has_working_chrome(content), + Agent::Codex => codex::has_visible_working(content), + _ => false, + } +} |
