agent_first_http/cli/cmd/
tabs.rs1use serde_json::Value;
4
5use crate::cli::output;
6use crate::sdk::Client;
7use crate::shared::error::{Error, ErrorCode};
8
9#[derive(Debug)]
10pub struct Args {
11 pub sub: TabsSub,
12}
13
14#[derive(Debug)]
15pub enum TabsSub {
16 List(EndpointArgs),
17 Close(CloseArgs),
18}
19
20#[derive(Debug)]
21pub struct EndpointArgs {
22 pub endpoint: String,
23 pub token: Option<String>,
24}
25
26#[derive(Debug)]
27pub struct CloseArgs {
28 pub tab: String,
29 pub endpoint: String,
30 pub token: Option<String>,
31}
32
33pub async fn run(args: Args) -> Result<(), Error> {
34 match args.sub {
35 TabsSub::List(a) => list(a).await,
36 TabsSub::Close(a) => close(a).await,
37 }
38}
39
40fn build_client(endpoint: &str, token: Option<String>) -> Result<Client, Error> {
41 let mut client = Client::connect(endpoint)?;
42 if let Some(t) = token {
43 client = client.with_token(t);
44 }
45 Ok(client)
46}
47
48async fn list(args: EndpointArgs) -> Result<(), Error> {
49 let client = build_client(&args.endpoint, args.token)?;
50 let response = client.cdp("Target.getTargets").send().await?;
51 let targets = response
55 .get("targetInfos")
56 .cloned()
57 .unwrap_or(Value::Array(Vec::new()));
58 let payload = serde_json::json!({
59 "code": "tabs",
60 "targets": targets,
61 });
62 output::emit("tabs", &payload)
63}
64
65async fn close(args: CloseArgs) -> Result<(), Error> {
66 if args.tab.trim().is_empty() {
67 return Err(Error::new(
68 ErrorCode::InvalidArgument,
69 "tabs close: target id must not be empty",
70 ));
71 }
72 let client = build_client(&args.endpoint, args.token)?;
73 let response = client
74 .cdp("Target.closeTarget")
75 .params(serde_json::json!({ "targetId": args.tab }))
76 .send()
77 .await?;
78 let success = response
79 .get("success")
80 .and_then(Value::as_bool)
81 .unwrap_or(false);
82 let payload = serde_json::json!({
83 "code": "tab_closed",
84 "target_id": args.tab,
85 "success": success,
86 });
87 output::emit("tab_closed", &payload)
88}