Converted all external tool calling to async
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
//! Agent stop — terminates a running agent while preserving its worktree.
|
||||
use crate::process_kill::{pids_matching, sigkill_pids_and_verify};
|
||||
use crate::slog;
|
||||
use crate::slog_error;
|
||||
use crate::slog_warn;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -40,7 +39,7 @@ impl AgentPool {
|
||||
|
||||
// Step 1: snapshot the worktree path (no status mutation yet).
|
||||
let worktree_info = {
|
||||
let agents = self.agents.lock().map_err(|e| e.to_string())?;
|
||||
let agents = self.agents.lock().await;
|
||||
let agent = agents
|
||||
.get(&key)
|
||||
.ok_or_else(|| format!("No agent '{agent_name}' for story '{story_id}'"))?;
|
||||
@@ -71,12 +70,12 @@ impl AgentPool {
|
||||
"[stop_agent] No worktree path recorded for '{key}'; cannot tree-kill, \
|
||||
falling back to portable_pty SIGHUP (likely no-op for claude-code)."
|
||||
);
|
||||
self.kill_child_for_key(&key);
|
||||
self.kill_child_for_key(&key).await;
|
||||
}
|
||||
|
||||
// Step 3: now safe to mutate. Status flip and handle abort.
|
||||
let (task_handle, tx) = {
|
||||
let mut agents = self.agents.lock().map_err(|e| e.to_string())?;
|
||||
let mut agents = self.agents.lock().await;
|
||||
let agent = agents
|
||||
.get_mut(&key)
|
||||
.ok_or_else(|| format!("No agent '{agent_name}' for story '{story_id}'"))?;
|
||||
@@ -107,7 +106,7 @@ impl AgentPool {
|
||||
|
||||
// Remove from map.
|
||||
{
|
||||
let mut agents = self.agents.lock().map_err(|e| e.to_string())?;
|
||||
let mut agents = self.agents.lock().await;
|
||||
agents.remove(&key);
|
||||
}
|
||||
|
||||
@@ -138,9 +137,7 @@ impl AgentPool {
|
||||
|
||||
// Snapshot active LLM agents without holding the lock during async stops.
|
||||
let snapshot: Vec<(String, String, PipelineStage)> = {
|
||||
let Ok(agents) = self.agents.lock() else {
|
||||
return;
|
||||
};
|
||||
let agents = self.agents.lock().await;
|
||||
agents
|
||||
.iter()
|
||||
.filter_map(|(key, a)| {
|
||||
@@ -197,14 +194,8 @@ impl AgentPool {
|
||||
///
|
||||
/// Called when a story is archived so that stale entries don't accumulate.
|
||||
/// Returns the number of entries removed.
|
||||
pub fn remove_agents_for_story(&self, story_id: &str) -> usize {
|
||||
let mut agents = match self.agents.lock() {
|
||||
Ok(a) => a,
|
||||
Err(e) => {
|
||||
slog_error!("[agents] Failed to lock pool for cleanup of '{story_id}': {e}");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
pub async fn remove_agents_for_story(&self, story_id: &str) -> usize {
|
||||
let mut agents = self.agents.lock().await;
|
||||
let prefix = format!("{story_id}:");
|
||||
let keys_to_remove: Vec<String> = agents
|
||||
.keys()
|
||||
@@ -229,30 +220,30 @@ mod tests {
|
||||
|
||||
// ── remove_agents_for_story tests ────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn remove_agents_for_story_removes_all_entries() {
|
||||
#[tokio::test]
|
||||
async fn remove_agents_for_story_removes_all_entries() {
|
||||
let pool = AgentPool::new_test(3001);
|
||||
pool.inject_test_agent("story_a", "coder-1", AgentStatus::Completed);
|
||||
pool.inject_test_agent("story_a", "qa", AgentStatus::Failed);
|
||||
pool.inject_test_agent("story_b", "coder-1", AgentStatus::Running);
|
||||
|
||||
let removed = pool.remove_agents_for_story("story_a");
|
||||
let removed = pool.remove_agents_for_story("story_a").await;
|
||||
assert_eq!(removed, 2, "should remove both agents for story_a");
|
||||
|
||||
let agents = pool.list_agents().unwrap();
|
||||
let agents = pool.list_agents().await.unwrap();
|
||||
assert_eq!(agents.len(), 1, "only story_b agent should remain");
|
||||
assert_eq!(agents[0].story_id, "story_b");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn remove_agents_for_story_returns_zero_when_no_match() {
|
||||
#[tokio::test]
|
||||
async fn remove_agents_for_story_returns_zero_when_no_match() {
|
||||
let pool = AgentPool::new_test(3001);
|
||||
pool.inject_test_agent("story_a", "coder-1", AgentStatus::Running);
|
||||
|
||||
let removed = pool.remove_agents_for_story("nonexistent");
|
||||
let removed = pool.remove_agents_for_story("nonexistent").await;
|
||||
assert_eq!(removed, 0);
|
||||
|
||||
let agents = pool.list_agents().unwrap();
|
||||
let agents = pool.list_agents().await.unwrap();
|
||||
assert_eq!(agents.len(), 1, "existing agents should not be affected");
|
||||
}
|
||||
|
||||
@@ -283,12 +274,12 @@ mod tests {
|
||||
pool.inject_test_agent("60_story_cleanup", "qa", AgentStatus::Completed);
|
||||
pool.inject_test_agent("61_story_other", "coder-1", AgentStatus::Running);
|
||||
|
||||
assert_eq!(pool.list_agents().unwrap().len(), 3);
|
||||
assert_eq!(pool.list_agents().await.unwrap().len(), 3);
|
||||
|
||||
move_story_to_done("60_story_cleanup").unwrap();
|
||||
pool.remove_agents_for_story("60_story_cleanup");
|
||||
pool.remove_agents_for_story("60_story_cleanup").await;
|
||||
|
||||
let remaining = pool.list_agents().unwrap();
|
||||
let remaining = pool.list_agents().await.unwrap();
|
||||
assert_eq!(
|
||||
remaining.len(),
|
||||
1,
|
||||
|
||||
Reference in New Issue
Block a user