Complete Rig tool lifecycle migration
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use ai::diff_validation::ParsedDiff;
|
||||
use ai::skills::{SkillPathOrigin, SkillReference};
|
||||
use galaxy_agent_core::ToolCall;
|
||||
|
||||
use super::action_from_tool_call;
|
||||
use crate::ai::agent::{AIAgentActionType, FileEdit};
|
||||
|
||||
fn call(name: &str, arguments: serde_json::Value) -> ToolCall {
|
||||
ToolCall {
|
||||
id: "call-1".to_string(),
|
||||
name: name.to_string(),
|
||||
arguments,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shell_calls_become_domain_actions_without_a_proto_round_trip() {
|
||||
let action = action_from_tool_call(
|
||||
"task-1",
|
||||
&call(
|
||||
"run_shell_command",
|
||||
serde_json::json!({
|
||||
"command": "cargo test",
|
||||
"is_read_only": true,
|
||||
"is_risky": false
|
||||
}),
|
||||
),
|
||||
&SkillPathOrigin::Local,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(action.id.to_string(), "call-1");
|
||||
assert_eq!(action.task_id.to_string(), "task-1");
|
||||
assert!(matches!(
|
||||
action.action,
|
||||
AIAgentActionType::RequestCommandOutput {
|
||||
command,
|
||||
is_read_only: Some(true),
|
||||
is_risky: Some(false),
|
||||
..
|
||||
} if command == "cargo test"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn edit_calls_preserve_file_edits_in_the_domain_model() {
|
||||
let action = action_from_tool_call(
|
||||
"task-1",
|
||||
&call(
|
||||
"apply_file_diffs",
|
||||
serde_json::json!({
|
||||
"summary": "Update greeting",
|
||||
"diffs": [{
|
||||
"file_path": "/tmp/greeting.txt",
|
||||
"search": "hello",
|
||||
"replace": "hello galaxy"
|
||||
}]
|
||||
}),
|
||||
),
|
||||
&SkillPathOrigin::Local,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let AIAgentActionType::RequestFileEdits { file_edits, title } = action.action else {
|
||||
panic!("expected file-edit action");
|
||||
};
|
||||
assert_eq!(title.as_deref(), Some("Update greeting"));
|
||||
assert!(matches!(
|
||||
&file_edits[0],
|
||||
FileEdit::Edit(ParsedDiff::StrReplaceEdit {
|
||||
file: Some(file),
|
||||
search: Some(search),
|
||||
replace: Some(replace),
|
||||
}) if file == "/tmp/greeting.txt" && search == "hello" && replace == "hello galaxy"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn grouped_mcp_calls_keep_the_installation_uuid_and_json_input() {
|
||||
let action = action_from_tool_call(
|
||||
"task-1",
|
||||
&call(
|
||||
"mcp__11111111-1111-4111-8111-111111111111__echo",
|
||||
serde_json::json!({"message": "hello"}),
|
||||
),
|
||||
&SkillPathOrigin::Local,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(matches!(
|
||||
action.action,
|
||||
AIAgentActionType::CallMCPTool {
|
||||
server_id: Some(server_id),
|
||||
name,
|
||||
input,
|
||||
} if server_id.to_string() == "11111111-1111-4111-8111-111111111111"
|
||||
&& name == "echo"
|
||||
&& input == serde_json::json!({"message": "hello"})
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn local_skill_paths_preserve_the_session_origin() {
|
||||
let action = action_from_tool_call(
|
||||
"task-1",
|
||||
&call(
|
||||
"read_skill",
|
||||
serde_json::json!({
|
||||
"skill": "/tmp/example/SKILL.md",
|
||||
"reference_type": "path"
|
||||
}),
|
||||
),
|
||||
&SkillPathOrigin::Local,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(matches!(
|
||||
action.action,
|
||||
AIAgentActionType::ReadSkill(request)
|
||||
if request.skill == SkillReference::Path(
|
||||
galaxy_util::local_or_remote_path::LocalOrRemotePath::Local(PathBuf::from(
|
||||
"/tmp/example/SKILL.md"
|
||||
))
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unknown_tools_are_rejected_before_the_permission_boundary() {
|
||||
let error = action_from_tool_call(
|
||||
"task-1",
|
||||
&call("invented_tool", serde_json::json!({})),
|
||||
&SkillPathOrigin::Local,
|
||||
)
|
||||
.unwrap_err();
|
||||
|
||||
assert!(error.contains("unsupported Rig tool proposal"));
|
||||
}
|
||||
Reference in New Issue
Block a user