browser_use/tools/
input.rs1use crate::error::{BrowserError, Result};
2use crate::tools::snapshot::{RenderMode, render_aria_tree};
3use crate::tools::{Tool, ToolContext, ToolResult};
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
8pub struct InputParams {
9 #[serde(skip_serializing_if = "Option::is_none")]
11 pub selector: Option<String>,
12
13 #[serde(skip_serializing_if = "Option::is_none")]
15 pub index: Option<usize>,
16
17 pub text: String,
19
20 #[serde(default)]
22 pub clear: bool,
23}
24
25#[derive(Default)]
26pub struct InputTool;
27
28impl Tool for InputTool {
29 type Params = InputParams;
30
31 fn name(&self) -> &str {
32 "input"
33 }
34
35 fn execute_typed(&self, params: InputParams, context: &mut ToolContext) -> Result<ToolResult> {
36 match (¶ms.selector, ¶ms.index) {
38 (Some(_), Some(_)) => {
39 return Err(BrowserError::ToolExecutionFailed {
40 tool: "input".to_string(),
41 reason: "Cannot specify both 'selector' and 'index'. Use one or the other."
42 .to_string(),
43 });
44 }
45 (None, None) => {
46 return Err(BrowserError::ToolExecutionFailed {
47 tool: "input".to_string(),
48 reason: "Must specify either 'selector' or 'index'.".to_string(),
49 });
50 }
51 _ => {}
52 }
53
54 let css_selector = if let Some(selector) = params.selector.clone() {
56 selector
57 } else if let Some(index) = params.index {
58 let dom = context.get_dom()?;
59 let selector = dom.get_selector(index).ok_or_else(|| {
60 BrowserError::ElementNotFound(format!("No element with index {}", index))
61 })?;
62 selector.clone()
63 } else {
64 unreachable!("Validation above ensures one field is Some")
65 };
66
67 let tab = context.session.tab()?;
68 let element = context.session.find_element(&tab, &css_selector)?;
69
70 if params.clear {
71 element.click().ok(); tab.press_key("End").ok();
74 for _ in 0..params.text.len() + 100 {
75 tab.press_key("Backspace").ok();
76 }
77 }
78
79 element
80 .type_into(¶ms.text)
81 .map_err(|e| BrowserError::ToolExecutionFailed {
82 tool: "input".to_string(),
83 reason: e.to_string(),
84 })?;
85
86 let snapshot = {
87 let dom = context.get_dom()?;
88 render_aria_tree(&dom.root, RenderMode::Ai, None)
89 };
90
91 let result_json = serde_json::json!({
92 "snapshot": snapshot
93 });
94
95 Ok(ToolResult::success_with(result_json))
96 }
97}