diff --git a/cli/src/native/actions.rs b/cli/src/native/actions.rs index 77d5b73..573974f 100644 --- a/cli/src/native/actions.rs +++ b/cli/src/native/actions.rs @@ -167,7 +167,8 @@ impl DaemonState { if let Ok(te) = serde_json::from_value::(event.params.clone()) { - if te.target_info.target_type == "page" + if (te.target_info.target_type == "page" + || te.target_info.target_type == "webview") && !te.target_info.url.is_empty() { let already_tracked = self @@ -443,6 +444,7 @@ pub async fn execute_command(cmd: &Value, state: &mut DaemonState) -> Value { session_id: attach.session_id, url: te.target_info.url.clone(), title: te.target_info.title.clone(), + target_type: te.target_info.target_type.clone(), }); } } @@ -2468,6 +2470,7 @@ async fn handle_recording_start(cmd: &Value, state: &mut DaemonState) -> Result< session_id: new_session_id.clone(), url: nav_url.clone(), title: String::new(), + target_type: "page".to_string(), }); // Navigate to URL @@ -4057,6 +4060,7 @@ async fn handle_window_new(cmd: &Value, state: &mut DaemonState) -> Result = result .target_infos .into_iter() - .filter(|t| t.target_type == "page" && !t.url.is_empty()) + .filter(|t| { + (t.target_type == "page" || t.target_type == "webview") && !t.url.is_empty() + }) .collect(); if page_targets.is_empty() { @@ -348,6 +351,7 @@ impl BrowserManager { session_id: attach_result.session_id.clone(), url: "about:blank".to_string(), title: String::new(), + target_type: "page".to_string(), }); self.active_page_index = 0; self.enable_domains(&attach_result.session_id).await?; @@ -370,6 +374,7 @@ impl BrowserManager { session_id: attach_result.session_id.clone(), url: target.url.clone(), title: target.title.clone(), + target_type: target.target_type.clone(), }); } @@ -664,6 +669,7 @@ impl BrowserManager { session_id: attach_result.session_id.clone(), url: "about:blank".to_string(), title: String::new(), + target_type: "page".to_string(), }); self.active_page_index = 0; self.enable_domains(&attach_result.session_id).await?; @@ -696,6 +702,7 @@ impl BrowserManager { "index": i, "title": p.title, "url": p.url, + "type": p.target_type, "active": i == self.active_page_index, }) }) @@ -736,6 +743,7 @@ impl BrowserManager { session_id: attach.session_id, url: target_url.to_string(), title: String::new(), + target_type: "page".to_string(), }); self.active_page_index = index; diff --git a/skills/electron/SKILL.md b/skills/electron/SKILL.md index 8de5718..4931da6 100644 --- a/skills/electron/SKILL.md +++ b/skills/electron/SKILL.md @@ -102,6 +102,31 @@ agent-browser tab 2 agent-browser tab --url "*settings*" ``` +## Webview Support + +Electron `` elements are automatically discovered and can be controlled like regular pages. When using `--native` mode, webviews appear as separate targets in the tab list with `type: "webview"`: + +```bash +# Connect in native mode +agent-browser --native connect 9222 + +# List targets -- webviews appear alongside pages +agent-browser tab +# Example output: +# 0: [page] Slack - Main Window https://app.slack.com/ +# 1: [webview] Embedded Content https://example.com/widget + +# Switch to a webview +agent-browser tab 1 + +# Interact with the webview normally +agent-browser snapshot -i +agent-browser click @e3 +agent-browser screenshot webview.png +``` + +**Note:** Webview support requires `--native` mode (raw CDP). The Playwright-based mode does not support webview targets. + ## Common Patterns ### Inspect and Navigate an App