feat(subagent): add progress event handling and formatting for subagent execution

This commit is contained in:
asepharyana
2026-07-15 02:25:15 +07:00
parent 472c597c5e
commit 558908aef2
5 changed files with 52 additions and 7 deletions
+29 -3
View File
@@ -296,6 +296,17 @@ fn generate_workspace_tree(roots: &[std::path::PathBuf]) -> String {
out
}
fn format_subagent_progress(prefix: &str, text: &str) -> String {
let lines: Vec<&str> = text.lines().filter(|l| !l.trim().is_empty()).collect();
if lines.is_empty() {
format!("{prefix}...")
} else if lines.len() == 1 {
format!("{prefix}: {}", lines[0])
} else {
lines[lines.len() - 2..].join("\n")
}
}
/// Synchronous subagent entry point: run up to `ctx.max_steps` iterations
/// of the LLM tool loop.
///
@@ -369,6 +380,10 @@ pub fn run_subagent(ctx: &SubagentContext, tx: &mpsc::Sender<SubagentEvent>) ->
anyhow::bail!("subagent aborted by parent at step {step}");
}
let tx_clone = tx.clone();
let mut current_thinking = String::new();
let mut current_token = String::new();
// Use streaming API so the abort flag is checked per SSE event,
// making the subagent responsive to cancellation even during an
// LLM call (non-streaming would block for 10-30s unchecked).
@@ -377,13 +392,24 @@ pub fn run_subagent(ctx: &SubagentContext, tx: &mpsc::Sender<SubagentEvent>) ->
tdefs_opt.clone(),
Some(0.7),
Some(4096),
|_event| -> bool {
|event| -> bool {
// Check abort on every SSE event for responsive cancellation.
if ctx.abort_flag.as_ref().is_some_and(|f| f.load(std::sync::atomic::Ordering::SeqCst)) {
return false; // signals provider to abort
}
// We don't stream tokens to the UI for subagents — just
// need the assembled message at the end.
match event {
crate::app::runtime::stream::StreamEvent::Reasoning(text) => {
current_thinking.push_str(text);
let prog = format_subagent_progress("thinking", &current_thinking);
let _ = tx_clone.blocking_send(SubagentEvent::Progress(prog));
}
crate::app::runtime::stream::StreamEvent::Token(text) => {
current_token.push_str(text);
let prog = format_subagent_progress("replying", &current_token);
let _ = tx_clone.blocking_send(SubagentEvent::Progress(prog));
}
_ => {}
}
true
},
);
+1
View File
@@ -31,4 +31,5 @@ pub enum SubagentEvent {
#[allow(dead_code)]
output: String,
},
Progress(String),
}