browser_use/tools/
extract.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)]
7pub struct ExtractParams {
8 #[serde(skip_serializing_if = "Option::is_none")]
10 pub selector: Option<String>,
11
12 #[serde(default = "default_format")]
14 pub format: String,
15}
16
17fn default_format() -> String {
18 "text".to_string()
19}
20
21#[derive(Default)]
22pub struct ExtractContentTool;
23
24impl Tool for ExtractContentTool {
25 type Params = ExtractParams;
26
27 fn name(&self) -> &str {
28 "extract"
29 }
30
31 fn execute_typed(
32 &self,
33 params: ExtractParams,
34 context: &mut ToolContext,
35 ) -> Result<ToolResult> {
36 let content = if let Some(selector) = ¶ms.selector {
37 let element = context.session.find_element(selector)?;
38
39 if params.format == "html" {
40 element
41 .get_content()
42 .map_err(|e| BrowserError::ToolExecutionFailed {
43 tool: "extract".to_string(),
44 reason: e.to_string(),
45 })?
46 } else {
47 element
48 .get_inner_text()
49 .map_err(|e| BrowserError::ToolExecutionFailed {
50 tool: "extract".to_string(),
51 reason: e.to_string(),
52 })?
53 }
54 } else {
55 let js_code = if params.format == "html" {
57 "document.body.innerHTML"
58 } else {
59 "document.body.innerText"
60 };
61
62 let result = context
63 .session
64 .tab()
65 .evaluate(js_code, false)
66 .map_err(|e| BrowserError::EvaluationFailed(e.to_string()))?;
67
68 result
69 .value
70 .and_then(|v| v.as_str().map(String::from))
71 .unwrap_or_default()
72 };
73
74 Ok(ToolResult::success_with(serde_json::json!({
75 "content": content,
76 "format": params.format,
77 "length": content.len()
78 })))
79 }
80}