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)]
17#[command(disable_help_subcommand = true)]
18pub enum TabsSub {
19 List(EndpointArgs),
21 Close(CloseArgs),
23}
24
25#[derive(ClapArgs, Debug)]
26pub struct EndpointArgs {
27 #[arg(long = "endpoint-url", env = "AFHTTP_ENDPOINT_URL")]
30 pub endpoint: String,
31 #[arg(long = "token-secret", env = "AFHTTP_TOKEN_SECRET")]
34 pub token: Option<String>,
35}
36
37#[derive(ClapArgs, Debug)]
38pub struct CloseArgs {
39 #[arg(long)]
41 pub tab: String,
42 #[arg(long = "endpoint-url", env = "AFHTTP_ENDPOINT_URL")]
45 pub endpoint: String,
46 #[arg(long = "token-secret", env = "AFHTTP_TOKEN_SECRET")]
49 pub token: Option<String>,
50}
51
52pub async fn run(args: Args) -> Result<(), Error> {
53 match args.sub {
54 TabsSub::List(a) => list(a).await,
55 TabsSub::Close(a) => close(a).await,
56 }
57}
58
59fn build_client(endpoint: &str, token: Option<String>) -> Result<Client, Error> {
60 let mut client = Client::connect(endpoint)?;
61 if let Some(t) = token {
62 client = client.with_token(t);
63 }
64 Ok(client)
65}
66
67async fn list(args: EndpointArgs) -> Result<(), Error> {
68 let client = build_client(&args.endpoint, args.token)?;
69 let response = client.cdp("Target.getTargets").send().await?;
70 let targets = response
74 .get("targetInfos")
75 .cloned()
76 .unwrap_or(Value::Array(Vec::new()));
77 let payload = serde_json::json!({
78 "code": "tabs",
79 "targets": targets,
80 });
81 output::emit("tabs", &payload)
82}
83
84async fn close(args: CloseArgs) -> Result<(), Error> {
85 if args.tab.trim().is_empty() {
86 return Err(Error::new(
87 ErrorCode::InvalidArgument,
88 "tabs close: target id must not be empty",
89 ));
90 }
91 let client = build_client(&args.endpoint, args.token)?;
92 let response = client
93 .cdp("Target.closeTarget")
94 .params(serde_json::json!({ "targetId": args.tab }))
95 .send()
96 .await?;
97 let success = response
98 .get("success")
99 .and_then(Value::as_bool)
100 .unwrap_or(false);
101 let payload = serde_json::json!({
102 "code": "tab_closed",
103 "target_id": args.tab,
104 "success": success,
105 });
106 output::emit("tab_closed", &payload)
107}