Add --stdin flag for eval command (#348)

Adds --stdin flag to read JavaScript from stdin, enabling heredoc usage
for multiline scripts without shell escaping issues.
This commit is contained in:
Chris Tate
2026-02-02 20:29:43 -06:00
committed by GitHub
parent f770593c66
commit 0dc36f2cff
5 changed files with 50 additions and 17 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"agent-browser": patch
---
Add --stdin flag for eval command to read JavaScript from stdin, enabling heredoc usage for multiline scripts
+1 -1
View File
@@ -77,7 +77,7 @@ agent-browser upload <sel> <files> # Upload files
agent-browser screenshot [path] # Take screenshot (--full for full page, saves to a temporary directory if no path) agent-browser screenshot [path] # Take screenshot (--full for full page, saves to a temporary directory if no path)
agent-browser pdf <path> # Save as PDF agent-browser pdf <path> # Save as PDF
agent-browser snapshot # Accessibility tree with refs (best for AI) agent-browser snapshot # Accessibility tree with refs (best for AI)
agent-browser eval <js> # Run JavaScript agent-browser eval <js> # Run JavaScript (-b for base64, --stdin for piped input)
agent-browser connect <port> # Connect to browser via CDP agent-browser connect <port> # Connect to browser via CDP
agent-browser close # Close browser (aliases: quit, exit) agent-browser close # Close browser (aliases: quit, exit)
``` ```
+28 -14
View File
@@ -1,5 +1,6 @@
use base64::{engine::general_purpose::STANDARD, Engine}; use base64::{engine::general_purpose::STANDARD, Engine};
use serde_json::{json, Value}; use serde_json::{json, Value};
use std::io::{self, BufRead};
use crate::flags::Flags; use crate::flags::Flags;
@@ -419,24 +420,37 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result<Value, ParseError
// === Eval === // === Eval ===
"eval" => { "eval" => {
let (is_base64, script_parts): (bool, &[&str]) = // Check for flags: -b/--base64 or --stdin
let (is_base64, is_stdin, script_parts): (bool, bool, &[&str]) =
if rest.first() == Some(&"-b") || rest.first() == Some(&"--base64") { if rest.first() == Some(&"-b") || rest.first() == Some(&"--base64") {
(true, &rest[1..]) (true, false, &rest[1..])
} else if rest.first() == Some(&"--stdin") {
(false, true, &rest[1..])
} else { } else {
(false, rest.as_slice()) (false, false, rest.as_slice())
}; };
let raw_script = script_parts.join(" ");
let script = if is_base64 { let script = if is_stdin {
let decoded = STANDARD.decode(&raw_script).map_err(|_| ParseError::InvalidValue { // Read script from stdin
message: "Invalid base64 encoding".to_string(), let stdin = io::stdin();
usage: "eval -b <base64-encoded-script>", let lines: Vec<String> = stdin.lock().lines()
})?; .map(|l| l.unwrap_or_default())
String::from_utf8(decoded).map_err(|_| ParseError::InvalidValue { .collect();
message: "Base64 decoded to invalid UTF-8".to_string(), lines.join("\n")
usage: "eval -b <base64-encoded-script>",
})?
} else { } else {
raw_script let raw_script = script_parts.join(" ");
if is_base64 {
let decoded = STANDARD.decode(&raw_script).map_err(|_| ParseError::InvalidValue {
message: "Invalid base64 encoding".to_string(),
usage: "eval -b <base64-encoded-script>",
})?;
String::from_utf8(decoded).map_err(|_| ParseError::InvalidValue {
message: "Base64 decoded to invalid UTF-8".to_string(),
usage: "eval -b <base64-encoded-script>",
})?
} else {
raw_script
}
}; };
Ok(json!({ "id": id, "action": "evaluate", "script": script })) Ok(json!({ "id": id, "action": "evaluate", "script": script }))
} }
+7
View File
@@ -885,6 +885,7 @@ Executes JavaScript code in the browser context and returns the result.
Options: Options:
-b, --base64 Decode script from base64 (avoids shell escaping issues) -b, --base64 Decode script from base64 (avoids shell escaping issues)
--stdin Read script from stdin (useful for heredocs/multiline)
Global Options: Global Options:
--json Output as JSON --json Output as JSON
@@ -895,6 +896,12 @@ Examples:
agent-browser eval "window.location.href" agent-browser eval "window.location.href"
agent-browser eval "document.querySelectorAll('a').length" agent-browser eval "document.querySelectorAll('a').length"
agent-browser eval -b "ZG9jdW1lbnQudGl0bGU=" agent-browser eval -b "ZG9jdW1lbnQudGl0bGU="
# Read from stdin with heredoc
cat <<'EOF' | agent-browser eval --stdin
const links = document.querySelectorAll('a');
links.length;
EOF
"## "##
} }
+9 -2
View File
@@ -189,14 +189,21 @@ agent-browser dialog dismiss # Dismiss dialog
```bash ```bash
agent-browser eval "document.title" # Simple expressions only agent-browser eval "document.title" # Simple expressions only
agent-browser eval -b "<base64>" # Any JavaScript (recommended) agent-browser eval -b "<base64>" # Any JavaScript (base64 encoded)
agent-browser eval --stdin # Read script from stdin
``` ```
Use `-b`/`--base64` for reliable execution. Shell escaping with nested quotes and special characters is error-prone. Use `-b`/`--base64` or `--stdin` for reliable execution. Shell escaping with nested quotes and special characters is error-prone.
```bash ```bash
# Base64 encode your script, then: # Base64 encode your script, then:
agent-browser eval -b "ZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW3NyYyo9Il9uZXh0Il0nKQ==" agent-browser eval -b "ZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW3NyYyo9Il9uZXh0Il0nKQ=="
# Or use stdin with heredoc for multiline scripts:
cat <<'EOF' | agent-browser eval --stdin
const links = document.querySelectorAll('a');
Array.from(links).map(a => a.href);
EOF
``` ```
## State Management ## State Management