Migrate Rig tool flow to domain runtime

This commit is contained in:
2026-08-04 14:14:51 -05:00
parent 4c7270db8d
commit 91d8bd0381
34 changed files with 2728 additions and 374 deletions
+175 -2
View File
@@ -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"
));
}