mirror of
https://github.com/aaif-goose/goose.git
synced 2026-07-03 14:10:03 +02:00
fix(summon): stop MOIM from telling models to sleep while waiting for tasks (#7377)
Signed-off-by: rabi <ramishra@redhat.com>
This commit is contained in:
@@ -330,10 +330,12 @@ impl SummonClient {
|
|||||||
"Load knowledge into your current context or discover available sources.\n\n\
|
"Load knowledge into your current context or discover available sources.\n\n\
|
||||||
Call with no arguments to list all available sources (subrecipes, recipes, skills, agents).\n\
|
Call with no arguments to list all available sources (subrecipes, recipes, skills, agents).\n\
|
||||||
Call with a source name to load its content into your context.\n\
|
Call with a source name to load its content into your context.\n\
|
||||||
For background tasks: load(source: \"task_id\", cancel: true) stops and returns output.\n\n\
|
For background tasks: load(source: \"task_id\") waits for the task and returns the result.\n\
|
||||||
|
To cancel a running task: load(source: \"task_id\", cancel: true) stops and returns output.\n\n\
|
||||||
Examples:\n\
|
Examples:\n\
|
||||||
- load() → Lists available sources\n\
|
- load() → Lists available sources\n\
|
||||||
- load(source: \"rust-patterns\") → Loads the rust-patterns skill"
|
- load(source: \"rust-patterns\") → Loads the rust-patterns skill\n\
|
||||||
|
- load(source: \"20260219_1\") → Waits for background task, then returns result"
|
||||||
.to_string(),
|
.to_string(),
|
||||||
schema.as_object().unwrap().clone(),
|
schema.as_object().unwrap().clone(),
|
||||||
)
|
)
|
||||||
@@ -880,7 +882,7 @@ impl SummonClient {
|
|||||||
|
|
||||||
// Wait for the running task to complete, keeping the tool call
|
// Wait for the running task to complete, keeping the tool call
|
||||||
// alive so notifications (subagent tool calls) stream in real time.
|
// alive so notifications (subagent tool calls) stream in real time.
|
||||||
let task = running.remove(task_id).unwrap();
|
let mut task = running.remove(task_id).unwrap();
|
||||||
drop(running);
|
drop(running);
|
||||||
|
|
||||||
let buffered = {
|
let buffered = {
|
||||||
@@ -896,45 +898,37 @@ impl SummonClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let description = task.description.clone();
|
tokio::select! {
|
||||||
let mut handle = task.handle;
|
result = &mut task.handle => {
|
||||||
|
let output = match result {
|
||||||
let (output, timed_out) = tokio::select! {
|
|
||||||
result = &mut handle => {
|
|
||||||
let s = match result {
|
|
||||||
Ok(Ok(s)) => s,
|
Ok(Ok(s)) => s,
|
||||||
Ok(Err(e)) => format!("Error: {}", e),
|
Ok(Err(e)) => format!("Error: {}", e),
|
||||||
Err(e) => format!("Task panicked: {}", e),
|
Err(e) => format!("Task panicked: {}", e),
|
||||||
};
|
};
|
||||||
(s, false)
|
|
||||||
|
return Ok(vec![Content::text(format!(
|
||||||
|
"# Background Task Result: {}\n\n\
|
||||||
|
**Task:** {}\n\
|
||||||
|
**Status:** ✓ Completed\n\
|
||||||
|
**Duration:** {} ({} turns)\n\n\
|
||||||
|
## Output\n\n{}",
|
||||||
|
task_id,
|
||||||
|
task.description,
|
||||||
|
round_duration(task.started_at.elapsed()),
|
||||||
|
task.turns.load(Ordering::Relaxed),
|
||||||
|
output
|
||||||
|
))]);
|
||||||
}
|
}
|
||||||
_ = tokio::time::sleep(Duration::from_secs(300)) => {
|
_ = tokio::time::sleep(Duration::from_secs(300)) => {
|
||||||
handle.abort();
|
self.background_tasks.lock().await.insert(task_id.to_string(), task);
|
||||||
("Task timed out waiting for completion (aborted after 5 min)".to_string(), true)
|
|
||||||
|
return Err(format!(
|
||||||
|
"Task '{task_id}' is still running after waiting 5 min. \
|
||||||
|
Use load(source: \"{task_id}\") to wait again, or \
|
||||||
|
load(source: \"{task_id}\", cancel: true) to stop."
|
||||||
|
));
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
let duration = task.started_at.elapsed();
|
|
||||||
let turns_taken = task.turns.load(Ordering::Relaxed);
|
|
||||||
let status = if timed_out {
|
|
||||||
"⏱ Timed out"
|
|
||||||
} else {
|
|
||||||
"✓ Completed"
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(vec![Content::text(format!(
|
|
||||||
"# Background Task Result: {}\n\n\
|
|
||||||
**Task:** {}\n\
|
|
||||||
**Status:** {}\n\
|
|
||||||
**Duration:** {} ({} turns)\n\n\
|
|
||||||
## Output\n\n{}",
|
|
||||||
task_id,
|
|
||||||
description,
|
|
||||||
status,
|
|
||||||
round_duration(duration),
|
|
||||||
turns_taken,
|
|
||||||
output
|
|
||||||
))]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(format!("Task '{}' not found.", task_id))
|
Err(format!("Task '{}' not found.", task_id))
|
||||||
@@ -1628,7 +1622,8 @@ impl SummonClient {
|
|||||||
.insert(task_id.clone(), task);
|
.insert(task_id.clone(), task);
|
||||||
|
|
||||||
Ok(vec![Content::text(format!(
|
Ok(vec![Content::text(format!(
|
||||||
"Task {} started in background: \"{}\"\nUse load(source: \"{}\") to wait for the result (it will block until complete).",
|
"Task {} started in background: \"{}\"\n\
|
||||||
|
Continue with other work. When you need the result, use load(source: \"{}\").",
|
||||||
task_id, description, task_id
|
task_id, description, task_id
|
||||||
))])
|
))])
|
||||||
}
|
}
|
||||||
@@ -1714,8 +1709,6 @@ impl McpClientTrait for SummonClient {
|
|||||||
let mut lines = vec!["Background tasks:".to_string()];
|
let mut lines = vec!["Background tasks:".to_string()];
|
||||||
let now = current_epoch_millis();
|
let now = current_epoch_millis();
|
||||||
|
|
||||||
let mut shortest_elapsed_secs: Option<u64> = None;
|
|
||||||
|
|
||||||
let mut sorted_running: Vec<_> = running.values().collect();
|
let mut sorted_running: Vec<_> = running.values().collect();
|
||||||
sorted_running.sort_by_key(|t| &t.id);
|
sorted_running.sort_by_key(|t| &t.id);
|
||||||
|
|
||||||
@@ -1723,10 +1716,6 @@ impl McpClientTrait for SummonClient {
|
|||||||
let elapsed = task.started_at.elapsed();
|
let elapsed = task.started_at.elapsed();
|
||||||
let idle_ms = now.saturating_sub(task.last_activity.load(Ordering::Relaxed));
|
let idle_ms = now.saturating_sub(task.last_activity.load(Ordering::Relaxed));
|
||||||
|
|
||||||
let elapsed_secs = elapsed.as_secs();
|
|
||||||
shortest_elapsed_secs =
|
|
||||||
Some(shortest_elapsed_secs.map_or(elapsed_secs, |s| s.min(elapsed_secs)));
|
|
||||||
|
|
||||||
lines.push(format!(
|
lines.push(format!(
|
||||||
"• {}: \"{}\" - running {}, {} turns, idle {}",
|
"• {}: \"{}\" - running {}, {} turns, idle {}",
|
||||||
task.id,
|
task.id,
|
||||||
@@ -1757,12 +1746,11 @@ impl McpClientTrait for SummonClient {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(shortest) = shortest_elapsed_secs {
|
if !running.is_empty() {
|
||||||
let sleep_secs = 300u64.saturating_sub(shortest).max(10);
|
lines.push(
|
||||||
lines.push(format!(
|
"\n→ Use load(source: \"<id>\") to wait for a task, or load(source: \"<id>\", cancel: true) to stop it"
|
||||||
"\n→ sleep {} to wait, or load(source: \"id\", cancel: true) to stop",
|
.to_string(),
|
||||||
sleep_secs
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(lines.join("\n"))
|
Some(lines.join("\n"))
|
||||||
|
|||||||
Reference in New Issue
Block a user