diff --git a/README.md b/README.md index 5f553ba..3a17e19 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,8 @@ flowchart TD - Reuse session state with `--session-name` for continuity. - Keep locale/timezone consistent with target market. - Use `--risk-mode block` in strict pipelines that require explicit operator intervention on verification pages. +- For `cookies set`, use either `--url `, or `--domain --path ` together. +- If `--url`, `--domain`, and `--path` are all omitted, the cookie is scoped from the current page URL. ## Validation Scripts diff --git a/cli/src/commands.rs b/cli/src/commands.rs index 57554f4..820d44d 100644 --- a/cli/src/commands.rs +++ b/cli/src/commands.rs @@ -828,6 +828,17 @@ pub fn parse_command(args: &[String], flags: &Flags) -> Result and --path ", + }); + } + Ok(json!({ "id": id, "action": "cookies_set", "cookies": [cookie] })) } "clear" => Ok(json!({ "id": id, "action": "cookies_clear" })), @@ -2097,28 +2108,34 @@ mod tests { } #[test] - fn test_cookies_set_with_domain() { - let cmd = parse_command( + fn test_cookies_set_with_domain_requires_path() { + let result = parse_command( &args("cookies set mycookie myvalue --domain example.com"), &default_flags(), + ); + assert!(result.is_err()); + } + + #[test] + fn test_cookies_set_with_path_requires_domain() { + let result = parse_command( + &args("cookies set mycookie myvalue --path /api"), + &default_flags(), + ); + assert!(result.is_err()); + } + + #[test] + fn test_cookies_set_with_domain_and_path() { + let cmd = parse_command( + &args("cookies set mycookie myvalue --domain example.com --path /api"), + &default_flags(), ) .unwrap(); assert_eq!(cmd["action"], "cookies_set"); assert_eq!(cmd["cookies"][0]["name"], "mycookie"); assert_eq!(cmd["cookies"][0]["value"], "myvalue"); assert_eq!(cmd["cookies"][0]["domain"], "example.com"); - } - - #[test] - fn test_cookies_set_with_path() { - let cmd = parse_command( - &args("cookies set mycookie myvalue --path /api"), - &default_flags(), - ) - .unwrap(); - assert_eq!(cmd["action"], "cookies_set"); - assert_eq!(cmd["cookies"][0]["name"], "mycookie"); - assert_eq!(cmd["cookies"][0]["value"], "myvalue"); assert_eq!(cmd["cookies"][0]["path"], "/api"); } diff --git a/cli/src/output.rs b/cli/src/output.rs index 834942b..0f3ae46 100644 --- a/cli/src/output.rs +++ b/cli/src/output.rs @@ -1486,8 +1486,8 @@ Operations: Cookie Set Options: --url URL for the cookie (allows setting before page load) - --domain Cookie domain (e.g., ".example.com") - --path Cookie path (e.g., "/api") + --domain Cookie domain (use with --path, e.g., ".example.com") + --path Cookie path (use with --domain, e.g., "/api") --httpOnly Set HttpOnly flag (prevents JavaScript access) --secure Set Secure flag (HTTPS only) --sameSite SameSite policy @@ -1495,6 +1495,7 @@ Cookie Set Options: Note: If --url, --domain, and --path are all omitted, the cookie will be set for the current page URL. +When --url is omitted, --domain and --path must be provided together. Global Options: --json Output as JSON diff --git a/docs/src/app/commands/page.mdx b/docs/src/app/commands/page.mdx index 6be0158..63477c3 100644 --- a/docs/src/app/commands/page.mdx +++ b/docs/src/app/commands/page.mdx @@ -172,6 +172,14 @@ agent-browser storage local clear # Clear all agent-browser storage session # Same for sessionStorage ``` +For `cookies set`, use one of these patterns: + +- `--url ` +- `--domain --path ` +- omit all three to scope from the current page URL + +When `--url` is omitted, `--domain` and `--path` must be provided together. + ## Network ```bash diff --git a/skills/agent-browser/SKILL.md b/skills/agent-browser/SKILL.md index c2d5dd9..a7a341a 100644 --- a/skills/agent-browser/SKILL.md +++ b/skills/agent-browser/SKILL.md @@ -137,6 +137,20 @@ agent-browser state load auth.json agent-browser open https://app.example.com/dashboard ``` +### Cookie Injection for Auth Callbacks + +```bash +# Before navigation: set by URL +agent-browser cookies set session_id "abc123" --url https://app.example.com/api/auth/sso/callback + +# Explicit domain/path pair (must be provided together) +agent-browser cookies set auth_token "xyz789" --domain .example.com --path /api + +# Or navigate first and rely on current URL +agent-browser open https://app.example.com/api/auth/sso/callback +agent-browser cookies set callback_token "token123" +``` + ### Session Persistence ```bash diff --git a/src/actions.ts b/src/actions.ts index 9860ef8..4c11d40 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -1378,9 +1378,20 @@ async function handleCookiesSet( ): Promise { const page = browser.getPage(); const context = page.context(); - // Auto-fill URL for cookies that don't have domain/path/url set + // Playwright requires either `url` or a complete `domain` + `path` pair. + // If none are provided, we default to the current page URL. const pageUrl = page.url(); const cookies = command.cookies.map((cookie) => { + const hasUrl = Boolean(cookie.url); + const hasDomain = Boolean(cookie.domain); + const hasPath = Boolean(cookie.path); + + if (!hasUrl && hasDomain !== hasPath) { + throw new Error( + `Invalid cookie "${cookie.name}": provide either url, or both domain and path` + ); + } + if (!cookie.url && !cookie.domain && !cookie.path) { return { ...cookie, url: pageUrl }; }