use super::*;
pub(super) fn subagents_safe_output(result: &ToolResult) -> String {
if let Ok(output) = serde_json::from_str::<SubagentsOutput>(&result.content) {
let mut lines = vec![subagents_summary_line(
output.summary.total as u64,
output.summary.completed as u64,
output.summary.failed as u64,
output.summary.total_tokens,
)];
for task in output.results.iter().take(10) {
let status = match task.status {
crate::subagents::SubagentStatus::Completed => "completed",
crate::subagents::SubagentStatus::Failed => "failed",
};
let mut parts = vec![format!("{}={status}", task.id)];
if let Some(identity) = task.identity.as_deref().filter(|value| !value.is_empty()) {
parts.push(format!("identity={}", redact_sensitive_text(identity)));
}
if let Some(session_path) = task.session_path.as_ref() {
parts.push(format!(
"session_path={}",
redact_sensitive_text(&session_path.display().to_string())
));
}
if task.output_truncated {
parts.push("output_truncated=true".to_string());
}
if let Some(tokens) = task.total_tokens {
parts.push(format!("total_tokens={tokens}"));
}
lines.push(parts.join(" "));
}
return lines.join("\n");
}
let Some(summary) = result.metadata.get(meta::SUMMARY) else {
return "summary unavailable".to_string();
};
let total = summary
.get(meta::TOTAL)
.and_then(Value::as_u64)
.unwrap_or(0);
let completed = summary
.get(meta::COMPLETED)
.and_then(Value::as_u64)
.unwrap_or(0);
let failed = summary
.get(meta::FAILED)
.and_then(Value::as_u64)
.unwrap_or(0);
let total_tokens = summary.get(meta::TOTAL_TOKENS).and_then(Value::as_u64);
subagents_summary_line(total, completed, failed, total_tokens)
}
fn subagents_summary_line(
total: u64,
completed: u64,
failed: u64,
total_tokens: Option<u64>,
) -> String {
let mut parts = vec![
format!("total={total}"),
format!("completed={completed}"),
format!("failed={failed}"),
];
if let Some(total_tokens) = total_tokens {
parts.push(format!("total_tokens={total_tokens}"));
}
format!("summary: {}", parts.join(" "))
}
pub(super) fn subagent_identity_list(tasks: &[Value]) -> Option<String> {
let identities = tasks
.iter()
.enumerate()
.filter_map(|(index, task)| {
task.get(arg_key::IDENTITY)
.and_then(Value::as_str)
.map(|identity| format!("g{}={}", index + 1, redact_sensitive_text(identity)))
})
.collect::<Vec<_>>();
(!identities.is_empty()).then(|| identities.join(", "))
}