diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-07 22:41:21 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-07 22:41:54 +0300 |
| commit | 2e9f030681b694d2e60e809724bfd7f6caa50a5a (patch) | |
| tree | 4468063b93b0c5fd7843ce0a76adf66a9f5b178b /src/detect | |
| parent | 6f459691056b68c2c99d8341b5f8dd4b811a53c1 (diff) | |
fix: scope codex blocked prompts to live prompt region
Diffstat (limited to 'src/detect')
| -rw-r--r-- | src/detect/agents/codex.rs | 19 | ||||
| -rw-r--r-- | src/detect/mod.rs | 10 |
2 files changed, 23 insertions, 6 deletions
diff --git a/src/detect/agents/codex.rs b/src/detect/agents/codex.rs index e00d0a28..9870bca6 100644 --- a/src/detect/agents/codex.rs +++ b/src/detect/agents/codex.rs @@ -1,14 +1,14 @@ use super::super::{has_confirmation_prompt, has_interrupt_pattern, AgentState}; pub(super) fn detect(content: &str) -> AgentState { - let lower = content.to_lowercase(); - // Strong blocked patterns are structural Codex UI chrome, so they can win // even when the prompt region is visible. - if has_codex_strong_blocked_prompt(&lower) { + if has_codex_strong_blocked_prompt(content) { return AgentState::Blocked; } + let lower = content.to_lowercase(); + // Working if has_codex_working_status_at_current_prompt(content) { return AgentState::Working; @@ -35,8 +35,7 @@ pub(super) fn detect(content: &str) -> AgentState { } pub(super) fn has_visible_blocker(content: &str) -> bool { - let lower = content.to_lowercase(); - has_codex_strong_blocked_prompt(&lower) + has_codex_strong_blocked_prompt(content) } pub(super) fn has_prompt(content: &str) -> bool { @@ -84,7 +83,15 @@ fn has_codex_visible_working_without_prompt(content: &str) -> bool { .is_some_and(codex_live_working_line) } -fn has_codex_strong_blocked_prompt(lower_content: &str) -> bool { +fn has_codex_strong_blocked_prompt(content: &str) -> bool { + let lines: Vec<&str> = content.lines().collect(); + let live_region = lines + .iter() + .rposition(|line| codex_prompt_line(line)) + .map(|prompt_index| lines[prompt_index + 1..].join("\n")) + .unwrap_or_else(|| content.to_string()); + let lower_content = live_region.to_lowercase(); + lower_content.contains("press enter to confirm or esc to cancel") || lower_content.contains("enter to submit answer") || lower_content.contains("enter to submit all") diff --git a/src/detect/mod.rs b/src/detect/mod.rs index 902ae999..0c7ad943 100644 --- a/src/detect/mod.rs +++ b/src/detect/mod.rs @@ -1472,6 +1472,16 @@ mod tests { } #[test] + fn codex_replayed_allow_command_text_above_prompt_is_idle() { + let screen = "• Ran grep for blockers\n └ The phrase allow command? appears in our discussion above.\n\n■ Conversation interrupted - tell the model what to do differently. Something went wrong? Hit `/feedback` to report the issue.\n\n\n› Write tests for @filename\n\n gpt-5.5 high · ~/.herdr/worktrees/herdr/plugin-v1 · plugin-v1 · Context 18% used · 5h 93% left · weekly 71% left"; + let detection = detect_agent(Some(Agent::Codex), screen); + + assert_eq!(detection.state, AgentState::Idle); + assert!(detection.visible_idle); + assert!(!detection.visible_blocker); + } + + #[test] fn codex_generic_confirmation_prompt_is_not_visible_blocker() { let detection = detect_agent( Some(Agent::Codex), |
