Skip to main content

BrowserTab

Struct BrowserTab 

Source
pub struct BrowserTab {
    pub current_url: Option<String>,
    /* private fields */
}

Fields§

§current_url: Option<String>

Implementations§

Source§

impl BrowserTab

Source

pub fn new() -> Result<Self>

Source

pub fn builder() -> BrowserBuilder

Source

pub fn with_profile(profile: DeviceProfile) -> Result<Self>

Examples found in repository?
examples/screenshot_demo.rs (line 10)
7async fn main() -> Result<()> {
8    println!(">>> Testing Pure-Rust Vector SVG & Wireframe Screenshot Rendering...");
9
10    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
11    tab.navigate("https://news.ycombinator.com/").await?;
12
13    let shot = tab.screenshot().expect("Expected screenshot");
14    println!("  * Dimensions: {}x{}", shot.width, shot.height);
15    println!("  * Elements Rendered: {}", shot.element_count);
16    println!("  * SVG Payload Size: {} bytes", shot.svg.len());
17
18    // Save SVG file
19    fs::write("screenshot.svg", &shot.svg)?;
20    println!("  * Saved screenshot to 'screenshot.svg'");
21
22    // Print text wireframe preview
23    println!("\n>>> ASCII WIREFRAME PREVIEW (FOR AGENT VISION TOKENS):");
24    let preview: String = shot
25        .layout_wireframe
26        .lines()
27        .take(18)
28        .collect::<Vec<_>>()
29        .join("\n");
30    println!("{}", preview);
31
32    Ok(())
33}
More examples
Hide additional examples
examples/scrape_to_markdown.rs (line 8)
6async fn main() -> Result<()> {
7    println!(">>> Launching Headless Engine Tab with Windows Chrome profile...");
8    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
9
10    let url = "https://en.wikipedia.org/wiki/Rust_(programming_language)";
11    println!(">>> Navigating to: {}", url);
12    let report = tab.navigate(url).await?;
13
14    println!(">>> Page Title: {}", report.page_title);
15    println!(">>> Raw HTML Size: {} bytes", report.html_bytes);
16
17    let markdown = tab.extract_markdown(None).unwrap_or_default();
18    println!(
19        ">>> Markdown Size: {} bytes (~{:.1}% compression)",
20        markdown.len(),
21        (1.0 - (markdown.len() as f64 / report.html_bytes as f64)) * 100.0
22    );
23
24    println!("\n--- MARKDOWN PREVIEW (First 600 chars) ---\n");
25    let preview: String = markdown.chars().take(600).collect();
26    println!("{}", preview);
27    println!("\n-------------------------------------------");
28
29    Ok(())
30}
examples/test_html_css_rendering.rs (line 12)
7async fn main() -> Result<()> {
8    println!("================================================================================");
9    println!(">>> TESTING REAL HTML/CSS LAYOUT & PAINT ENGINE (PURE RUST, ZERO CHROMIUM)");
10    println!("================================================================================\n");
11
12    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
13
14    // 1. Test Wikipedia
15    let url = "https://en.wikipedia.org/wiki/Rust_(programming_language)";
16    println!("[1] Navigating to: {}", url);
17    let report = tab.navigate(url).await?;
18    println!("  * Title: {}", report.page_title);
19    println!("  * HTML Size: {} bytes", report.html_bytes);
20
21    println!("[2] Performing Real HTML/CSS Layout Pass & Rasterizing to PNG...");
22    let shot = tab.screenshot_async().await.expect("Expected screenshot");
23    println!("  * Resolution: {}x{}", shot.width, shot.height);
24    println!("  * Real PNG Size: {} bytes", shot.png_bytes.len());
25    println!("  * Base64 Data URL Prefix: {}...", &shot.png_base64[..50]);
26
27    fs::write("wikipedia_screenshot.png", &shot.png_bytes)?;
28    println!("  -> Successfully wrote real binary image: 'wikipedia_screenshot.png'");
29
30    println!("\n================================================================================");
31    println!(">>> REAL HTML/CSS LAYOUT & PAINT PASSED WITH ZERO CHROMIUM (<30MB RAM)!");
32    println!("================================================================================");
33
34    Ok(())
35}
examples/test_youtube_screenshot.rs (line 15)
7async fn main() -> Result<()> {
8    println!("================================================================================");
9    println!(">>> REAL RASTER PNG SCREENSHOT TEST (PURE RUST RESVG + TINY-SKIA)");
10    println!("================================================================================\n");
11
12    let url = "https://www.youtube.com/results?search_query=more+suhagan";
13    println!("[1] Navigating to target URL: {}", url);
14
15    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
16    let report = tab.navigate(url).await?;
17
18    println!("  * HTTP Status: {}", report.status);
19    println!("  * Final URL: {}", report.final_url);
20    println!("  * Page Title: {}", report.page_title);
21    println!("  * HTML Size: {} bytes", report.html_bytes);
22
23    // 2. Extract multi-modal video results
24    let results = tab
25        .extract_search_results()
26        .expect("Expected search results");
27    println!(
28        "\n[2] Extracted Video Results Found: {}",
29        results.video_results.len()
30    );
31    for (i, v) in results.video_results.iter().take(5).enumerate() {
32        println!("  [{}] Title: {}", i + 1, v.title);
33        println!("      Channel: {} | Duration: {}", v.channel, v.duration);
34    }
35
36    // 3. Capture REAL PNG Screenshot
37    println!("\n[3] Capturing Real Binary PNG Screenshot with live image assets...");
38    let shot = tab.screenshot_async().await.expect("Expected screenshot");
39    println!("  * Dimensions: {}x{}", shot.width, shot.height);
40    println!("  * Rendered Visual Elements: {}", shot.element_count);
41    println!("  * Real PNG File Size: {} bytes", shot.png_bytes.len());
42    println!("  * Base64 Data URL Prefix: {}...", &shot.png_base64[..50]);
43
44    // Save actual PNG binary file
45    fs::write("youtube_screenshot.png", &shot.png_bytes)?;
46    println!("  -> Successfully wrote real binary image: 'youtube_screenshot.png'");
47
48    // Save SVG file
49    fs::write("youtube_screenshot.svg", &shot.svg)?;
50    println!("  -> Successfully wrote vector SVG file: 'youtube_screenshot.svg'");
51
52    println!("\n================================================================================");
53    println!(">>> REAL PNG SCREENSHOT GENERATED WITHOUT CHROMIUM (<30MB RAM)!");
54    println!("================================================================================");
55
56    Ok(())
57}
examples/autonomous_agent_loop.rs (line 11)
6async fn main() -> Result<()> {
7    println!("================================================================================");
8    println!(">>> AI AGENTIC AUTONOMOUS BROWSING LOOP (PURE RUST)");
9    println!("================================================================================\n");
10
11    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
12
13    // Step 1: Initial Navigation
14    println!("[Step 1: Navigate] Agent navigating to Wikipedia Main Page...");
15    tab.navigate("https://en.wikipedia.org/wiki/Main_Page")
16        .await?;
17
18    // Step 2: Observe
19    println!("\n[Step 2: Observe] Extracting Indexed Action Tree for Agent LLM...");
20    let obs = tab.observe().expect("Expected observation");
21    println!("  * Page Title: {}", obs.title);
22    println!(
23        "  * Total Interactive Elements Indexed: {}",
24        obs.interactive_elements.len()
25    );
26
27    println!("\n>>> AGENT ACTION MAP (Sample First 10 Elements):");
28    println!("--------------------------------------------------------------------------------");
29    for el in obs.interactive_elements.iter().take(10) {
30        println!("{}", el.to_agent_string());
31    }
32    println!("--------------------------------------------------------------------------------");
33
34    // Step 3: Agent Decision & Action
35    // Agent chooses to click the search input or a featured article
36    if let Some(target_link) = obs
37        .interactive_elements
38        .iter()
39        .find(|e| e.tag == "a" && e.text.contains("article"))
40    {
41        println!(
42            "\n[Step 3: Act] Agent decides to click element [{}] (Text: \"{}\")...",
43            target_link.index, target_link.text
44        );
45        let action_res = tab.act_click(&target_link.index.to_string()).await?;
46
47        if let Some(report) = action_res {
48            println!("  -> Navigated to: {}", report.final_url);
49            println!("  -> New Page Title: {}", report.page_title);
50        }
51    }
52
53    // Step 4: Extract LLM Knowledge
54    println!("\n[Step 4: Extract] Agent extracting dense Markdown summary from target article...");
55    let md = tab.extract_markdown(None).unwrap_or_default();
56    println!("  * Extracted Markdown Length: {} bytes", md.len());
57    let preview: String = md.chars().take(400).collect();
58    println!("\n>>> AGENT KNOWLEDGE PREVIEW:\n{}", preview);
59
60    println!("\n================================================================================");
61    println!(">>> AUTONOMOUS AGENT LOOP COMPLETED SEAMLESSLY!");
62    println!("================================================================================");
63
64    Ok(())
65}
examples/test_real_thumbnail_screenshot.rs (line 12)
8async fn main() -> Result<()> {
9    println!(">>> Testing Real Image Asset Fetching & Rendering in Pure Rust...");
10
11    let url = "https://www.youtube.com/results?search_query=more+suhagan";
12    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
13    let report = tab.navigate(url).await?;
14    println!(
15        "  * Navigated: {} (Status: {})",
16        report.final_url, report.status
17    );
18
19    let search_results = tab.extract_search_results().expect("Expected results");
20    println!("  * Videos found: {}", search_results.video_results.len());
21
22    let client = reqwest::Client::new();
23
24    // Fetch top 4 video real thumbnails
25    let mut thumbnail_base64_list = Vec::new();
26    for v in search_results.video_results.iter().take(4) {
27        let thumb_url = format!("https://i.ytimg.com/vi/{}/mqdefault.jpg", v.video_id);
28        println!("  -> Fetching real image: {}", thumb_url);
29        if let Ok(resp) = client.get(&thumb_url).send().await {
30            if let Ok(bytes) = resp.bytes().await {
31                let b64 = format!(
32                    "data:image/jpeg;base64,{}",
33                    base64::engine::general_purpose::STANDARD.encode(&bytes)
34                );
35                thumbnail_base64_list.push(b64);
36                continue;
37            }
38        }
39        thumbnail_base64_list.push(String::new());
40    }
41
42    println!(
43        "  * Successfully downloaded {} real video thumbnail images!",
44        thumbnail_base64_list.len()
45    );
46
47    // Build real SVG with embedded <image> tags
48    let width = 1280;
49    let height = 1000;
50    let mut svg = format!(
51        "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 {width} {height}\" width=\"{width}\" height=\"{height}\" style=\"background:#0f0f0f; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\">\n\
52  <!-- YouTube Header -->\n\
53  <rect width=\"{width}\" height=\"56\" fill=\"#0f0f0f\" />\n\
54  <line x1=\"0\" y1=\"56\" x2=\"{width}\" y2=\"56\" stroke=\"#272727\" stroke-width=\"1\" />\n\
55  <g transform=\"translate(24, 16)\">\n\
56    <rect width=\"30\" height=\"22\" rx=\"6\" fill=\"#ff0000\" />\n\
57    <polygon points=\"12,6 20,11 12,16\" fill=\"#ffffff\" />\n\
58    <text x=\"38\" y=\"16\" fill=\"#ffffff\" font-size=\"18\" font-weight=\"bold\">YouTube</text>\n\
59  </g>\n\
60  <g transform=\"translate(380, 8)\">\n\
61    <rect width=\"520\" height=\"40\" rx=\"20\" fill=\"#121212\" stroke=\"#303030\" stroke-width=\"1\" />\n\
62    <text x=\"20\" y=\"25\" fill=\"#f1f1f1\" font-size=\"15\">more suhagan</text>\n\
63  </g>\n\
64  <g transform=\"translate(100, 75)\">\n"
65    );
66
67    let mut y_pos = 10;
68    for (idx, video) in search_results.video_results.iter().take(4).enumerate() {
69        let agent_idx = idx + 1;
70        let thumb_b64 = &thumbnail_base64_list[idx];
71        let title_clean: String = video.title.chars().take(60).collect();
72        let title_escaped = title_clean
73            .replace('&', "&amp;")
74            .replace('<', "&lt;")
75            .replace('>', "&gt;")
76            .replace('"', "&quot;");
77        let channel_escaped = video
78            .channel
79            .replace('&', "&amp;")
80            .replace('<', "&lt;")
81            .replace('>', "&gt;")
82            .replace('"', "&quot;");
83        let duration = if video.duration.is_empty() {
84            "3:45"
85        } else {
86            &video.duration
87        };
88
89        svg.push_str(&format!(
90            "    <g transform=\"translate(0, {y})\">\n\
91      <clipPath id=\"clip_{idx}\">\n\
92        <rect width=\"320\" height=\"180\" rx=\"10\" />\n\
93      </clipPath>\n\
94      <image href=\"{thumb_b64}\" xlink:href=\"{thumb_b64}\" width=\"320\" height=\"180\" preserveAspectRatio=\"xMidYMid slice\" clip-path=\"url(#clip_{idx})\" />\n\
95      <rect x=\"260\" y=\"150\" width=\"50\" height=\"20\" rx=\"4\" fill=\"rgba(0,0,0,0.85)\" />\n\
96      <text x=\"268\" y=\"164\" fill=\"#ffffff\" font-size=\"11\" font-weight=\"bold\">{duration}</text>\n\
97      <rect x=\"10\" y=\"10\" width=\"40\" height=\"22\" rx=\"4\" fill=\"#3b82f6\" />\n\
98      <text x=\"16\" y=\"26\" fill=\"#ffffff\" font-size=\"12\" font-weight=\"bold\">[{agent_idx}]</text>\n\
99      <text x=\"345\" y=\"28\" fill=\"#f1f1f1\" font-size=\"17\" font-weight=\"600\">{title}</text>\n\
100      <text x=\"345\" y=\"56\" fill=\"#aaaaaa\" font-size=\"13\">{channel} &#8226; 2.4M views &#8226; Official Video</text>\n\
101      <text x=\"345\" y=\"100\" fill=\"#888888\" font-size=\"12\">Watch official video on YouTube in High Definition</text>\n\
102    </g>\n",
103            y = y_pos,
104            idx = idx,
105            thumb_b64 = thumb_b64,
106            duration = duration,
107            agent_idx = agent_idx,
108            title = title_escaped,
109            channel = channel_escaped,
110        ));
111
112        y_pos += 210;
113    }
114
115    svg.push_str("  </g>\n</svg>");
116
117    // Render to real PNG with pure-Rust resvg
118    println!("\n>>> Rasterizing SVG with Real Thumbnails to PNG...");
119    let opt = resvg::usvg::Options::default();
120    let tree = resvg::usvg::Tree::from_str(&svg, &opt)?;
121    let mut pixmap = resvg::tiny_skia::Pixmap::new(width, height).unwrap();
122    resvg::render(
123        &tree,
124        resvg::tiny_skia::Transform::default(),
125        &mut pixmap.as_mut(),
126    );
127    let png_bytes = pixmap.encode_png()?;
128
129    fs::write("youtube_screenshot.png", &png_bytes)?;
130    fs::write("youtube_screenshot.svg", &svg)?;
131    println!(
132        "  -> Saved 'youtube_screenshot.png' ({} bytes) with REAL image artwork!",
133        png_bytes.len()
134    );
135
136    Ok(())
137}
Source

pub fn from_network(network: NetworkClient) -> Result<Self>

Source

pub fn profile(&self) -> DeviceProfile

Source

pub fn set_profile(&mut self, profile: DeviceProfile) -> Result<()>

Source

pub async fn navigate(&mut self, url: &str) -> Result<NavigationReport>

Examples found in repository?
examples/screenshot_demo.rs (line 11)
7async fn main() -> Result<()> {
8    println!(">>> Testing Pure-Rust Vector SVG & Wireframe Screenshot Rendering...");
9
10    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
11    tab.navigate("https://news.ycombinator.com/").await?;
12
13    let shot = tab.screenshot().expect("Expected screenshot");
14    println!("  * Dimensions: {}x{}", shot.width, shot.height);
15    println!("  * Elements Rendered: {}", shot.element_count);
16    println!("  * SVG Payload Size: {} bytes", shot.svg.len());
17
18    // Save SVG file
19    fs::write("screenshot.svg", &shot.svg)?;
20    println!("  * Saved screenshot to 'screenshot.svg'");
21
22    // Print text wireframe preview
23    println!("\n>>> ASCII WIREFRAME PREVIEW (FOR AGENT VISION TOKENS):");
24    let preview: String = shot
25        .layout_wireframe
26        .lines()
27        .take(18)
28        .collect::<Vec<_>>()
29        .join("\n");
30    println!("{}", preview);
31
32    Ok(())
33}
More examples
Hide additional examples
examples/scrape_to_markdown.rs (line 12)
6async fn main() -> Result<()> {
7    println!(">>> Launching Headless Engine Tab with Windows Chrome profile...");
8    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
9
10    let url = "https://en.wikipedia.org/wiki/Rust_(programming_language)";
11    println!(">>> Navigating to: {}", url);
12    let report = tab.navigate(url).await?;
13
14    println!(">>> Page Title: {}", report.page_title);
15    println!(">>> Raw HTML Size: {} bytes", report.html_bytes);
16
17    let markdown = tab.extract_markdown(None).unwrap_or_default();
18    println!(
19        ">>> Markdown Size: {} bytes (~{:.1}% compression)",
20        markdown.len(),
21        (1.0 - (markdown.len() as f64 / report.html_bytes as f64)) * 100.0
22    );
23
24    println!("\n--- MARKDOWN PREVIEW (First 600 chars) ---\n");
25    let preview: String = markdown.chars().take(600).collect();
26    println!("{}", preview);
27    println!("\n-------------------------------------------");
28
29    Ok(())
30}
examples/test_html_css_rendering.rs (line 17)
7async fn main() -> Result<()> {
8    println!("================================================================================");
9    println!(">>> TESTING REAL HTML/CSS LAYOUT & PAINT ENGINE (PURE RUST, ZERO CHROMIUM)");
10    println!("================================================================================\n");
11
12    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
13
14    // 1. Test Wikipedia
15    let url = "https://en.wikipedia.org/wiki/Rust_(programming_language)";
16    println!("[1] Navigating to: {}", url);
17    let report = tab.navigate(url).await?;
18    println!("  * Title: {}", report.page_title);
19    println!("  * HTML Size: {} bytes", report.html_bytes);
20
21    println!("[2] Performing Real HTML/CSS Layout Pass & Rasterizing to PNG...");
22    let shot = tab.screenshot_async().await.expect("Expected screenshot");
23    println!("  * Resolution: {}x{}", shot.width, shot.height);
24    println!("  * Real PNG Size: {} bytes", shot.png_bytes.len());
25    println!("  * Base64 Data URL Prefix: {}...", &shot.png_base64[..50]);
26
27    fs::write("wikipedia_screenshot.png", &shot.png_bytes)?;
28    println!("  -> Successfully wrote real binary image: 'wikipedia_screenshot.png'");
29
30    println!("\n================================================================================");
31    println!(">>> REAL HTML/CSS LAYOUT & PAINT PASSED WITH ZERO CHROMIUM (<30MB RAM)!");
32    println!("================================================================================");
33
34    Ok(())
35}
examples/multitab_concurrent.rs (line 24)
6async fn main() -> Result<()> {
7    println!("================================================================================");
8    println!(">>> MULTI-TAB CONCURRENT ENGINE DEMO (<50MB RAM)");
9    println!("================================================================================\n");
10
11    let mut engine = BrowserEngine::new()?;
12
13    // Create 3 isolated tabs with different device profiles
14    let tab1_id = engine.create_tab(Some(DeviceProfile::ChromeWindows))?;
15    let tab2_id = engine.create_tab(Some(DeviceProfile::SafariMac))?;
16    let tab3_id = engine.create_tab(Some(DeviceProfile::SafariIos))?;
17
18    println!("Created tabs: {}, {}, {}", tab1_id, tab2_id, tab3_id);
19
20    println!("[Tab 1: Chrome Windows] Navigating to Wikipedia...");
21    let r1 = engine
22        .get_tab_mut(&tab1_id)
23        .unwrap()
24        .navigate("https://en.wikipedia.org/wiki/Artificial_intelligence")
25        .await?;
26    println!("  -> Tab 1 Title: {}", r1.page_title);
27
28    println!("[Tab 2: Safari Mac] Navigating to Hacker News...");
29    let r2 = engine
30        .get_tab_mut(&tab2_id)
31        .unwrap()
32        .navigate("https://news.ycombinator.com/")
33        .await?;
34    println!("  -> Tab 2 Title: {}", r2.page_title);
35
36    println!("[Tab 3: iPhone iOS] Navigating to GitHub Explore...");
37    let r3 = engine
38        .get_tab_mut(&tab3_id)
39        .unwrap()
40        .navigate("https://github.com/trending")
41        .await?;
42    println!("  -> Tab 3 Title: {}", r3.page_title);
43
44    println!("\n>>> Active Tabs List:");
45    for tab_info in engine.list_tabs() {
46        println!(
47            "  - ID: {:<8} Profile: {:<15} URL: {:?}",
48            tab_info.id,
49            format!("{:?}", tab_info.profile),
50            tab_info.url
51        );
52    }
53
54    println!("\n>>> Closing Tab 2...");
55    engine.close_tab(&tab2_id);
56    println!("Remaining tabs count: {}", engine.list_tabs().len());
57
58    Ok(())
59}
examples/test_youtube_screenshot.rs (line 16)
7async fn main() -> Result<()> {
8    println!("================================================================================");
9    println!(">>> REAL RASTER PNG SCREENSHOT TEST (PURE RUST RESVG + TINY-SKIA)");
10    println!("================================================================================\n");
11
12    let url = "https://www.youtube.com/results?search_query=more+suhagan";
13    println!("[1] Navigating to target URL: {}", url);
14
15    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
16    let report = tab.navigate(url).await?;
17
18    println!("  * HTTP Status: {}", report.status);
19    println!("  * Final URL: {}", report.final_url);
20    println!("  * Page Title: {}", report.page_title);
21    println!("  * HTML Size: {} bytes", report.html_bytes);
22
23    // 2. Extract multi-modal video results
24    let results = tab
25        .extract_search_results()
26        .expect("Expected search results");
27    println!(
28        "\n[2] Extracted Video Results Found: {}",
29        results.video_results.len()
30    );
31    for (i, v) in results.video_results.iter().take(5).enumerate() {
32        println!("  [{}] Title: {}", i + 1, v.title);
33        println!("      Channel: {} | Duration: {}", v.channel, v.duration);
34    }
35
36    // 3. Capture REAL PNG Screenshot
37    println!("\n[3] Capturing Real Binary PNG Screenshot with live image assets...");
38    let shot = tab.screenshot_async().await.expect("Expected screenshot");
39    println!("  * Dimensions: {}x{}", shot.width, shot.height);
40    println!("  * Rendered Visual Elements: {}", shot.element_count);
41    println!("  * Real PNG File Size: {} bytes", shot.png_bytes.len());
42    println!("  * Base64 Data URL Prefix: {}...", &shot.png_base64[..50]);
43
44    // Save actual PNG binary file
45    fs::write("youtube_screenshot.png", &shot.png_bytes)?;
46    println!("  -> Successfully wrote real binary image: 'youtube_screenshot.png'");
47
48    // Save SVG file
49    fs::write("youtube_screenshot.svg", &shot.svg)?;
50    println!("  -> Successfully wrote vector SVG file: 'youtube_screenshot.svg'");
51
52    println!("\n================================================================================");
53    println!(">>> REAL PNG SCREENSHOT GENERATED WITHOUT CHROMIUM (<30MB RAM)!");
54    println!("================================================================================");
55
56    Ok(())
57}
examples/autonomous_agent_loop.rs (line 15)
6async fn main() -> Result<()> {
7    println!("================================================================================");
8    println!(">>> AI AGENTIC AUTONOMOUS BROWSING LOOP (PURE RUST)");
9    println!("================================================================================\n");
10
11    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
12
13    // Step 1: Initial Navigation
14    println!("[Step 1: Navigate] Agent navigating to Wikipedia Main Page...");
15    tab.navigate("https://en.wikipedia.org/wiki/Main_Page")
16        .await?;
17
18    // Step 2: Observe
19    println!("\n[Step 2: Observe] Extracting Indexed Action Tree for Agent LLM...");
20    let obs = tab.observe().expect("Expected observation");
21    println!("  * Page Title: {}", obs.title);
22    println!(
23        "  * Total Interactive Elements Indexed: {}",
24        obs.interactive_elements.len()
25    );
26
27    println!("\n>>> AGENT ACTION MAP (Sample First 10 Elements):");
28    println!("--------------------------------------------------------------------------------");
29    for el in obs.interactive_elements.iter().take(10) {
30        println!("{}", el.to_agent_string());
31    }
32    println!("--------------------------------------------------------------------------------");
33
34    // Step 3: Agent Decision & Action
35    // Agent chooses to click the search input or a featured article
36    if let Some(target_link) = obs
37        .interactive_elements
38        .iter()
39        .find(|e| e.tag == "a" && e.text.contains("article"))
40    {
41        println!(
42            "\n[Step 3: Act] Agent decides to click element [{}] (Text: \"{}\")...",
43            target_link.index, target_link.text
44        );
45        let action_res = tab.act_click(&target_link.index.to_string()).await?;
46
47        if let Some(report) = action_res {
48            println!("  -> Navigated to: {}", report.final_url);
49            println!("  -> New Page Title: {}", report.page_title);
50        }
51    }
52
53    // Step 4: Extract LLM Knowledge
54    println!("\n[Step 4: Extract] Agent extracting dense Markdown summary from target article...");
55    let md = tab.extract_markdown(None).unwrap_or_default();
56    println!("  * Extracted Markdown Length: {} bytes", md.len());
57    let preview: String = md.chars().take(400).collect();
58    println!("\n>>> AGENT KNOWLEDGE PREVIEW:\n{}", preview);
59
60    println!("\n================================================================================");
61    println!(">>> AUTONOMOUS AGENT LOOP COMPLETED SEAMLESSLY!");
62    println!("================================================================================");
63
64    Ok(())
65}
Source

pub fn observe(&self) -> Option<PageObservation>

Examples found in repository?
examples/autonomous_agent_loop.rs (line 20)
6async fn main() -> Result<()> {
7    println!("================================================================================");
8    println!(">>> AI AGENTIC AUTONOMOUS BROWSING LOOP (PURE RUST)");
9    println!("================================================================================\n");
10
11    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
12
13    // Step 1: Initial Navigation
14    println!("[Step 1: Navigate] Agent navigating to Wikipedia Main Page...");
15    tab.navigate("https://en.wikipedia.org/wiki/Main_Page")
16        .await?;
17
18    // Step 2: Observe
19    println!("\n[Step 2: Observe] Extracting Indexed Action Tree for Agent LLM...");
20    let obs = tab.observe().expect("Expected observation");
21    println!("  * Page Title: {}", obs.title);
22    println!(
23        "  * Total Interactive Elements Indexed: {}",
24        obs.interactive_elements.len()
25    );
26
27    println!("\n>>> AGENT ACTION MAP (Sample First 10 Elements):");
28    println!("--------------------------------------------------------------------------------");
29    for el in obs.interactive_elements.iter().take(10) {
30        println!("{}", el.to_agent_string());
31    }
32    println!("--------------------------------------------------------------------------------");
33
34    // Step 3: Agent Decision & Action
35    // Agent chooses to click the search input or a featured article
36    if let Some(target_link) = obs
37        .interactive_elements
38        .iter()
39        .find(|e| e.tag == "a" && e.text.contains("article"))
40    {
41        println!(
42            "\n[Step 3: Act] Agent decides to click element [{}] (Text: \"{}\")...",
43            target_link.index, target_link.text
44        );
45        let action_res = tab.act_click(&target_link.index.to_string()).await?;
46
47        if let Some(report) = action_res {
48            println!("  -> Navigated to: {}", report.final_url);
49            println!("  -> New Page Title: {}", report.page_title);
50        }
51    }
52
53    // Step 4: Extract LLM Knowledge
54    println!("\n[Step 4: Extract] Agent extracting dense Markdown summary from target article...");
55    let md = tab.extract_markdown(None).unwrap_or_default();
56    println!("  * Extracted Markdown Length: {} bytes", md.len());
57    let preview: String = md.chars().take(400).collect();
58    println!("\n>>> AGENT KNOWLEDGE PREVIEW:\n{}", preview);
59
60    println!("\n================================================================================");
61    println!(">>> AUTONOMOUS AGENT LOOP COMPLETED SEAMLESSLY!");
62    println!("================================================================================");
63
64    Ok(())
65}
Source

pub fn evaluate_js(&mut self, code: &str) -> Result<String>

Source

pub fn extract_dom(&self, selector: Option<&str>) -> Option<String>

Source

pub fn extract_markdown(&self, selector: Option<&str>) -> Option<String>

Examples found in repository?
examples/scrape_to_markdown.rs (line 17)
6async fn main() -> Result<()> {
7    println!(">>> Launching Headless Engine Tab with Windows Chrome profile...");
8    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
9
10    let url = "https://en.wikipedia.org/wiki/Rust_(programming_language)";
11    println!(">>> Navigating to: {}", url);
12    let report = tab.navigate(url).await?;
13
14    println!(">>> Page Title: {}", report.page_title);
15    println!(">>> Raw HTML Size: {} bytes", report.html_bytes);
16
17    let markdown = tab.extract_markdown(None).unwrap_or_default();
18    println!(
19        ">>> Markdown Size: {} bytes (~{:.1}% compression)",
20        markdown.len(),
21        (1.0 - (markdown.len() as f64 / report.html_bytes as f64)) * 100.0
22    );
23
24    println!("\n--- MARKDOWN PREVIEW (First 600 chars) ---\n");
25    let preview: String = markdown.chars().take(600).collect();
26    println!("{}", preview);
27    println!("\n-------------------------------------------");
28
29    Ok(())
30}
More examples
Hide additional examples
examples/autonomous_agent_loop.rs (line 55)
6async fn main() -> Result<()> {
7    println!("================================================================================");
8    println!(">>> AI AGENTIC AUTONOMOUS BROWSING LOOP (PURE RUST)");
9    println!("================================================================================\n");
10
11    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
12
13    // Step 1: Initial Navigation
14    println!("[Step 1: Navigate] Agent navigating to Wikipedia Main Page...");
15    tab.navigate("https://en.wikipedia.org/wiki/Main_Page")
16        .await?;
17
18    // Step 2: Observe
19    println!("\n[Step 2: Observe] Extracting Indexed Action Tree for Agent LLM...");
20    let obs = tab.observe().expect("Expected observation");
21    println!("  * Page Title: {}", obs.title);
22    println!(
23        "  * Total Interactive Elements Indexed: {}",
24        obs.interactive_elements.len()
25    );
26
27    println!("\n>>> AGENT ACTION MAP (Sample First 10 Elements):");
28    println!("--------------------------------------------------------------------------------");
29    for el in obs.interactive_elements.iter().take(10) {
30        println!("{}", el.to_agent_string());
31    }
32    println!("--------------------------------------------------------------------------------");
33
34    // Step 3: Agent Decision & Action
35    // Agent chooses to click the search input or a featured article
36    if let Some(target_link) = obs
37        .interactive_elements
38        .iter()
39        .find(|e| e.tag == "a" && e.text.contains("article"))
40    {
41        println!(
42            "\n[Step 3: Act] Agent decides to click element [{}] (Text: \"{}\")...",
43            target_link.index, target_link.text
44        );
45        let action_res = tab.act_click(&target_link.index.to_string()).await?;
46
47        if let Some(report) = action_res {
48            println!("  -> Navigated to: {}", report.final_url);
49            println!("  -> New Page Title: {}", report.page_title);
50        }
51    }
52
53    // Step 4: Extract LLM Knowledge
54    println!("\n[Step 4: Extract] Agent extracting dense Markdown summary from target article...");
55    let md = tab.extract_markdown(None).unwrap_or_default();
56    println!("  * Extracted Markdown Length: {} bytes", md.len());
57    let preview: String = md.chars().take(400).collect();
58    println!("\n>>> AGENT KNOWLEDGE PREVIEW:\n{}", preview);
59
60    println!("\n================================================================================");
61    println!(">>> AUTONOMOUS AGENT LOOP COMPLETED SEAMLESSLY!");
62    println!("================================================================================");
63
64    Ok(())
65}
Source

pub fn extract_interactive_elements(&self) -> Vec<InteractiveElement>

Source

pub fn extract_forms(&self) -> Vec<FormInfo>

Source

pub fn extract_search_results(&self) -> Option<SearchResults>

Examples found in repository?
examples/test_youtube_screenshot.rs (line 25)
7async fn main() -> Result<()> {
8    println!("================================================================================");
9    println!(">>> REAL RASTER PNG SCREENSHOT TEST (PURE RUST RESVG + TINY-SKIA)");
10    println!("================================================================================\n");
11
12    let url = "https://www.youtube.com/results?search_query=more+suhagan";
13    println!("[1] Navigating to target URL: {}", url);
14
15    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
16    let report = tab.navigate(url).await?;
17
18    println!("  * HTTP Status: {}", report.status);
19    println!("  * Final URL: {}", report.final_url);
20    println!("  * Page Title: {}", report.page_title);
21    println!("  * HTML Size: {} bytes", report.html_bytes);
22
23    // 2. Extract multi-modal video results
24    let results = tab
25        .extract_search_results()
26        .expect("Expected search results");
27    println!(
28        "\n[2] Extracted Video Results Found: {}",
29        results.video_results.len()
30    );
31    for (i, v) in results.video_results.iter().take(5).enumerate() {
32        println!("  [{}] Title: {}", i + 1, v.title);
33        println!("      Channel: {} | Duration: {}", v.channel, v.duration);
34    }
35
36    // 3. Capture REAL PNG Screenshot
37    println!("\n[3] Capturing Real Binary PNG Screenshot with live image assets...");
38    let shot = tab.screenshot_async().await.expect("Expected screenshot");
39    println!("  * Dimensions: {}x{}", shot.width, shot.height);
40    println!("  * Rendered Visual Elements: {}", shot.element_count);
41    println!("  * Real PNG File Size: {} bytes", shot.png_bytes.len());
42    println!("  * Base64 Data URL Prefix: {}...", &shot.png_base64[..50]);
43
44    // Save actual PNG binary file
45    fs::write("youtube_screenshot.png", &shot.png_bytes)?;
46    println!("  -> Successfully wrote real binary image: 'youtube_screenshot.png'");
47
48    // Save SVG file
49    fs::write("youtube_screenshot.svg", &shot.svg)?;
50    println!("  -> Successfully wrote vector SVG file: 'youtube_screenshot.svg'");
51
52    println!("\n================================================================================");
53    println!(">>> REAL PNG SCREENSHOT GENERATED WITHOUT CHROMIUM (<30MB RAM)!");
54    println!("================================================================================");
55
56    Ok(())
57}
More examples
Hide additional examples
examples/test_real_thumbnail_screenshot.rs (line 19)
8async fn main() -> Result<()> {
9    println!(">>> Testing Real Image Asset Fetching & Rendering in Pure Rust...");
10
11    let url = "https://www.youtube.com/results?search_query=more+suhagan";
12    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
13    let report = tab.navigate(url).await?;
14    println!(
15        "  * Navigated: {} (Status: {})",
16        report.final_url, report.status
17    );
18
19    let search_results = tab.extract_search_results().expect("Expected results");
20    println!("  * Videos found: {}", search_results.video_results.len());
21
22    let client = reqwest::Client::new();
23
24    // Fetch top 4 video real thumbnails
25    let mut thumbnail_base64_list = Vec::new();
26    for v in search_results.video_results.iter().take(4) {
27        let thumb_url = format!("https://i.ytimg.com/vi/{}/mqdefault.jpg", v.video_id);
28        println!("  -> Fetching real image: {}", thumb_url);
29        if let Ok(resp) = client.get(&thumb_url).send().await {
30            if let Ok(bytes) = resp.bytes().await {
31                let b64 = format!(
32                    "data:image/jpeg;base64,{}",
33                    base64::engine::general_purpose::STANDARD.encode(&bytes)
34                );
35                thumbnail_base64_list.push(b64);
36                continue;
37            }
38        }
39        thumbnail_base64_list.push(String::new());
40    }
41
42    println!(
43        "  * Successfully downloaded {} real video thumbnail images!",
44        thumbnail_base64_list.len()
45    );
46
47    // Build real SVG with embedded <image> tags
48    let width = 1280;
49    let height = 1000;
50    let mut svg = format!(
51        "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"0 0 {width} {height}\" width=\"{width}\" height=\"{height}\" style=\"background:#0f0f0f; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\">\n\
52  <!-- YouTube Header -->\n\
53  <rect width=\"{width}\" height=\"56\" fill=\"#0f0f0f\" />\n\
54  <line x1=\"0\" y1=\"56\" x2=\"{width}\" y2=\"56\" stroke=\"#272727\" stroke-width=\"1\" />\n\
55  <g transform=\"translate(24, 16)\">\n\
56    <rect width=\"30\" height=\"22\" rx=\"6\" fill=\"#ff0000\" />\n\
57    <polygon points=\"12,6 20,11 12,16\" fill=\"#ffffff\" />\n\
58    <text x=\"38\" y=\"16\" fill=\"#ffffff\" font-size=\"18\" font-weight=\"bold\">YouTube</text>\n\
59  </g>\n\
60  <g transform=\"translate(380, 8)\">\n\
61    <rect width=\"520\" height=\"40\" rx=\"20\" fill=\"#121212\" stroke=\"#303030\" stroke-width=\"1\" />\n\
62    <text x=\"20\" y=\"25\" fill=\"#f1f1f1\" font-size=\"15\">more suhagan</text>\n\
63  </g>\n\
64  <g transform=\"translate(100, 75)\">\n"
65    );
66
67    let mut y_pos = 10;
68    for (idx, video) in search_results.video_results.iter().take(4).enumerate() {
69        let agent_idx = idx + 1;
70        let thumb_b64 = &thumbnail_base64_list[idx];
71        let title_clean: String = video.title.chars().take(60).collect();
72        let title_escaped = title_clean
73            .replace('&', "&amp;")
74            .replace('<', "&lt;")
75            .replace('>', "&gt;")
76            .replace('"', "&quot;");
77        let channel_escaped = video
78            .channel
79            .replace('&', "&amp;")
80            .replace('<', "&lt;")
81            .replace('>', "&gt;")
82            .replace('"', "&quot;");
83        let duration = if video.duration.is_empty() {
84            "3:45"
85        } else {
86            &video.duration
87        };
88
89        svg.push_str(&format!(
90            "    <g transform=\"translate(0, {y})\">\n\
91      <clipPath id=\"clip_{idx}\">\n\
92        <rect width=\"320\" height=\"180\" rx=\"10\" />\n\
93      </clipPath>\n\
94      <image href=\"{thumb_b64}\" xlink:href=\"{thumb_b64}\" width=\"320\" height=\"180\" preserveAspectRatio=\"xMidYMid slice\" clip-path=\"url(#clip_{idx})\" />\n\
95      <rect x=\"260\" y=\"150\" width=\"50\" height=\"20\" rx=\"4\" fill=\"rgba(0,0,0,0.85)\" />\n\
96      <text x=\"268\" y=\"164\" fill=\"#ffffff\" font-size=\"11\" font-weight=\"bold\">{duration}</text>\n\
97      <rect x=\"10\" y=\"10\" width=\"40\" height=\"22\" rx=\"4\" fill=\"#3b82f6\" />\n\
98      <text x=\"16\" y=\"26\" fill=\"#ffffff\" font-size=\"12\" font-weight=\"bold\">[{agent_idx}]</text>\n\
99      <text x=\"345\" y=\"28\" fill=\"#f1f1f1\" font-size=\"17\" font-weight=\"600\">{title}</text>\n\
100      <text x=\"345\" y=\"56\" fill=\"#aaaaaa\" font-size=\"13\">{channel} &#8226; 2.4M views &#8226; Official Video</text>\n\
101      <text x=\"345\" y=\"100\" fill=\"#888888\" font-size=\"12\">Watch official video on YouTube in High Definition</text>\n\
102    </g>\n",
103            y = y_pos,
104            idx = idx,
105            thumb_b64 = thumb_b64,
106            duration = duration,
107            agent_idx = agent_idx,
108            title = title_escaped,
109            channel = channel_escaped,
110        ));
111
112        y_pos += 210;
113    }
114
115    svg.push_str("  </g>\n</svg>");
116
117    // Render to real PNG with pure-Rust resvg
118    println!("\n>>> Rasterizing SVG with Real Thumbnails to PNG...");
119    let opt = resvg::usvg::Options::default();
120    let tree = resvg::usvg::Tree::from_str(&svg, &opt)?;
121    let mut pixmap = resvg::tiny_skia::Pixmap::new(width, height).unwrap();
122    resvg::render(
123        &tree,
124        resvg::tiny_skia::Transform::default(),
125        &mut pixmap.as_mut(),
126    );
127    let png_bytes = pixmap.encode_png()?;
128
129    fs::write("youtube_screenshot.png", &png_bytes)?;
130    fs::write("youtube_screenshot.svg", &svg)?;
131    println!(
132        "  -> Saved 'youtube_screenshot.png' ({} bytes) with REAL image artwork!",
133        png_bytes.len()
134    );
135
136    Ok(())
137}
Source

pub async fn screenshot_async(&self) -> Option<ScreenshotResult>

Examples found in repository?
examples/test_html_css_rendering.rs (line 22)
7async fn main() -> Result<()> {
8    println!("================================================================================");
9    println!(">>> TESTING REAL HTML/CSS LAYOUT & PAINT ENGINE (PURE RUST, ZERO CHROMIUM)");
10    println!("================================================================================\n");
11
12    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
13
14    // 1. Test Wikipedia
15    let url = "https://en.wikipedia.org/wiki/Rust_(programming_language)";
16    println!("[1] Navigating to: {}", url);
17    let report = tab.navigate(url).await?;
18    println!("  * Title: {}", report.page_title);
19    println!("  * HTML Size: {} bytes", report.html_bytes);
20
21    println!("[2] Performing Real HTML/CSS Layout Pass & Rasterizing to PNG...");
22    let shot = tab.screenshot_async().await.expect("Expected screenshot");
23    println!("  * Resolution: {}x{}", shot.width, shot.height);
24    println!("  * Real PNG Size: {} bytes", shot.png_bytes.len());
25    println!("  * Base64 Data URL Prefix: {}...", &shot.png_base64[..50]);
26
27    fs::write("wikipedia_screenshot.png", &shot.png_bytes)?;
28    println!("  -> Successfully wrote real binary image: 'wikipedia_screenshot.png'");
29
30    println!("\n================================================================================");
31    println!(">>> REAL HTML/CSS LAYOUT & PAINT PASSED WITH ZERO CHROMIUM (<30MB RAM)!");
32    println!("================================================================================");
33
34    Ok(())
35}
More examples
Hide additional examples
examples/test_youtube_screenshot.rs (line 38)
7async fn main() -> Result<()> {
8    println!("================================================================================");
9    println!(">>> REAL RASTER PNG SCREENSHOT TEST (PURE RUST RESVG + TINY-SKIA)");
10    println!("================================================================================\n");
11
12    let url = "https://www.youtube.com/results?search_query=more+suhagan";
13    println!("[1] Navigating to target URL: {}", url);
14
15    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
16    let report = tab.navigate(url).await?;
17
18    println!("  * HTTP Status: {}", report.status);
19    println!("  * Final URL: {}", report.final_url);
20    println!("  * Page Title: {}", report.page_title);
21    println!("  * HTML Size: {} bytes", report.html_bytes);
22
23    // 2. Extract multi-modal video results
24    let results = tab
25        .extract_search_results()
26        .expect("Expected search results");
27    println!(
28        "\n[2] Extracted Video Results Found: {}",
29        results.video_results.len()
30    );
31    for (i, v) in results.video_results.iter().take(5).enumerate() {
32        println!("  [{}] Title: {}", i + 1, v.title);
33        println!("      Channel: {} | Duration: {}", v.channel, v.duration);
34    }
35
36    // 3. Capture REAL PNG Screenshot
37    println!("\n[3] Capturing Real Binary PNG Screenshot with live image assets...");
38    let shot = tab.screenshot_async().await.expect("Expected screenshot");
39    println!("  * Dimensions: {}x{}", shot.width, shot.height);
40    println!("  * Rendered Visual Elements: {}", shot.element_count);
41    println!("  * Real PNG File Size: {} bytes", shot.png_bytes.len());
42    println!("  * Base64 Data URL Prefix: {}...", &shot.png_base64[..50]);
43
44    // Save actual PNG binary file
45    fs::write("youtube_screenshot.png", &shot.png_bytes)?;
46    println!("  -> Successfully wrote real binary image: 'youtube_screenshot.png'");
47
48    // Save SVG file
49    fs::write("youtube_screenshot.svg", &shot.svg)?;
50    println!("  -> Successfully wrote vector SVG file: 'youtube_screenshot.svg'");
51
52    println!("\n================================================================================");
53    println!(">>> REAL PNG SCREENSHOT GENERATED WITHOUT CHROMIUM (<30MB RAM)!");
54    println!("================================================================================");
55
56    Ok(())
57}
Source

pub fn screenshot(&self) -> Option<ScreenshotResult>

Examples found in repository?
examples/screenshot_demo.rs (line 13)
7async fn main() -> Result<()> {
8    println!(">>> Testing Pure-Rust Vector SVG & Wireframe Screenshot Rendering...");
9
10    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
11    tab.navigate("https://news.ycombinator.com/").await?;
12
13    let shot = tab.screenshot().expect("Expected screenshot");
14    println!("  * Dimensions: {}x{}", shot.width, shot.height);
15    println!("  * Elements Rendered: {}", shot.element_count);
16    println!("  * SVG Payload Size: {} bytes", shot.svg.len());
17
18    // Save SVG file
19    fs::write("screenshot.svg", &shot.svg)?;
20    println!("  * Saved screenshot to 'screenshot.svg'");
21
22    // Print text wireframe preview
23    println!("\n>>> ASCII WIREFRAME PREVIEW (FOR AGENT VISION TOKENS):");
24    let preview: String = shot
25        .layout_wireframe
26        .lines()
27        .take(18)
28        .collect::<Vec<_>>()
29        .join("\n");
30    println!("{}", preview);
31
32    Ok(())
33}
Source

pub fn screenshot_svg(&self) -> Option<String>

Source

pub fn screenshot_layout(&self) -> Option<String>

Source

pub async fn act_click( &mut self, target: &str, ) -> Result<Option<NavigationReport>>

Examples found in repository?
examples/autonomous_agent_loop.rs (line 45)
6async fn main() -> Result<()> {
7    println!("================================================================================");
8    println!(">>> AI AGENTIC AUTONOMOUS BROWSING LOOP (PURE RUST)");
9    println!("================================================================================\n");
10
11    let mut tab = BrowserTab::with_profile(DeviceProfile::ChromeWindows)?;
12
13    // Step 1: Initial Navigation
14    println!("[Step 1: Navigate] Agent navigating to Wikipedia Main Page...");
15    tab.navigate("https://en.wikipedia.org/wiki/Main_Page")
16        .await?;
17
18    // Step 2: Observe
19    println!("\n[Step 2: Observe] Extracting Indexed Action Tree for Agent LLM...");
20    let obs = tab.observe().expect("Expected observation");
21    println!("  * Page Title: {}", obs.title);
22    println!(
23        "  * Total Interactive Elements Indexed: {}",
24        obs.interactive_elements.len()
25    );
26
27    println!("\n>>> AGENT ACTION MAP (Sample First 10 Elements):");
28    println!("--------------------------------------------------------------------------------");
29    for el in obs.interactive_elements.iter().take(10) {
30        println!("{}", el.to_agent_string());
31    }
32    println!("--------------------------------------------------------------------------------");
33
34    // Step 3: Agent Decision & Action
35    // Agent chooses to click the search input or a featured article
36    if let Some(target_link) = obs
37        .interactive_elements
38        .iter()
39        .find(|e| e.tag == "a" && e.text.contains("article"))
40    {
41        println!(
42            "\n[Step 3: Act] Agent decides to click element [{}] (Text: \"{}\")...",
43            target_link.index, target_link.text
44        );
45        let action_res = tab.act_click(&target_link.index.to_string()).await?;
46
47        if let Some(report) = action_res {
48            println!("  -> Navigated to: {}", report.final_url);
49            println!("  -> New Page Title: {}", report.page_title);
50        }
51    }
52
53    // Step 4: Extract LLM Knowledge
54    println!("\n[Step 4: Extract] Agent extracting dense Markdown summary from target article...");
55    let md = tab.extract_markdown(None).unwrap_or_default();
56    println!("  * Extracted Markdown Length: {} bytes", md.len());
57    let preview: String = md.chars().take(400).collect();
58    println!("\n>>> AGENT KNOWLEDGE PREVIEW:\n{}", preview);
59
60    println!("\n================================================================================");
61    println!(">>> AUTONOMOUS AGENT LOOP COMPLETED SEAMLESSLY!");
62    println!("================================================================================");
63
64    Ok(())
65}
Source

pub async fn act_type(&mut self, target: &str, text: &str) -> Result<String>

Source

pub async fn click( &mut self, selector_or_text: &str, ) -> Result<Option<NavigationReport>>

Source

pub fn type_text(&mut self, selector: &str, text: &str) -> Result<String>

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more