Migrate Rig tool flow to domain runtime
This commit is contained in:
@@ -1,7 +1,14 @@
|
||||
use galaxy_agent_core::StopReason;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use galaxy_agent_core::{
|
||||
MessageContent, MessageRole, StopReason, ToolCall, ToolResult, ToolResultStatus,
|
||||
};
|
||||
use warp_multi_agent_api::response_event::stream_finished;
|
||||
|
||||
use super::{build_add_reasoning, build_append_reasoning, map_stop_reason, saturating_i32};
|
||||
use super::{
|
||||
append_tool_result, build_add_reasoning, build_append_reasoning, build_tool_proposed,
|
||||
map_stop_reason, saturating_i32, sync_assistant_turn,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn stop_reasons_map_to_the_existing_ui_contract() {
|
||||
@@ -57,3 +64,169 @@ fn reasoning_events_match_the_existing_ui_message_contract() {
|
||||
["agent_reasoning.reasoning"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tool_proposal_matches_the_existing_permission_ui_contract() {
|
||||
let event = build_tool_proposed(
|
||||
"task",
|
||||
&ToolCall {
|
||||
id: "call-1".to_string(),
|
||||
name: "run_shell_command".to_string(),
|
||||
arguments: serde_json::json!({
|
||||
"command": "cargo test",
|
||||
"is_read_only": true
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
let Some(warp_multi_agent_api::response_event::Type::ClientActions(actions)) = event.r#type
|
||||
else {
|
||||
panic!("expected client actions");
|
||||
};
|
||||
let Some(warp_multi_agent_api::client_action::Action::AddMessagesToTask(add)) =
|
||||
&actions.actions[0].action
|
||||
else {
|
||||
panic!("expected add-message action");
|
||||
};
|
||||
let Some(warp_multi_agent_api::message::Message::ToolCall(tool_call)) =
|
||||
&add.messages[0].message
|
||||
else {
|
||||
panic!("expected tool-call message");
|
||||
};
|
||||
let Some(warp_multi_agent_api::message::tool_call::Tool::RunShellCommand(command)) =
|
||||
&tool_call.tool
|
||||
else {
|
||||
panic!("expected run-shell-command payload");
|
||||
};
|
||||
|
||||
assert_eq!(tool_call.tool_call_id, "call-1");
|
||||
assert_eq!(command.command, "cargo test");
|
||||
assert!(command.is_read_only);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mcp_tool_proposal_routes_through_the_existing_mcp_executor_contract() {
|
||||
let event = build_tool_proposed(
|
||||
"task",
|
||||
&ToolCall {
|
||||
id: "call-mcp".to_string(),
|
||||
name: "mcp__filesystem__read_file".to_string(),
|
||||
arguments: serde_json::json!({"path": "Cargo.toml"}),
|
||||
},
|
||||
);
|
||||
|
||||
let Some(warp_multi_agent_api::response_event::Type::ClientActions(actions)) = event.r#type
|
||||
else {
|
||||
panic!("expected client actions");
|
||||
};
|
||||
let Some(warp_multi_agent_api::client_action::Action::AddMessagesToTask(add)) =
|
||||
&actions.actions[0].action
|
||||
else {
|
||||
panic!("expected add-message action");
|
||||
};
|
||||
let Some(warp_multi_agent_api::message::Message::ToolCall(tool_call)) =
|
||||
&add.messages[0].message
|
||||
else {
|
||||
panic!("expected tool-call message");
|
||||
};
|
||||
let Some(warp_multi_agent_api::message::tool_call::Tool::CallMcpTool(call)) = &tool_call.tool
|
||||
else {
|
||||
panic!("expected MCP tool payload");
|
||||
};
|
||||
|
||||
assert_eq!(tool_call.tool_call_id, "call-mcp");
|
||||
assert_eq!(call.server_id, "filesystem");
|
||||
assert_eq!(call.name, "read_file");
|
||||
assert!(call.args.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assistant_history_is_updated_before_fast_tool_execution_can_continue() {
|
||||
let messages = Arc::new(Mutex::new(Vec::new()));
|
||||
let mut history_index = None;
|
||||
let first_call = ToolCall {
|
||||
id: "call-1".to_string(),
|
||||
name: "read_files".to_string(),
|
||||
arguments: serde_json::json!({"files": ["Cargo.toml"]}),
|
||||
};
|
||||
let second_call = ToolCall {
|
||||
id: "call-2".to_string(),
|
||||
name: "grep".to_string(),
|
||||
arguments: serde_json::json!({"queries": ["rig"]}),
|
||||
};
|
||||
|
||||
sync_assistant_turn(
|
||||
&messages,
|
||||
"I'll inspect both.",
|
||||
std::slice::from_ref(&first_call),
|
||||
&mut history_index,
|
||||
);
|
||||
sync_assistant_turn(
|
||||
&messages,
|
||||
"I'll inspect both.",
|
||||
&[first_call, second_call],
|
||||
&mut history_index,
|
||||
);
|
||||
|
||||
let messages = messages.lock().unwrap();
|
||||
assert_eq!(messages.len(), 1);
|
||||
let MessageContent::MultiPart(parts) = &messages[0].content else {
|
||||
panic!("expected combined assistant content");
|
||||
};
|
||||
assert_eq!(parts.len(), 3);
|
||||
assert!(
|
||||
matches!(&parts[0], galaxy_agent_core::ContentPart::Text(text) if text == "I'll inspect both.")
|
||||
);
|
||||
assert!(
|
||||
matches!(&parts[1], galaxy_agent_core::ContentPart::ToolUse { tool_use_id, .. } if tool_use_id == "call-1")
|
||||
);
|
||||
assert!(
|
||||
matches!(&parts[2], galaxy_agent_core::ContentPart::ToolUse { tool_use_id, .. } if tool_use_id == "call-2")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejected_tool_result_is_paired_with_the_assistant_call_in_history() {
|
||||
let messages = Arc::new(Mutex::new(Vec::new()));
|
||||
let mut history_index = None;
|
||||
let call = ToolCall {
|
||||
id: "call-unknown".to_string(),
|
||||
name: "invented_tool".to_string(),
|
||||
arguments: serde_json::json!({}),
|
||||
};
|
||||
sync_assistant_turn(
|
||||
&messages,
|
||||
"",
|
||||
std::slice::from_ref(&call),
|
||||
&mut history_index,
|
||||
);
|
||||
append_tool_result(
|
||||
&messages,
|
||||
ToolResult {
|
||||
call_id: call.id.clone(),
|
||||
content: "tool is unavailable".to_string(),
|
||||
status: ToolResultStatus::Error,
|
||||
},
|
||||
);
|
||||
|
||||
let messages = messages.lock().unwrap();
|
||||
assert_eq!(messages.len(), 2);
|
||||
assert_eq!(messages[0].role, MessageRole::Assistant);
|
||||
assert!(matches!(
|
||||
&messages[0].content,
|
||||
MessageContent::ToolUse {
|
||||
tool_use_id,
|
||||
name,
|
||||
..
|
||||
} if tool_use_id == "call-unknown" && name == "invented_tool"
|
||||
));
|
||||
assert_eq!(messages[1].role, MessageRole::User);
|
||||
assert!(matches!(
|
||||
&messages[1].content,
|
||||
MessageContent::ToolResult {
|
||||
tool_use_id,
|
||||
content,
|
||||
is_error: true,
|
||||
} if tool_use_id == "call-unknown" && content == "tool is unavailable"
|
||||
));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user