systemprompt-cli 0.1.22

systemprompt.io OS - CLI for agent orchestration, AI operations, and system management
Documentation
use super::types::ContentDetailOutput;
use crate::cli_settings::CliConfig;
use crate::shared::CommandResult;
use anyhow::{Result, anyhow};
use clap::Args;
use systemprompt_content::ContentRepository;
use systemprompt_database::DbPool;
use systemprompt_identifiers::{ContentId, SourceId};
use systemprompt_runtime::AppContext;

#[derive(Debug, Args)]
pub struct ShowArgs {
    #[arg(help = "Content ID or slug")]
    pub identifier: String,

    #[arg(long, help = "Source ID (required when using slug)")]
    pub source: Option<String>,
}

pub async fn execute(
    args: ShowArgs,
    config: &CliConfig,
) -> Result<CommandResult<ContentDetailOutput>> {
    let ctx = AppContext::new().await?;
    execute_with_pool(args, ctx.db_pool(), config).await
}

pub async fn execute_with_pool(
    args: ShowArgs,
    pool: &DbPool,
    _config: &CliConfig,
) -> Result<CommandResult<ContentDetailOutput>> {
    let repo = ContentRepository::new(pool)?;

    let content = if args.identifier.starts_with("content_")
        || args.identifier.contains('-') && args.identifier.len() > 30
    {
        let id = ContentId::new(args.identifier.clone());
        repo.get_by_id(&id)
            .await?
            .ok_or_else(|| anyhow!("Content not found: {}", args.identifier))?
    } else {
        let source_id = args
            .source
            .as_ref()
            .ok_or_else(|| anyhow!("Source ID required when using slug"))?;
        let source = SourceId::new(source_id.clone());
        repo.get_by_source_and_slug(&source, &args.identifier)
            .await?
            .ok_or_else(|| {
                anyhow!(
                    "Content not found: {} in source {}",
                    args.identifier,
                    source_id
                )
            })?
    };

    let keywords: Vec<String> = content
        .keywords
        .split(',')
        .map(|s| s.trim().to_string())
        .filter(|s| !s.is_empty())
        .collect();

    let output = ContentDetailOutput {
        id: content.id,
        slug: content.slug,
        title: content.title,
        description: if content.description.is_empty() {
            None
        } else {
            Some(content.description)
        },
        body: content.body,
        author: if content.author.is_empty() {
            None
        } else {
            Some(content.author)
        },
        published_at: Some(content.published_at),
        keywords,
        kind: content.kind,
        image: content.image,
        category_id: content.category_id,
        source_id: content.source_id,
        version_hash: content.version_hash,
        is_public: content.public,
        updated_at: content.updated_at,
    };

    Ok(CommandResult::card(output).with_title("Content Details"))
}