use super::*;
use crate::multi_agent::mailbox::MailboxTask;
use crate::multi_agent::runtime::outcome::*;
#[test]
fn test_summarize_completed() {
let s = summarize_outcome(&RunOutcome::Completed);
assert_eq!(s, "task completed");
}
#[test]
fn test_summarize_failed() {
let outcome = RunOutcome::Failed {
error: "connection refused".to_string(),
};
let s = summarize_outcome(&outcome);
assert_eq!(s, "task failed: connection refused");
}
#[test]
fn test_summarize_max_turns() {
let outcome = RunOutcome::MaxTurnsExceeded { turns: 42 };
let s = summarize_outcome(&outcome);
assert!(s.contains("max turns exceeded"));
assert!(s.contains("42"));
}
#[test]
fn test_summarize_cancelled() {
let s = summarize_outcome(&RunOutcome::Cancelled);
assert_eq!(s, "cancelled");
}
fn text_delta(text: &str, agent_id: Option<&str>) -> agent_base::RuntimeEvent {
agent_base::RuntimeEvent::TextDelta {
session_id: agent_base::SessionId::new(1),
text: text.to_string(),
agent_id: agent_id.map(|s| s.to_string()),
trace_id: None,
}
}
fn tool_started(tool_name: &str) -> agent_base::RuntimeEvent {
agent_base::RuntimeEvent::ToolCallStarted {
session_id: agent_base::SessionId::new(1),
tool_name: tool_name.to_string(),
args_json: "{}".to_string(),
agent_id: None,
trace_id: None,
}
}
#[test]
fn test_build_child_result_completed_returns_final_text() {
let events = vec![text_delta("I couldn't ", None), text_delta("delete.", None)];
assert_eq!(
build_child_result(&RunOutcome::Completed, &events),
"I couldn't delete."
);
}
#[test]
fn test_build_child_result_completed_falls_back_when_no_text() {
assert_eq!(
build_child_result(&RunOutcome::Completed, &[]),
"task completed"
);
}
#[test]
fn test_extract_last_assistant_message_ignores_subagent_text() {
let events = vec![
tool_started("read_file"),
text_delta("root answer", None),
text_delta("grandchild", Some("root/child/grandchild")),
];
assert_eq!(extract_last_assistant_message(&events), "root answer");
}
#[test]
fn test_extract_last_assistant_message_skips_earlier_turns() {
let events = vec![
text_delta("thinking about this...", None),
tool_started("read_file"),
text_delta("Here is my final analysis.", None),
];
assert_eq!(
extract_last_assistant_message(&events),
"Here is my final analysis."
);
}
#[test]
fn test_extract_last_assistant_message_no_tool_calls() {
let events = vec![text_delta("I couldn't ", None), text_delta("delete.", None)];
assert_eq!(
extract_last_assistant_message(&events),
"I couldn't delete."
);
}
#[test]
fn test_build_child_result_failed_keeps_error() {
let outcome = RunOutcome::Failed {
error: "boom".to_string(),
};
assert_eq!(build_child_result(&outcome, &[]), "task failed: boom");
}
fn tool_finished(tool_name: &str, denied: bool) -> agent_base::RuntimeEvent {
agent_base::RuntimeEvent::ToolCallFinished {
session_id: agent_base::SessionId::new(1),
tool_name: tool_name.to_string(),
summary: "summary".to_string(),
agent_id: None,
trace_id: None,
denied,
details: None,
}
}
#[test]
fn test_collect_denied_tools_filters_denied_only() {
let events = vec![
tool_finished("read_file", false),
tool_finished("delete_file", true),
tool_finished("shell", true),
];
assert_eq!(
collect_denied_tools(&events),
vec!["delete_file".to_string(), "shell".to_string()]
);
}
#[test]
fn test_collect_denied_tools_empty_when_no_denials() {
let events = vec![
tool_finished("read_file", false),
text_delta("all good", None),
];
assert!(collect_denied_tools(&events).is_empty());
}
#[test]
fn test_collect_denied_tools_excludes_grandchild_denials() {
let events = vec![
agent_base::RuntimeEvent::ToolCallFinished {
session_id: agent_base::SessionId::new(1),
tool_name: "grandchild_tool".to_string(),
summary: "summary".to_string(),
agent_id: Some("root/child/grandchild".to_string()),
trace_id: None,
denied: true,
details: None,
},
tool_finished("child_tool", true),
];
assert_eq!(
collect_denied_tools(&events),
vec!["child_tool".to_string()]
);
}
#[test]
fn test_build_child_input_task_only() {
let task = MailboxTask {
task: "do work".into(),
interrupt: true,
pending_messages: vec![],
};
let out = build_child_input(&task);
assert_eq!(out, "do work");
}
#[test]
fn test_build_child_input_with_pending_messages() {
let task = MailboxTask {
task: "do work".into(),
interrupt: false,
pending_messages: vec!["context 1".into(), "context 2".into()],
};
let out = build_child_input(&task);
assert!(out.contains("[Message]: context 1"));
assert!(out.contains("[Message]: context 2"));
assert!(out.contains("[Task]: do work"));
let msg_pos = out.find("[Message]:").unwrap();
let task_pos = out.find("[Task]:").unwrap();
assert!(msg_pos < task_pos, "messages should precede task");
}
#[test]
fn test_build_child_input_single_message() {
let task = MailboxTask {
task: "final task".into(),
interrupt: true,
pending_messages: vec!["hint".into()],
};
let out = build_child_input(&task);
assert_eq!(out, "[Message]: hint\n\n[Task]: final task");
}
use crate::multi_agent::mailbox::{MailboxResult, MailboxStatus};
use crate::multi_agent::path::AgentPath;
#[test]
fn test_format_child_result_ok_with_text() {
let result = MailboxResult {
agent_path: AgentPath::parse("root/worker").unwrap(),
status: MailboxStatus::Ok,
result: Some("found 3 files".to_string()),
denied_tools: vec![],
};
let event = format_child_result(&result);
assert_eq!(event.agent_path, "root/worker");
assert_eq!(event.status, "ok");
assert_eq!(event.result.as_deref(), Some("found 3 files"));
assert!(event.message.contains("root/worker"));
assert!(event.message.contains("已完成"));
assert!(event.message.contains("found 3 files"));
}
#[test]
fn test_format_child_result_ok_empty() {
let result = MailboxResult {
agent_path: AgentPath::parse("root/helper").unwrap(),
status: MailboxStatus::Ok,
result: None,
denied_tools: vec![],
};
let event = format_child_result(&result);
assert_eq!(event.status, "ok");
assert!(event.message.contains("已完成"));
assert!(!event.message.contains("\n")); }
#[test]
fn test_format_child_result_error() {
let result = MailboxResult {
agent_path: AgentPath::parse("root/worker").unwrap(),
status: MailboxStatus::Error,
result: Some("timeout".to_string()),
denied_tools: vec![],
};
let event = format_child_result(&result);
assert_eq!(event.status, "error");
assert!(event.message.contains("出错"));
assert!(event.message.contains("timeout"));
}
#[test]
fn test_format_child_result_closed() {
let result = MailboxResult {
agent_path: AgentPath::parse("root/worker").unwrap(),
status: MailboxStatus::Closed,
result: None,
denied_tools: vec![],
};
let event = format_child_result(&result);
assert_eq!(event.status, "closed");
assert!(event.message.contains("已关闭"));
}