Skip to main content

systemprompt_cli/presentation/tables/
entities.rs

1//! Listing tables for stored artifacts, contexts, and database tables.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use systemprompt_identifiers::McpToolName;
7use tabled::{Table, Tabled};
8
9use crate::commands::core::artifacts::ArtifactSummary;
10use crate::commands::core::contexts::ContextSummary;
11use crate::commands::infrastructure::db::TableInfo;
12use crate::shared::truncate_with_ellipsis;
13
14use super::{OrDash, dash};
15
16#[derive(Tabled)]
17struct ArtifactListRow {
18    #[tabled(rename = "ID")]
19    id: String,
20    #[tabled(rename = "Name")]
21    name: String,
22    #[tabled(rename = "Type")]
23    artifact_type: String,
24    #[tabled(rename = "Tool")]
25    tool_name: OrDash<McpToolName>,
26    #[tabled(rename = "Created")]
27    created_at: String,
28}
29
30#[must_use]
31pub fn artifact_list_table(artifacts: &[ArtifactSummary]) -> String {
32    let rows: Vec<ArtifactListRow> = artifacts
33        .iter()
34        .map(|a| ArtifactListRow {
35            id: truncate_with_ellipsis(a.artifact_id.as_str(), 12),
36            name: a.name.clone().unwrap_or_else(dash),
37            artifact_type: a.artifact_type.clone(),
38            tool_name: OrDash(a.tool_name.clone().map(McpToolName::new)),
39            created_at: a.created_at.format("%Y-%m-%d %H:%M").to_string(),
40        })
41        .collect();
42    Table::new(rows).to_string()
43}
44
45#[derive(Tabled)]
46struct ContextListRow {
47    #[tabled(rename = "ID")]
48    id: String,
49    #[tabled(rename = "Name")]
50    name: String,
51    #[tabled(rename = "Tasks")]
52    task_count: i64,
53    #[tabled(rename = "Messages")]
54    message_count: i64,
55    #[tabled(rename = "Updated")]
56    updated_at: String,
57    #[tabled(rename = "Active")]
58    active: String,
59}
60
61#[must_use]
62pub fn context_list_table(contexts: &[ContextSummary]) -> String {
63    let rows: Vec<ContextListRow> = contexts
64        .iter()
65        .map(|c| ContextListRow {
66            id: c.id.as_str().chars().take(8).collect(),
67            name: truncate_with_ellipsis(&c.name, 40),
68            task_count: c.task_count,
69            message_count: c.message_count,
70            updated_at: c.updated_at.format("%Y-%m-%d %H:%M").to_string(),
71            active: if c.is_active {
72                "*".to_owned()
73            } else {
74                String::new()
75            },
76        })
77        .collect();
78    Table::new(rows).to_string()
79}
80
81#[derive(Tabled)]
82struct DbTableRow {
83    #[tabled(rename = "Table")]
84    name: String,
85    #[tabled(rename = "Rows (est.)")]
86    row_count: i64,
87    #[tabled(rename = "Size")]
88    size: String,
89}
90
91#[must_use]
92pub fn db_tables_table(tables: &[TableInfo]) -> String {
93    let rows: Vec<DbTableRow> = tables
94        .iter()
95        .map(|t| DbTableRow {
96            name: t.name.clone(),
97            row_count: t.row_count,
98            size: crate::commands::infrastructure::db::format_bytes(t.size_bytes),
99        })
100        .collect();
101    Table::new(rows).to_string()
102}