systemprompt_cli/commands/core/artifacts/
list.rs1use anyhow::{Context, Result};
7use clap::Args;
8use systemprompt_agent::repository::content::artifact::ArtifactRepository;
9use systemprompt_database::DbPool;
10use systemprompt_identifiers::ContextId;
11use systemprompt_logging::CliService;
12
13use super::types::{ArtifactListOutput, ArtifactSummary};
14use crate::cli_settings::CliConfig;
15use crate::context::CommandContext;
16use crate::presentation::tables::artifact_list_table;
17use crate::session::get_or_create_session;
18use crate::shared::CommandOutput;
19
20#[derive(Debug, Args)]
21pub struct ListArgs {
22 #[arg(long = "context-id", short = 'c', help = "Filter by context ID")]
23 pub context: Option<String>,
24
25 #[arg(
26 long,
27 short = 'l',
28 default_value = "20",
29 help = "Maximum artifacts to show"
30 )]
31 pub limit: i32,
32}
33
34pub(super) async fn execute(args: ListArgs, ctx: &CommandContext) -> Result<CommandOutput> {
35 let session_ctx = get_or_create_session(ctx).await?;
36 let pool = ctx.db_pool().await?;
37 execute_with_pool(args, &session_ctx.session.user_id, &pool, &ctx.cli).await
38}
39
40pub async fn execute_with_pool(
41 args: ListArgs,
42 user_id: &systemprompt_identifiers::UserId,
43 pool: &DbPool,
44 config: &CliConfig,
45) -> Result<CommandOutput> {
46 let repo = ArtifactRepository::new(pool)?;
47
48 let artifacts = if let Some(ref ctx_id) = args.context {
49 let context_id = ContextId::new(ctx_id);
50 repo.get_artifacts_by_context(&context_id)
51 .await
52 .context("Failed to fetch artifacts by context")?
53 } else {
54 repo.get_artifacts_by_user_id(user_id, Some(args.limit))
55 .await
56 .context("Failed to fetch artifacts")?
57 };
58
59 let summaries: Vec<ArtifactSummary> = artifacts
60 .iter()
61 .take(args.limit as usize)
62 .map(|a| ArtifactSummary {
63 artifact_id: a.id.clone(),
64 name: a.title.clone(),
65 artifact_type: a.metadata.artifact_type.clone(),
66 tool_name: a.metadata.tool_name.clone(),
67 task_id: a.metadata.task_id.clone(),
68 created_at: chrono::DateTime::parse_from_rfc3339(&a.metadata.created_at)
69 .map_or_else(|_| chrono::Utc::now(), |dt| dt.with_timezone(&chrono::Utc)),
70 })
71 .collect();
72
73 let total = summaries.len();
74
75 let output = ArtifactListOutput {
76 artifacts: summaries.clone(),
77 total,
78 context: args.context.clone(),
79 };
80
81 if !config.is_json_output() {
82 CliService::section("Artifacts");
83
84 if summaries.is_empty() {
85 CliService::info("No artifacts found");
86 } else {
87 CliService::output(&artifact_list_table(&summaries));
88
89 CliService::info(&format!("Showing {} artifact(s)", total));
90 }
91 }
92
93 Ok(CommandOutput::table_of(
94 vec!["id", "name", "artifact_type", "tool_name", "created_at"],
95 &output.artifacts,
96 )
97 .with_title("Artifacts"))
98}