browser_use/tools/
hover.rs1use crate::error::{BrowserError, Result};
2use crate::tools::{Tool, ToolContext, ToolResult};
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
8pub struct HoverParams {
9 #[serde(flatten)]
11 pub selector: ElementSelector,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
15#[serde(untagged)]
16pub enum ElementSelector {
17 Css {
19 selector: String,
21 },
22 Index {
24 index: usize,
26 },
27}
28
29#[derive(Default)]
31pub struct HoverTool;
32
33const HOVER_JS: &str = include_str!("hover.js");
34
35impl Tool for HoverTool {
36 type Params = HoverParams;
37
38 fn name(&self) -> &str {
39 "hover"
40 }
41
42 fn execute_typed(&self, params: HoverParams, context: &mut ToolContext) -> Result<ToolResult> {
43 let css_selector = match params.selector {
44 ElementSelector::Css { selector } => selector,
45 ElementSelector::Index { index } => {
46 let dom = context.get_dom()?;
47 let selector_info = dom.get_selector(index).ok_or_else(|| {
48 BrowserError::ElementNotFound(format!("No element with index {}", index))
49 })?;
50 selector_info.css_selector.clone()
51 }
52 };
53
54 let selector_json =
58 serde_json::to_string(&css_selector).expect("serializing CSS selector never fails");
59 let hover_js = HOVER_JS.replace("__SELECTOR__", &selector_json);
60
61 let result = context
62 .session
63 .tab()
64 .evaluate(&hover_js, false)
65 .map_err(|e| BrowserError::ToolExecutionFailed {
66 tool: "hover".to_string(),
67 reason: e.to_string(),
68 })?;
69
70 let result_json: serde_json::Value = if let Some(serde_json::Value::String(json_str)) =
72 result.value
73 {
74 serde_json::from_str(&json_str)
75 .unwrap_or(serde_json::json!({"success": false, "error": "Failed to parse result"}))
76 } else {
77 result
78 .value
79 .unwrap_or(serde_json::json!({"success": false, "error": "No result returned"}))
80 };
81
82 if result_json["success"].as_bool() == Some(true) {
83 Ok(ToolResult::success_with(serde_json::json!({
84 "selector": css_selector,
85 "element": {
86 "tagName": result_json["tagName"],
87 "id": result_json["id"],
88 "className": result_json["className"]
89 }
90 })))
91 } else {
92 Err(BrowserError::ToolExecutionFailed {
93 tool: "hover".to_string(),
94 reason: result_json["error"]
95 .as_str()
96 .unwrap_or("Unknown error")
97 .to_string(),
98 })
99 }
100 }
101}