fix: polish two Hermes follow-up cosmetics (invalid-selector wording, empty url glob)
Release binaries / Build macOS ARM64 (push) Has been cancelled
Release binaries / Build macOS x64 (push) Has been cancelled
Release binaries / Build Linux ARM64 (push) Has been cancelled
Release binaries / Build Linux musl ARM64 (push) Has been cancelled
Release binaries / Build Linux musl x64 (push) Has been cancelled
Release binaries / Build Linux x64 (push) Has been cancelled
Release binaries / Build Windows x64 (push) Has been cancelled
Release binaries / Attach binaries to GitHub Release (push) Has been cancelled
Release binaries / Build macOS ARM64 (push) Has been cancelled
Release binaries / Build macOS x64 (push) Has been cancelled
Release binaries / Build Linux ARM64 (push) Has been cancelled
Release binaries / Build Linux musl ARM64 (push) Has been cancelled
Release binaries / Build Linux musl x64 (push) Has been cancelled
Release binaries / Build Linux x64 (push) Has been cancelled
Release binaries / Build Windows x64 (push) Has been cancelled
Release binaries / Attach binaries to GitHub Release (push) Has been cancelled
- invalid CSS selector now errors "Invalid selector '<sel>': <reason>" instead of
the misleading "Element not found" — the coordinate path (resolve_by_selector)
now also inspects exception_details, matching resolve_element_object_id.
- `wait --url ""` is rejected at parse time ("needs a non-empty pattern") rather
than silently matching any URL. Unit test added.
Not changed: verb-less `find role X` defaulting to a click. That default is a
deliberate, tested decision (test_find_role_default_subaction_click_when_no_action);
changing it to locate-and-report is a design choice left to the maintainer.
This commit is contained in:
Generated
+1
-1
@@ -45,7 +45,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "agent-browser-stealth"
|
name = "agent-browser-stealth"
|
||||||
version = "0.27.0-fork.32"
|
version = "0.27.0-fork.33"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "agent-browser-stealth"
|
name = "agent-browser-stealth"
|
||||||
version = "0.27.0-fork.32"
|
version = "0.27.0-fork.33"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Fast browser automation CLI for AI agents"
|
description = "Fast browser automation CLI for AI agents"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
|
|||||||
@@ -548,6 +548,14 @@ fn parse_command_inner(args: &[String], flags: &Flags) -> Result<Value, ParseErr
|
|||||||
context: "wait --url".to_string(),
|
context: "wait --url".to_string(),
|
||||||
usage: "wait --url <pattern>",
|
usage: "wait --url <pattern>",
|
||||||
})?;
|
})?;
|
||||||
|
if url.is_empty() {
|
||||||
|
return Err(ParseError::InvalidValue {
|
||||||
|
message: "wait --url needs a non-empty pattern (an empty pattern would \
|
||||||
|
match any URL)."
|
||||||
|
.to_string(),
|
||||||
|
usage: "wait --url <pattern>",
|
||||||
|
});
|
||||||
|
}
|
||||||
let mut cmd = json!({ "id": id, "action": "waitforurl", "url": url });
|
let mut cmd = json!({ "id": id, "action": "waitforurl", "url": url });
|
||||||
// Parse --timeout (without it the default applies — and a
|
// Parse --timeout (without it the default applies — and a
|
||||||
// non-matching pattern would otherwise wait the full default).
|
// non-matching pattern would otherwise wait the full default).
|
||||||
@@ -3811,6 +3819,15 @@ mod tests {
|
|||||||
assert_eq!(cmd["url"], "**/dashboard");
|
assert_eq!(cmd["url"], "**/dashboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_wait_url_empty_pattern_rejected() {
|
||||||
|
// An empty pattern would match any URL — reject it rather than silently
|
||||||
|
// always-match. (Build argv directly: split_whitespace can't yield "".)
|
||||||
|
let argv = vec!["wait".to_string(), "--url".to_string(), String::new()];
|
||||||
|
let err = parse_command(&argv, &default_flags());
|
||||||
|
assert!(err.is_err(), "empty --url pattern should be rejected");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wait_url_with_timeout() {
|
fn test_wait_url_with_timeout() {
|
||||||
// --timeout must be parsed for the --url path; without it a non-matching
|
// --timeout must be parsed for the --url path; without it a non-matching
|
||||||
|
|||||||
@@ -845,6 +845,12 @@ async fn resolve_by_selector(
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
// A syntactically-invalid CSS selector makes querySelector throw — surface
|
||||||
|
// that as "invalid selector" rather than a misleading "element not found".
|
||||||
|
if let Some(ex) = result.exception_details {
|
||||||
|
return Err(format!("Invalid selector '{}': {}", selector, ex.text));
|
||||||
|
}
|
||||||
|
|
||||||
let val = result.result.value.unwrap_or(Value::Null);
|
let val = result.result.value.unwrap_or(Value::Null);
|
||||||
let x = val.get("x").and_then(|v| v.as_f64());
|
let x = val.get("x").and_then(|v| v.as_f64());
|
||||||
let y = val.get("y").and_then(|v| v.as_f64());
|
let y = val.get("y").and_then(|v| v.as_f64());
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "agent-browser-stealth",
|
"name": "agent-browser-stealth",
|
||||||
"version": "0.27.0-fork.32",
|
"version": "0.27.0-fork.33",
|
||||||
"description": "Browser automation CLI for AI agents — stealth fork with anti-detection",
|
"description": "Browser automation CLI for AI agents — stealth fork with anti-detection",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"packageManager": "pnpm@11.1.3",
|
"packageManager": "pnpm@11.1.3",
|
||||||
|
|||||||
Reference in New Issue
Block a user