Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 46 additions & 6 deletions libs/cua-driver-rs/crates/cua-driver/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,34 @@ pub fn parse_command() -> Command {
}
Some("call") => {
let tool = pos.next().unwrap_or("").to_string();
let json_args = pos.next()
.and_then(|s| serde_json::from_str(s).ok())
.or_else(|| read_stdin_json());
// Differentiate "no positional arg" (fall back to stdin) from
// "positional arg given but didn't parse as JSON" (surface the
// error instead of silently falling back to stdin and letting
// the tool's required-field validator emit a misleading
// "missing field X" later). See #1637.
//
// The common cause of an unparseable positional arg is
// PowerShell 5.1's native-command-arg quote-stripping on
// multi-field JSON — `'{"a":1,"b":2}'` arrives as `{a:1,b:2}`
// which serde_json rejects. The error message points users at
// the stdin-pipe workaround.
let json_args = match pos.next() {
Some(s) => match serde_json::from_str(s) {
Ok(v) => Some(v),
Err(e) => {
eprintln!("error: positional JSON arg to 'cua-driver call' did not parse: {e}");
eprintln!(" received: {s}");
eprintln!();
eprintln!("hint: PowerShell 5.1 strips quotes around JSON field names in");
eprintln!(" multi-field args. Pipe the JSON via stdin instead:");
eprintln!(" '{{\"pid\":1234,\"window_id\":5678}}' | cua-driver call {}", tool);
eprintln!();
eprintln!(" Or use PowerShell 7+ (pwsh) which preserves the quotes.");
process::exit(2);
}
},
None => read_stdin_json(),
};
Command::Call { tool, json_args, screenshot_out_file }
}
Some("telemetry") => {
Expand Down Expand Up @@ -251,10 +276,25 @@ pub fn parse_command() -> Command {
}
Some(first) => {
// Implicit call: unrecognised first positional → treat as tool name.
// Same parse-error handling as the explicit `call` branch above. See #1637.
let tool = first.to_string();
let json_args = pos.next()
.and_then(|s| serde_json::from_str(s).ok())
.or_else(|| read_stdin_json());
let json_args = match pos.next() {
Some(s) => match serde_json::from_str(s) {
Ok(v) => Some(v),
Err(e) => {
eprintln!("error: positional JSON arg to 'cua-driver {tool}' did not parse: {e}");
eprintln!(" received: {s}");
eprintln!();
eprintln!("hint: PowerShell 5.1 strips quotes around JSON field names in");
eprintln!(" multi-field args. Pipe the JSON via stdin instead:");
eprintln!(" '{{\"pid\":1234,\"window_id\":5678}}' | cua-driver {}", tool);
eprintln!();
eprintln!(" Or use PowerShell 7+ (pwsh) which preserves the quotes.");
process::exit(2);
}
},
None => read_stdin_json(),
};
Command::Call { tool, json_args, screenshot_out_file }
}
}
Expand Down
11 changes: 9 additions & 2 deletions libs/cua-driver-rs/crates/platform-windows/src/tools/impl_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -843,8 +843,15 @@ impl Tool for LaunchAppTool {
}

if target.is_none() && urls.is_empty() {
// Match Swift's wording verbatim.
return ToolResult::error("Provide either bundle_id or name to identify the app to launch.");
// Error message lists every field the resolver actually accepts.
// The Swift-original "bundle_id or name" message predated the Windows
// additions (aumid, path, launch_path, urls) and made #1635 look like
// an aumid-specific bug. The actual cause of #1635 was the upstream
// PS argv quote-stripping bug fixed in #1637; this message just stops
// misleading anyone who hits the error for unrelated reasons.
return ToolResult::error(
"Provide one of: bundle_id, name, aumid, path, launch_path, or urls to identify the app to launch.",
);
}

// ── Packaged-app (UWP / MSIX) routing decision ──────────────────────
Expand Down
Loading