fix: detect kiro subagent approvals

refs #388
This commit is contained in:
Ogulcan Celik 2026-06-01 23:47:40 +03:00
parent 36a4608603
commit 9709ba6938
3 changed files with 32 additions and 7 deletions

View File

@ -10,6 +10,7 @@
- Native agent session restore is now enabled by default for supported panes with current official integrations. Set `[session] resume_agents_on_restore = false` to disable it.
### Fixed
- Kiro sub-agent tool approval prompts are now detected as blocked instead of working. (#388)
- Pane input no longer waits behind the PTY actor's idle read poll, restoring responsive typing at quiet shell prompts. (#379)
- Pane apps that query OSC 4 ANSI palette colors now receive the active terminal palette response, so OpenCode and similar TUIs can enable system-theme behavior inside Herdr. (#387)
- Pane text selection now derives its highlight colors from the host terminal or active Herdr palette instead of forcing the theme's blue accent. (#298)

View File

@ -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();

View File

@ -1899,6 +1899,12 @@ mod tests {
assert_eq!(detect_state(Some(Agent::Kiro), screen), AgentState::Blocked);
}
#[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 ↵";