systemprompt_cli/commands/core/files/ai/
show.rs1use anyhow::{Result, anyhow};
7use clap::Args;
8use systemprompt_database::DbPool;
9use systemprompt_files::{FileRepository, TypeSpecificMetadata};
10use systemprompt_identifiers::FileId;
11use systemprompt_runtime::AppContext;
12
13use crate::CliConfig;
14use crate::commands::core::files::types::{
15 ChecksumsOutput, FileDetailOutput, FileMetadataOutput, ImageMetadataOutput,
16};
17use crate::shared::CommandOutput;
18
19#[derive(Debug, Clone, Args)]
20pub struct ShowArgs {
21 #[arg(value_name = "FILE_ID", help = "AI image file ID (UUID format)")]
22 pub file: String,
23}
24
25pub(super) async fn execute(args: ShowArgs, config: &CliConfig) -> Result<CommandOutput> {
26 let ctx = AppContext::new().await?;
27 execute_with_pool(args, ctx.db_pool(), config).await
28}
29
30pub async fn execute_with_pool(
31 args: ShowArgs,
32 pool: &DbPool,
33 _config: &CliConfig,
34) -> Result<CommandOutput> {
35 let file_id = parse_file_id(&args.file)?;
36
37 let service = FileRepository::new(pool)?;
38
39 let file = service
40 .find_by_id(&file_id)
41 .await?
42 .ok_or_else(|| anyhow!("File not found: {}", args.file))?;
43
44 if !file.ai_content {
45 return Err(anyhow!(
46 "File '{}' is not an AI-generated image. Use 'files show' for regular files.",
47 args.file
48 ));
49 }
50
51 let metadata_output = convert_metadata(&file);
52
53 let output = FileDetailOutput {
54 id: file.id(),
55 path: file.path,
56 public_url: file.public_url,
57 mime_type: file.mime_type,
58 size_bytes: file.size_bytes,
59 ai_content: file.ai_content,
60 user_id: file.user_id,
61 session_id: file.session_id,
62 trace_id: file.trace_id,
63 context_id: file.context_id,
64 metadata: metadata_output,
65 created_at: file.created_at,
66 updated_at: file.updated_at,
67 };
68
69 Ok(CommandOutput::card_value(
70 format!("AI Image: {}", args.file),
71 &output,
72 ))
73}
74
75fn parse_file_id(id: &str) -> Result<FileId> {
76 uuid::Uuid::parse_str(id).map_err(|_e| {
77 anyhow!(
78 "Invalid file ID format. Expected UUID like 'b75940ac-c50f-4d46-9fdd-ebb4970b2a7d', \
79 got '{}'",
80 id
81 )
82 })?;
83 Ok(FileId::new(id.to_owned()))
84}
85
86fn convert_metadata(file: &systemprompt_files::File) -> FileMetadataOutput {
87 let metadata = file.metadata.0.clone();
88
89 let checksums = metadata.checksums.map(|c| ChecksumsOutput {
90 md5: c.md5,
91 sha256: c.sha256,
92 });
93
94 let image = match metadata.type_specific {
95 Some(TypeSpecificMetadata::Image(img)) => Some(ImageMetadataOutput {
96 width: img.width,
97 height: img.height,
98 alt_text: img.alt_text,
99 description: img.description,
100 }),
101 _ => None,
102 };
103
104 FileMetadataOutput {
105 checksums,
106 image,
107 document: None,
108 audio: None,
109 video: None,
110 }
111}