Files
skill-lib/tests/agent_runtime_test.rs
2026-03-25 04:27:12 +00:00

135 lines
3.9 KiB
Rust

mod common;
use std::sync::Arc;
use std::time::Duration;
use common::MockTransport;
use sgclaw::agent::runtime::{browser_action_tool_definition, execute_task_with_provider};
use sgclaw::llm::{ChatMessage, LlmError, LlmProvider, ToolDefinition, ToolFunctionCall};
use sgclaw::pipe::{Action, AgentMessage, BrowserMessage, BrowserPipeTool, Timing};
use sgclaw::security::MacPolicy;
struct FakeProvider {
calls: Vec<ToolFunctionCall>,
}
impl LlmProvider for FakeProvider {
fn chat(
&self,
_messages: &[ChatMessage],
_tools: &[ToolDefinition],
) -> Result<Vec<ToolFunctionCall>, LlmError> {
Ok(self.calls.clone())
}
}
fn test_policy() -> MacPolicy {
MacPolicy::from_json_str(
r#"{
"version": "1.0",
"domains": { "allowed": ["www.baidu.com"] },
"pipe_actions": {
"allowed": ["click", "type", "navigate", "getText"],
"blocked": []
}
}"#,
)
.unwrap()
}
#[test]
fn browser_action_tool_definition_uses_expected_name() {
let tool = browser_action_tool_definition();
assert_eq!(tool.name, "browser_action");
assert_eq!(tool.parameters["required"][0], "action");
assert_eq!(tool.parameters["required"][1], "expected_domain");
}
#[test]
fn runtime_executes_provider_tool_calls_and_returns_summary() {
let transport = Arc::new(MockTransport::new(vec![
BrowserMessage::Response {
seq: 1,
success: true,
data: serde_json::json!({ "navigated": true }),
aom_snapshot: vec![],
timing: Timing {
queue_ms: 1,
exec_ms: 10,
},
},
BrowserMessage::Response {
seq: 2,
success: true,
data: serde_json::json!({ "typed": true }),
aom_snapshot: vec![],
timing: Timing {
queue_ms: 1,
exec_ms: 10,
},
},
]));
let browser_tool = BrowserPipeTool::new(
transport.clone(),
test_policy(),
vec![1, 2, 3, 4, 5, 6, 7, 8],
)
.with_response_timeout(Duration::from_secs(1));
let provider = FakeProvider {
calls: vec![
ToolFunctionCall {
id: "call-1".to_string(),
name: "browser_action".to_string(),
arguments: serde_json::json!({
"action": "navigate",
"expected_domain": "www.baidu.com",
"url": "https://www.baidu.com"
}),
},
ToolFunctionCall {
id: "call-2".to_string(),
name: "browser_action".to_string(),
arguments: serde_json::json!({
"action": "type",
"expected_domain": "www.baidu.com",
"selector": "#kw",
"text": "天气",
"clear_first": true
}),
},
],
};
let summary = execute_task_with_provider(
transport.as_ref(),
&browser_tool,
&provider,
"打开百度搜索天气",
)
.unwrap();
let sent = transport.sent_messages();
assert_eq!(summary, "已通过 Agent 执行任务: 打开百度搜索天气");
assert!(matches!(
&sent[0],
AgentMessage::LogEntry { level, message }
if level == "info" && message == "navigate www.baidu.com"
));
assert!(matches!(
&sent[1],
AgentMessage::Command { seq, action, .. }
if *seq == 1 && action == &Action::Navigate
));
assert!(matches!(
&sent[2],
AgentMessage::LogEntry { level, message }
if level == "info" && message == "type www.baidu.com"
));
assert!(matches!(
&sent[3],
AgentMessage::Command { seq, action, .. }
if *seq == 2 && action == &Action::Type
));
}