Skip to main content

systemprompt_cli/commands/core/content/
mod.rs

1//! `core content` command group: manage and inspect published content.
2//!
3//! Dispatches the [`ContentCommands`] subcommands — list/show/search,
4//! edit/delete, ingest verification and status, plus the `link`, `analytics`,
5//! and `files` sub-groups. The reduced [`execute_with_db`] path serves the
6//! read-only commands that can run with only a [`DatabaseContext`]; the
7//! mutating commands require a full profile context.
8
9pub mod analytics;
10pub mod delete;
11pub mod delete_source;
12mod edit;
13mod edit_apply;
14pub mod files;
15pub mod link;
16pub mod list;
17pub mod popular;
18pub mod search;
19pub mod show;
20pub mod status;
21pub mod types;
22pub mod verify;
23
24use crate::cli_settings::{CliConfig, get_global_config};
25use crate::shared::render_result;
26use anyhow::{Context, Result, bail};
27use clap::Subcommand;
28use systemprompt_runtime::DatabaseContext;
29
30#[derive(Debug, Subcommand)]
31pub enum ContentCommands {
32    #[command(about = "List content with pagination")]
33    List(list::ListArgs),
34
35    #[command(about = "Show content details")]
36    Show(show::ShowArgs),
37
38    #[command(about = "Search content")]
39    Search(search::SearchArgs),
40
41    #[command(about = "Edit content fields")]
42    Edit(edit::EditArgs),
43
44    #[command(about = "Delete content by ID")]
45    Delete(delete::DeleteArgs),
46
47    #[command(name = "delete-source", about = "Delete all content from a source")]
48    DeleteSource(delete_source::DeleteSourceArgs),
49
50    #[command(about = "Get popular content")]
51    Popular(popular::PopularArgs),
52
53    #[command(about = "Verify content is published and accessible")]
54    Verify(verify::VerifyArgs),
55
56    #[command(about = "Show content health status for a source")]
57    Status(status::StatusArgs),
58
59    #[command(subcommand, about = "Link generation and management")]
60    Link(link::LinkCommands),
61
62    #[command(subcommand, about = "Content analytics")]
63    Analytics(analytics::AnalyticsCommands),
64
65    #[command(subcommand, about = "Content-file operations (link, unlink, featured)")]
66    Files(files::ContentFilesCommands),
67}
68
69pub async fn execute(command: ContentCommands) -> Result<()> {
70    let config = get_global_config();
71    execute_with_config(command, &config).await
72}
73
74pub async fn execute_with_config(command: ContentCommands, config: &CliConfig) -> Result<()> {
75    match command {
76        ContentCommands::List(args) => {
77            let result = list::execute(args, config)
78                .await
79                .context("Failed to list content")?;
80            render_result(&result);
81        },
82        ContentCommands::Show(args) => {
83            let result = show::execute(args, config)
84                .await
85                .context("Failed to show content")?;
86            render_result(&result);
87        },
88        ContentCommands::Search(args) => {
89            let result = search::execute(args, config)
90                .await
91                .context("Failed to search content")?;
92            render_result(&result);
93        },
94        ContentCommands::Edit(args) => {
95            let result = edit::execute(args, config)
96                .await
97                .context("Failed to edit content")?;
98            render_result(&result);
99        },
100        ContentCommands::Delete(args) => {
101            let result = delete::execute(args, config)
102                .await
103                .context("Failed to delete content")?;
104            render_result(&result);
105        },
106        ContentCommands::DeleteSource(args) => {
107            let result = delete_source::execute(args, config)
108                .await
109                .context("Failed to delete source content")?;
110            render_result(&result);
111        },
112        ContentCommands::Popular(args) => {
113            let result = popular::execute(args, config)
114                .await
115                .context("Failed to get popular content")?;
116            render_result(&result);
117        },
118        ContentCommands::Verify(args) => {
119            let result = verify::execute(args, config)
120                .await
121                .context("Failed to verify content")?;
122            render_result(&result);
123        },
124        ContentCommands::Status(args) => {
125            let result = status::execute(args, config)
126                .await
127                .context("Failed to get content status")?;
128            render_result(&result);
129        },
130        ContentCommands::Link(cmd) => {
131            link::execute(cmd, config).await?;
132        },
133        ContentCommands::Analytics(cmd) => {
134            analytics::execute(cmd, config).await?;
135        },
136        ContentCommands::Files(cmd) => {
137            files::execute(cmd, config).await?;
138        },
139    }
140    Ok(())
141}
142
143pub async fn execute_with_db(
144    command: ContentCommands,
145    db_ctx: &DatabaseContext,
146    config: &CliConfig,
147) -> Result<()> {
148    match command {
149        ContentCommands::List(args) => {
150            let result = list::execute_with_pool(args, db_ctx.db_pool(), config)
151                .await
152                .context("Failed to list content")?;
153            render_result(&result);
154        },
155        ContentCommands::Show(args) => {
156            let result = show::execute_with_pool(args, db_ctx.db_pool(), config)
157                .await
158                .context("Failed to show content")?;
159            render_result(&result);
160        },
161        ContentCommands::Search(args) => {
162            let result = search::execute_with_pool(args, db_ctx.db_pool(), config)
163                .await
164                .context("Failed to search content")?;
165            render_result(&result);
166        },
167        ContentCommands::Popular(args) => {
168            let result = popular::execute_with_pool(args, db_ctx.db_pool(), config)
169                .await
170                .context("Failed to get popular content")?;
171            render_result(&result);
172        },
173        ContentCommands::Status(args) => {
174            let result = status::execute_with_pool(args, db_ctx.db_pool(), config)
175                .await
176                .context("Failed to get content status")?;
177            render_result(&result);
178        },
179        ContentCommands::Analytics(cmd) => {
180            analytics::execute_with_pool(cmd, db_ctx.db_pool(), config).await?;
181        },
182        ContentCommands::Edit(_)
183        | ContentCommands::Delete(_)
184        | ContentCommands::DeleteSource(_)
185        | ContentCommands::Verify(_)
186        | ContentCommands::Link(_)
187        | ContentCommands::Files(_) => {
188            bail!("This content command requires full profile context")
189        },
190    }
191    Ok(())
192}