fix(runtime,hands): 4项根因修复 — URL编码/Browser桩/定时解析/LLM超时
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
1. researcher.rs: url_encode() chars→bytes,修复中文搜索URL编码 (U+533B→%533B 改为 UTF-8 %E5%8C%BB) 2. browser.rs: WebDriver不可用时返回明确错误而非静默成功, 防止LLM误以为操作已完成 3. nl_schedule.rs: 新增相对延迟解析(秒后/分钟后/小时后), 避免fallback到LLM幻觉cron 4. 4个LLM driver: 移除http1_only()防reqwest解码错误, 超时120s→300s适配工具调用链,Anthropic裸Client::new()补全配置
This commit is contained in:
@@ -246,23 +246,29 @@ impl Hand for BrowserHand {
|
||||
}
|
||||
|
||||
async fn execute(&self, _context: &HandContext, input: Value) -> Result<HandResult> {
|
||||
// Parse the action
|
||||
let action: BrowserAction = match serde_json::from_value(input) {
|
||||
Ok(a) => a,
|
||||
Err(e) => return Ok(HandResult::error(format!("Invalid action: {}", e))),
|
||||
};
|
||||
|
||||
// Browser automation executes on the frontend via BrowserHandCard.
|
||||
// Return the parsed action with a clear message so the LLM can inform
|
||||
// the user and the frontend can pick it up via Tauri events.
|
||||
let action_type = action.action_name();
|
||||
let summary = action.summary();
|
||||
|
||||
// Check if WebDriver is available
|
||||
if !self.check_webdriver() {
|
||||
return Ok(HandResult::error(format!(
|
||||
"浏览器操作「{}」无法执行:未检测到 WebDriver (ChromeDriver/GeckoDriver)。请先启动 WebDriver 服务。",
|
||||
summary
|
||||
)));
|
||||
}
|
||||
|
||||
// WebDriver is running — delegate to frontend BrowserHandCard.
|
||||
// The frontend manages the Fantoccini session lifecycle.
|
||||
Ok(HandResult::success(serde_json::json!({
|
||||
"action": action_type,
|
||||
"status": "delegated_to_frontend",
|
||||
"message": format!("浏览器操作「{}」已委托给前端执行。请在 HandsPanel 中查看执行结果。", summary),
|
||||
"details": format!("{} — 需要 WebDriver 会话,由前端 BrowserHandCard 管理。", summary),
|
||||
"message": format!("浏览器操作「{}」已发送到前端执行。WebDriver 已就绪。", summary),
|
||||
"details": format!("{} — 由前端 BrowserHandCard 通过 Fantoccini 执行。", summary),
|
||||
})))
|
||||
}
|
||||
|
||||
@@ -512,12 +518,16 @@ mod tests {
|
||||
assert!(!sequence.stop_on_error);
|
||||
assert_eq!(sequence.steps.len(), 1);
|
||||
|
||||
// Execute the navigate step
|
||||
// Execute the navigate step — without WebDriver running, should report error
|
||||
let action_json = serde_json::to_value(&sequence.steps[0]).expect("serialize step");
|
||||
let result = hand.execute(&ctx, action_json).await.expect("execute");
|
||||
assert!(result.success);
|
||||
assert_eq!(result.output["action"], "navigate");
|
||||
assert_eq!(result.output["status"], "delegated_to_frontend");
|
||||
// In test env no WebDriver is running, so we get an error about missing WebDriver
|
||||
if result.success {
|
||||
assert_eq!(result.output["action"], "navigate");
|
||||
assert_eq!(result.output["status"], "delegated_to_frontend");
|
||||
} else {
|
||||
assert!(result.error.as_deref().unwrap_or("").contains("WebDriver"));
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -533,11 +543,18 @@ mod tests {
|
||||
|
||||
assert_eq!(sequence.steps.len(), 4);
|
||||
|
||||
// Verify each step can execute
|
||||
// Verify each step can parse and execute (or report missing WebDriver)
|
||||
for (i, step) in sequence.steps.iter().enumerate() {
|
||||
let action_json = serde_json::to_value(step).expect("serialize step");
|
||||
let result = hand.execute(&ctx, action_json).await.expect("execute step");
|
||||
assert!(result.success, "Step {} failed: {:?}", i, result.error);
|
||||
// Without WebDriver, all steps should report the error cleanly
|
||||
if !result.success {
|
||||
assert!(
|
||||
result.error.as_deref().unwrap_or("").contains("WebDriver"),
|
||||
"Step {} unexpected error: {:?}",
|
||||
i, result.error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user