use super::super::{assembler, tool_step};
use crate::prompt::notice::notice;
use crate::prompt::{Deps, Error};
use brazen::{Content, Role};
use std::path::Path;
pub(super) fn settle_crashed_window(
workspace: &Path,
agent_id: &str,
deps: &Deps<'_>,
) -> Result<(), Error> {
let worktree = crate::workspace::agent_worktree(workspace, agent_id);
if !worktree.exists() {
return Ok(());
}
let messages = assembler::transcript(&worktree)?;
let Some(window) = messages.iter().rposition(|m| m.role == Role::Assistant) else {
return Ok(());
};
if messages[window + 1..].iter().any(|m| m.role == Role::User) {
return Ok(());
}
let mut unanswered: std::collections::HashSet<&str> = messages[window]
.content
.iter()
.filter_map(|b| match b {
Content::ToolUse { id, .. } => Some(id.as_str()),
_ => None,
})
.collect();
for m in &messages[window + 1..] {
for b in &m.content {
if let Content::ToolResult { tool_use_id, .. } = b {
unanswered.remove(tool_use_id.as_str());
}
}
}
if unanswered.is_empty() {
return Ok(());
}
notice!(
"settling a crashed tool window on [{agent_id}] — {} unanswered \
invocation(s) recorded as died (ARCH §6, bl-4187)",
unanswered.len()
);
tool_step::settle::crashed(&worktree, agent_id, &messages[window].content, deps)
}