diff --git a/cli/src/commands.rs b/cli/src/commands.rs index 73c9332..c725a75 100644 --- a/cli/src/commands.rs +++ b/cli/src/commands.rs @@ -418,6 +418,33 @@ fn parse_command_inner(args: &[String], flags: &Flags) -> Result { + // pick --option "" — atomic combobox select: + // open the control, wait for options (incl. portal menus), match by + // text, fire the right event sequence, verify. Covers native `, +/// ARIA combobox/listbox, and react-select, which a bare `click`+`press Enter` +/// can't do reliably. Runs as one in-page async routine so the open→render→pick +/// dance happens without round-trips that let the menu collapse between commands. +async fn handle_pick(cmd: &Value, state: &mut DaemonState) -> Result { + let mgr = state.browser.as_ref().ok_or("Browser not launched")?; + let session_id = mgr.active_session_id()?.to_string(); + let selector = cmd + .get("selector") + .and_then(|v| v.as_str()) + .ok_or("Missing 'selector' parameter")?; + let option = cmd + .get("option") + .and_then(|v| v.as_str()) + .ok_or("Missing 'option' parameter")?; + + let (object_id, effective_session_id) = super::element::resolve_element_object_id( + &mgr.client, + &session_id, + &state.ref_map, + selector, + &state.iframe_sessions, + ) + .await?; + + let func = format!( + r#"async function() {{ + const want = {opt}; + const norm = s => (s || '').replace(/\s+/g, ' ').trim(); + const matches = el => norm(el.textContent).toLowerCase().includes(want.toLowerCase()); + const el = this; + const fire = (n, t) => n.dispatchEvent(new MouseEvent(t, {{ bubbles: true, cancelable: true, view: window }})); + + // Native only agent-browser select @e4 "a" "b" # select multiple +agent-browser pick @e4 --option "Europe" # ANY combobox (react-select / ARIA / + # native): opens it, waits for the menu + # (incl. portal-rendered), matches by + # visible text, fires the right events, + # and ERRORS if the option never shows + # (no silent no-op). Use this for custom + # dropdowns where `select` returns ✓ but + # changes nothing. agent-browser upload @e5 file1.pdf # upload file(s) agent-browser scroll down 500 # scroll page (up/down/left/right) agent-browser scrollintoview @e1 # scroll element into view