browser_use/tools/
markdown.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 GetMarkdownParams {}
9
10#[derive(Default)]
11pub struct GetMarkdownTool;
12
13impl Tool for GetMarkdownTool {
14 type Params = GetMarkdownParams;
15
16 fn name(&self) -> &str {
17 "get_markdown"
18 }
19
20 fn execute_typed(
21 &self,
22 _params: GetMarkdownParams,
23 context: &mut ToolContext,
24 ) -> Result<ToolResult> {
25 std::thread::sleep(std::time::Duration::from_millis(1000));
29
30 let js_code = include_str!("convert_to_markdown.js");
32
33 let result = context
35 .session
36 .tab()
37 .evaluate(js_code, false)
38 .map_err(|e| BrowserError::EvaluationFailed(e.to_string()))?;
39
40 let result_value = result
42 .value
43 .ok_or_else(|| BrowserError::ToolExecutionFailed {
44 tool: "get_markdown".to_string(),
45 reason: "No value returned from JavaScript".to_string(),
46 })?;
47
48 let content_data: MarkdownContent = if let Some(json_str) = result_value.as_str() {
50 serde_json::from_str(json_str).map_err(|e| BrowserError::ToolExecutionFailed {
51 tool: "get_markdown".to_string(),
52 reason: format!("Failed to parse markdown content: {}", e),
53 })?
54 } else {
55 serde_json::from_value(result_value).map_err(|e| BrowserError::ToolExecutionFailed {
57 tool: "get_markdown".to_string(),
58 reason: format!("Failed to deserialize markdown content: {}", e),
59 })?
60 };
61
62 let markdown = if !content_data.title.is_empty() {
64 format!("# {}\n\n{}", content_data.title, content_data.content)
65 } else {
66 content_data.content.clone()
67 };
68
69 Ok(ToolResult::success_with(serde_json::json!({
70 "markdown": markdown,
71 "title": content_data.title,
72 "url": content_data.url,
73 "length": markdown.len()
74 })))
75 }
76}
77
78#[derive(Debug, Serialize, Deserialize)]
80struct MarkdownContent {
81 title: String,
82 content: String,
83 url: String,
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89
90 #[test]
91 fn test_get_markdown_tool_name() {
92 let tool = GetMarkdownTool::default();
93 assert_eq!(tool.name(), "get_markdown");
94 }
95
96 #[test]
97 fn test_get_markdown_params_schema() {
98 let tool = GetMarkdownTool::default();
99 let schema = tool.parameters_schema();
100 assert!(schema.is_object());
101 }
102
103 #[test]
104 fn test_markdown_content_deserialization() {
105 let json = r#"{"title": "Test", "content": "Hello", "url": "https://example.com"}"#;
106 let content: MarkdownContent = serde_json::from_str(json).unwrap();
107 assert_eq!(content.title, "Test");
108 assert_eq!(content.content, "Hello");
109 assert_eq!(content.url, "https://example.com");
110 }
111}