aboutsummaryrefslogtreecommitdiff
path: root/src/detect
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-01 23:47:40 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-01 23:47:40 +0300
commit9709ba6938bd720fea6d8dd15346adf9db2b7f4b (patch)
tree4da522fa3a5e43ef25bef2a12b12734caa839688 /src/detect
parent36a4608603a82dbf32ec8a013dd47047cf02c6a3 (diff)
fix: detect kiro subagent approvals
refs #388
Diffstat (limited to 'src/detect')
-rw-r--r--src/detect/agents/kiro.rs32
-rw-r--r--src/detect/mod.rs6
2 files changed, 31 insertions, 7 deletions
diff --git a/src/detect/agents/kiro.rs b/src/detect/agents/kiro.rs
index 5ef1fbca..f40b9bcb 100644
--- a/src/detect/agents/kiro.rs
+++ b/src/detect/agents/kiro.rs
@@ -3,16 +3,11 @@ use super::super::AgentState;
/// Kiro CLI detection.
///
/// Kiro exposes reliable working and idle terminal markers. Tool approval
-/// prompts render with a stable "requires approval" line and an action menu.
+/// prompts render with stable approval wording and an action menu.
pub(super) fn detect(content: &str) -> AgentState {
let lower = content.to_lowercase();
- let has_approval_request = lower.contains("requires approval");
- let has_approval_actions = lower.contains("yes, single permission")
- || lower.contains("trust, always allow")
- || lower.contains("no (tab to edit)")
- || lower.contains("esc to close");
- if has_approval_request && has_approval_actions {
+ if has_kiro_blocked_prompt(&lower) {
return AgentState::Blocked;
}
@@ -25,6 +20,29 @@ pub(super) fn detect(content: &str) -> AgentState {
AgentState::Idle
}
+fn has_kiro_blocked_prompt(lower_content: &str) -> bool {
+ has_tool_approval_prompt(lower_content) || has_subagent_approval_prompt(lower_content)
+}
+
+fn has_tool_approval_prompt(lower_content: &str) -> bool {
+ let has_approval_request = lower_content.contains("requires approval");
+ let has_approval_actions = lower_content.contains("yes, single permission")
+ || lower_content.contains("trust, always allow")
+ || lower_content.contains("no (tab to edit)")
+ || lower_content.contains("esc to close");
+ has_approval_request && has_approval_actions
+}
+
+fn has_subagent_approval_prompt(lower_content: &str) -> bool {
+ let has_approval_request = (lower_content.contains("tool approval")
+ || lower_content.contains("tool approvals"))
+ && lower_content.contains("pending from subagents");
+ let has_approval_actions = lower_content.contains("approve all pending")
+ || lower_content.contains("configure individually")
+ || lower_content.contains("exit (cancel subagents)");
+ has_approval_request && has_approval_actions
+}
+
fn has_kiro_tool_spinner(content: &str) -> bool {
content.lines().any(|line| {
let trimmed = line.trim_start();
diff --git a/src/detect/mod.rs b/src/detect/mod.rs
index b9806b19..e5f84628 100644
--- a/src/detect/mod.rs
+++ b/src/detect/mod.rs
@@ -1900,6 +1900,12 @@ mod tests {
}
#[test]
+ fn kiro_blocked_on_subagent_tool_approval_prompt() {
+ let screen = " Please delegate to a sub-agent to search the web\n\n● Orchestrating (1 agent)\n esc to cancel\n ctrl+g open agent monitor\n ● web-research kiro_default ⚠ tool approval needed\n\n ◐ Tasks · 1 done · 2 remaining ctrl+x to expand\n──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n ⚠ 3 tool approvals pending from subagents\n ❯ (a) Approve all pending\n (f) Approve all pending and auto-approve all future requests\n (c) Configure individually (agent monitor)\n (x) Exit (cancel subagents) %";
+ assert_eq!(detect_state(Some(Agent::Kiro), screen), AgentState::Blocked);
+ }
+
+ #[test]
fn kiro_does_not_treat_stale_failure_spinner_as_working() {
let screen = "● 1 MCP failure — see /mcp\n─────────────────────────────────────────────────────\nKiro · auto · ◔ 6%\n\n ask a question or describe a task ↵";
assert_eq!(detect_state(Some(Agent::Kiro), screen), AgentState::Idle);