agent_first_http/cli/cmd/
tabs.rs1use clap::{Args as ClapArgs, Subcommand};
4use serde_json::Value;
5
6use crate::cli::output;
7use crate::sdk::Client;
8use crate::shared::error::{Error, ErrorCode};
9
10#[derive(ClapArgs, Debug)]
11pub struct Args {
12 #[command(subcommand)]
13 pub sub: TabsSub,
14}
15
16#[derive(Subcommand, Debug)]
17pub enum TabsSub {
18 List(EndpointArgs),
20 Close(CloseArgs),
22}
23
24#[derive(ClapArgs, Debug)]
25pub struct EndpointArgs {
26 #[arg(long = "endpoint-url", env = "AFHTTP_ENDPOINT_URL")]
29 pub endpoint: String,
30 #[arg(long = "token-secret", env = "AFHTTP_TOKEN_SECRET")]
33 pub token: Option<String>,
34}
35
36#[derive(ClapArgs, Debug)]
37pub struct CloseArgs {
38 #[arg(long)]
40 pub tab: String,
41 #[arg(long = "endpoint-url", env = "AFHTTP_ENDPOINT_URL")]
44 pub endpoint: String,
45 #[arg(long = "token-secret", env = "AFHTTP_TOKEN_SECRET")]
48 pub token: Option<String>,
49}
50
51pub async fn run(args: Args) -> Result<(), Error> {
52 match args.sub {
53 TabsSub::List(a) => list(a).await,
54 TabsSub::Close(a) => close(a).await,
55 }
56}
57
58fn build_client(endpoint: &str, token: Option<String>) -> Result<Client, Error> {
59 let mut client = Client::connect(endpoint)?;
60 if let Some(t) = token {
61 client = client.with_token(t);
62 }
63 Ok(client)
64}
65
66async fn list(args: EndpointArgs) -> Result<(), Error> {
67 let client = build_client(&args.endpoint, args.token)?;
68 let response = client.cdp("Target.getTargets").send().await?;
69 let targets = response
73 .get("targetInfos")
74 .cloned()
75 .unwrap_or(Value::Array(Vec::new()));
76 let payload = serde_json::json!({
77 "code": "tabs",
78 "targets": targets,
79 });
80 output::emit("tabs", &payload)
81}
82
83async fn close(args: CloseArgs) -> Result<(), Error> {
84 if args.tab.trim().is_empty() {
85 return Err(Error::new(
86 ErrorCode::InvalidArgument,
87 "tabs close: target id must not be empty",
88 ));
89 }
90 let client = build_client(&args.endpoint, args.token)?;
91 let response = client
92 .cdp("Target.closeTarget")
93 .params(serde_json::json!({ "targetId": args.tab }))
94 .send()
95 .await?;
96 let success = response
97 .get("success")
98 .and_then(Value::as_bool)
99 .unwrap_or(false);
100 let payload = serde_json::json!({
101 "code": "tab_closed",
102 "target_id": args.tab,
103 "success": success,
104 });
105 output::emit("tab_closed", &payload)
106}