Skip to main content

agent_first_http/cli/cmd/
cdp.rs

1//! `afhttp cdp` subcommand. Raw CDP method invocation.
2
3use clap::Args as ClapArgs;
4
5use crate::cli::output;
6use crate::sdk::Client;
7use crate::shared::error::{Error, ErrorCode};
8use crate::shared::ids::TabId;
9use crate::shared::time::parse_duration;
10
11#[derive(ClapArgs, Debug)]
12pub struct Args {
13    /// CDP method name (e.g. Runtime.evaluate).
14    pub method: String,
15    /// CDP endpoint of the running host.
16    #[arg(long = "endpoint-url")]
17    pub endpoint: String,
18    /// Bearer token, if the host was started with `--token-secret`.
19    #[arg(long = "token-secret")]
20    pub token: Option<String>,
21    /// CDP target id to drive.
22    #[arg(long)]
23    pub tab: String,
24    /// JSON literal, or `@-` to read from stdin.
25    #[arg(long)]
26    pub params: Option<String>,
27    /// "<event>:<timeout>" — wait for a CDP event before exiting.
28    #[arg(long)]
29    pub wait: Option<String>,
30}
31
32pub async fn run(args: Args) -> Result<(), Error> {
33    let mut client = Client::connect(&args.endpoint)?;
34    if let Some(t) = args.token.as_deref() {
35        client = client.with_token(t);
36    }
37    let params = if let Some(raw) = args.params {
38        if raw == "@-" {
39            use std::io::Read;
40            let mut buf = String::new();
41            std::io::stdin()
42                .read_to_string(&mut buf)
43                .map_err(|e| Error::new(ErrorCode::IoError, format!("read stdin: {e}")))?;
44            serde_json::from_str(&buf).map_err(|e| {
45                Error::new(
46                    ErrorCode::InvalidArgument,
47                    format!("--params @-: invalid JSON: {e}"),
48                )
49            })?
50        } else {
51            serde_json::from_str(&raw).map_err(|e| {
52                Error::new(
53                    ErrorCode::InvalidArgument,
54                    format!("--params: invalid JSON: {e}"),
55                )
56            })?
57        }
58    } else {
59        serde_json::Value::Object(Default::default())
60    };
61    let mut req = client
62        .cdp(args.method)
63        .tab(TabId::new(args.tab))
64        .params(params);
65    if let Some(spec) = args.wait {
66        let (ev, timeout) = spec.rsplit_once(':').ok_or_else(|| {
67            Error::new(
68                ErrorCode::InvalidArgument,
69                "--wait: expected <event>:<timeout>",
70            )
71        })?;
72        let d = parse_duration(timeout)?;
73        req = req.wait_for(ev, d);
74    }
75    let value = req.send().await?;
76    output::emit("cdp", &value)
77}