aboutsummaryrefslogtreecommitdiff
path: root/src/detect
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-31 03:00:46 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-31 03:04:20 +0300
commit3acd499ffb1119e8032bbcba3f1f46d4ff5f3da9 (patch)
tree4e30e82ccbc821e8930b03addfd1542d91ee8705 /src/detect
parent4e1fbf410b844749dcddae775806e1cce01ef442 (diff)
fix: keep codex visible approval review working
Diffstat (limited to 'src/detect')
-rw-r--r--src/detect/agents/codex.rs27
-rw-r--r--src/detect/mod.rs24
2 files changed, 45 insertions, 6 deletions
diff --git a/src/detect/agents/codex.rs b/src/detect/agents/codex.rs
index 0d23d4cb..50430aa4 100644
--- a/src/detect/agents/codex.rs
+++ b/src/detect/agents/codex.rs
@@ -49,11 +49,20 @@ pub(super) fn has_visible_working(content: &str) -> bool {
}
fn has_codex_visible_working_without_prompt(content: &str) -> bool {
- content
- .lines()
- .rev()
- .find(|line| !line.trim().is_empty())
- .is_some_and(codex_live_working_line)
+ let mut recent_lines = content.lines().rev().filter(|line| !line.trim().is_empty());
+ let Some(last_line) = recent_lines.next() else {
+ return false;
+ };
+
+ if codex_live_working_line(last_line) {
+ return true;
+ }
+
+ codex_status_detail_line(last_line)
+ && recent_lines
+ .take(4)
+ .find(|line| codex_block_marker_line(line))
+ .is_some_and(codex_live_working_line)
}
fn has_codex_strong_blocked_prompt(lower_content: &str) -> bool {
@@ -113,10 +122,12 @@ fn codex_working_status_line(line: &str) -> bool {
}
let trimmed = line.trim_start();
+ let lower = trimmed.to_lowercase();
trimmed.starts_with('•')
&& (trimmed.contains("Working (")
|| trimmed.contains("Waiting for background terminal (")
- || trimmed.contains("Reviewing approval request (")
+ || lower.contains("reviewing approval request (")
+ || (lower.contains("reviewing ") && lower.contains(" approval requests ("))
|| trimmed.contains("Booting MCP server:"))
}
@@ -146,6 +157,10 @@ fn codex_block_marker_line(line: &str) -> bool {
line.starts_with('•') || line.starts_with('■') || line.starts_with('✗') || line.starts_with('✓')
}
+fn codex_status_detail_line(line: &str) -> bool {
+ line.trim_start().starts_with('└')
+}
+
fn codex_queued_input_header_line(line: &str) -> bool {
let trimmed = line.trim_start();
if !trimmed.starts_with('•') {
diff --git a/src/detect/mod.rs b/src/detect/mod.rs
index 6173415b..cf600f51 100644
--- a/src/detect/mod.rs
+++ b/src/detect/mod.rs
@@ -1212,6 +1212,30 @@ mod tests {
}
#[test]
+ fn codex_reviewing_approval_request_without_prompt_is_visible_working() {
+ let detection = detect_agent(
+ Some(Agent::Codex),
+ "• Running git push --force-with-lease origin codex/ci-flake-diagnostics\n\n• Reviewing approval request (2m 53s • esc to interrupt)\n └ /bin/zsh -lc 'git push --force-with-lease origin codex/ci-flake-diagnostics'",
+ );
+
+ assert_eq!(detection.state, AgentState::Working);
+ assert!(detection.visible_working);
+ assert!(!detection.visible_idle);
+ }
+
+ #[test]
+ fn codex_reviewing_multiple_approval_requests_is_visible_working() {
+ let detection = detect_agent(
+ Some(Agent::Codex),
+ "• Reviewing 2 approval requests (0s • esc to interrupt)\n\n\n› Summarize recent commits\n\n ~/Projects/herdr · master",
+ );
+
+ assert_eq!(detection.state, AgentState::Working);
+ assert!(detection.visible_working);
+ assert!(!detection.visible_idle);
+ }
+
+ #[test]
fn codex_booting_mcp_server_is_visible_working() {
let detection = detect_agent(
Some(Agent::Codex),