Skip to main content

systemprompt_cli/commands/core/files/
mod.rs

1//! `core files` command group: manage stored file uploads.
2//!
3//! Dispatches the [`FilesCommands`] subcommands — list/show/search/stats,
4//! upload/delete, validate/config, and the `ai` sub-group. The reduced
5//! [`execute_with_db`] path serves the read-only commands that need only a
6//! [`DatabaseContext`]; upload, delete, validate, config, and ai require a full
7//! profile context.
8
9pub mod types;
10
11mod config;
12pub(crate) mod delete;
13mod list;
14mod search;
15mod show;
16mod stats;
17pub mod upload;
18mod validate;
19
20pub mod ai;
21
22use anyhow::{Context, Result, bail};
23use clap::Subcommand;
24use systemprompt_runtime::DatabaseContext;
25
26use crate::CliConfig;
27use crate::shared::render_result;
28
29#[derive(Debug, Subcommand)]
30pub enum FilesCommands {
31    #[command(about = "List files with pagination and filtering")]
32    List(list::ListArgs),
33
34    #[command(about = "Show detailed file information")]
35    Show(show::ShowArgs),
36
37    #[command(about = "Upload a file from the local filesystem")]
38    Upload(upload::UploadArgs),
39
40    #[command(about = "Delete a file")]
41    Delete(delete::DeleteArgs),
42
43    #[command(about = "Validate a file before upload")]
44    Validate(validate::ValidateArgs),
45
46    #[command(about = "Show file upload configuration")]
47    Config(config::ConfigArgs),
48
49    #[command(about = "Search files by path pattern")]
50    Search(search::SearchArgs),
51
52    #[command(about = "Show file storage statistics")]
53    Stats(stats::StatsArgs),
54
55    #[command(subcommand, about = "AI-generated images operations")]
56    Ai(ai::AiCommands),
57}
58
59pub async fn execute(cmd: FilesCommands, config: &CliConfig) -> Result<()> {
60    execute_with_config(cmd, config).await
61}
62
63pub async fn execute_with_config(cmd: FilesCommands, config: &CliConfig) -> Result<()> {
64    match cmd {
65        FilesCommands::List(args) => {
66            let result = list::execute(args, config)
67                .await
68                .context("Failed to list files")?;
69            render_result(&result);
70            Ok(())
71        },
72        FilesCommands::Show(args) => {
73            let result = show::execute(args, config)
74                .await
75                .context("Failed to show file")?;
76            render_result(&result);
77            Ok(())
78        },
79        FilesCommands::Upload(args) => {
80            let result = upload::execute(args, config)
81                .await
82                .context("Failed to upload file")?;
83            render_result(&result);
84            Ok(())
85        },
86        FilesCommands::Delete(args) => {
87            let result = delete::execute(args, config)
88                .await
89                .context("Failed to delete file")?;
90            render_result(&result);
91            Ok(())
92        },
93        FilesCommands::Validate(args) => {
94            let result = validate::execute(&args, config).context("Failed to validate file")?;
95            render_result(&result);
96            Ok(())
97        },
98        FilesCommands::Config(args) => {
99            let result = config::execute(args, config).context("Failed to get file config")?;
100            render_result(&result);
101            Ok(())
102        },
103        FilesCommands::Search(args) => {
104            let result = search::execute(args, config)
105                .await
106                .context("Failed to search files")?;
107            render_result(&result);
108            Ok(())
109        },
110        FilesCommands::Stats(args) => {
111            let result = stats::execute(args, config)
112                .await
113                .context("Failed to get file stats")?;
114            render_result(&result);
115            Ok(())
116        },
117        FilesCommands::Ai(cmd) => ai::execute(cmd, config).await,
118    }
119}
120
121pub async fn execute_with_db(
122    cmd: FilesCommands,
123    db_ctx: &DatabaseContext,
124    config: &CliConfig,
125) -> Result<()> {
126    match cmd {
127        FilesCommands::List(args) => {
128            let result = list::execute_with_pool(args, db_ctx.db_pool(), config)
129                .await
130                .context("Failed to list files")?;
131            render_result(&result);
132            Ok(())
133        },
134        FilesCommands::Show(args) => {
135            let result = show::execute_with_pool(args, db_ctx.db_pool(), config)
136                .await
137                .context("Failed to show file")?;
138            render_result(&result);
139            Ok(())
140        },
141        FilesCommands::Search(args) => {
142            let result = search::execute_with_pool(args, db_ctx.db_pool(), config)
143                .await
144                .context("Failed to search files")?;
145            render_result(&result);
146            Ok(())
147        },
148        FilesCommands::Stats(args) => {
149            let result = stats::execute_with_pool(args, db_ctx.db_pool(), config)
150                .await
151                .context("Failed to get file stats")?;
152            render_result(&result);
153            Ok(())
154        },
155        FilesCommands::Upload(_)
156        | FilesCommands::Delete(_)
157        | FilesCommands::Validate(_)
158        | FilesCommands::Config(_)
159        | FilesCommands::Ai(_) => {
160            bail!("This files command requires full profile context")
161        },
162    }
163}