agent_first_http/cli/cmd/
profile.rs1use std::path::PathBuf;
4
5use clap::{Args as ClapArgs, Subcommand};
6
7use crate::cli::output;
8use crate::sdk::profile;
9use crate::shared::error::Error;
10use crate::shared::time::parse_duration;
11
12#[derive(ClapArgs, Debug)]
13pub struct Args {
14 #[command(subcommand)]
15 pub sub: ProfileSub,
16}
17
18#[derive(Subcommand, Debug)]
19pub enum ProfileSub {
20 List(ListArgs),
22 Info(InfoArgs),
24 LockStatus(InfoArgs),
26 Downloads(InfoArgs),
28 Delete(DeleteArgs),
30 Prune(PruneArgs),
32 Cookies(InfoArgs),
34}
35
36#[derive(ClapArgs, Debug)]
37pub struct ListArgs {
38 #[arg(long)]
40 pub profile_root: Option<PathBuf>,
41}
42
43#[derive(ClapArgs, Debug)]
44pub struct InfoArgs {
45 pub name: String,
47 #[arg(long)]
50 pub backend: Option<String>,
51 #[arg(long)]
53 pub profile_root: Option<PathBuf>,
54}
55
56#[derive(ClapArgs, Debug)]
57pub struct DeleteArgs {
58 pub name: String,
60 #[arg(long)]
63 pub backend: Option<String>,
64 #[arg(long)]
66 pub confirm: String,
67 #[arg(long)]
69 pub profile_root: Option<PathBuf>,
70}
71
72#[derive(ClapArgs, Debug)]
73pub struct PruneArgs {
74 #[arg(long)]
76 pub older_than: String,
77 #[arg(long, default_value_t = false)]
79 pub dry_run: bool,
80 #[arg(long)]
82 pub profile_root: Option<PathBuf>,
83}
84
85pub async fn run(args: Args) -> Result<(), Error> {
86 match args.sub {
87 ProfileSub::List(a) => {
88 let root = profile_root_for_output(a.profile_root.as_deref());
89 let entries = profile::list(a.profile_root.as_deref())?;
90 output::emit(
91 "profile_list",
92 &serde_json::json!({
93 "profile_root": root.display().to_string(),
94 "profiles": entries,
95 }),
96 )
97 }
98 ProfileSub::Info(a) => {
99 let entry = profile::info(&a.name, a.backend.as_deref(), a.profile_root.as_deref())?;
100 output::emit("profile_info", &entry)
101 }
102 ProfileSub::LockStatus(a) => {
103 let status =
104 profile::lock_status(&a.name, a.backend.as_deref(), a.profile_root.as_deref())?;
105 output::emit("profile_lock_status", &status)
106 }
107 ProfileSub::Downloads(a) => {
108 let entry = profile::info(&a.name, a.backend.as_deref(), a.profile_root.as_deref())?;
109 let download_dir = entry.path.join("downloads");
110 let download_dir = download_dir.canonicalize().unwrap_or(download_dir);
111 let downloads =
112 profile::downloads(&a.name, a.backend.as_deref(), a.profile_root.as_deref())?;
113 output::emit(
114 "profile_downloads",
115 &serde_json::json!({
116 "backend": entry.backend,
117 "name": a.name,
118 "download_dir": download_dir.display().to_string(),
119 "downloads": downloads,
120 }),
121 )
122 }
123 ProfileSub::Delete(a) => {
124 let entry = profile::info(&a.name, a.backend.as_deref(), a.profile_root.as_deref())?;
125 profile::delete(
126 &a.name,
127 &a.confirm,
128 a.backend.as_deref(),
129 a.profile_root.as_deref(),
130 )?;
131 output::emit(
132 "profile_delete",
133 &serde_json::json!({"backend": entry.backend, "name": a.name, "deleted": true}),
134 )
135 }
136 ProfileSub::Prune(a) => {
137 let root = profile_root_for_output(a.profile_root.as_deref());
138 let older_than = parse_duration(&a.older_than)?;
139 let removed = profile::prune(older_than, a.dry_run, a.profile_root.as_deref())?;
140 output::emit(
141 "profile_prune",
142 &serde_json::json!({
143 "profile_root": root.display().to_string(),
144 "dry_run": a.dry_run,
145 "profiles": removed,
146 }),
147 )
148 }
149 ProfileSub::Cookies(a) => {
150 let entry = profile::info(&a.name, a.backend.as_deref(), a.profile_root.as_deref())?;
151 let jar_path = entry.path.join("cookies.jar.json");
152 let jar = crate::sdk::profile::cookie_jar::CookieJar::load(&jar_path)?;
153 let cookies = jar.cookies_redacted();
154 output::emit(
155 "profile_cookies",
156 &serde_json::json!({
157 "backend": entry.backend,
158 "name": a.name,
159 "jar_path": jar_path.display().to_string(),
160 "count": cookies.len(),
161 "cookies": cookies,
162 }),
163 )
164 }
165 }
166}
167
168fn profile_root_for_output(root: Option<&std::path::Path>) -> PathBuf {
169 root.map(PathBuf::from)
170 .unwrap_or_else(profile::paths::default_root)
171}