systemprompt-cli 0.10.2

Unified CLI for systemprompt.io AI governance: agent orchestration, MCP governance, analytics, profiles, cloud deploy, and self-hosted operations.
Documentation
use anyhow::{Context, Result, anyhow};
use std::sync::Arc;
use systemprompt_database::services::DatabaseProvider;
use systemprompt_database::{Database, MigrationService};
use systemprompt_extension::ExtensionRegistry;
use systemprompt_logging::CliService;
use systemprompt_models::Config;
use systemprompt_runtime::DatabaseContext;

use crate::cli_settings::CliConfig;
use crate::shared::{CommandResult, render_result};

use super::types::DbMigrateDownOutput;

pub async fn execute_migrate_down(config: &CliConfig, extension: &str, count: u32) -> Result<()> {
    let sys_config = Config::get()?;

    let database = Arc::new(
        Database::from_config_with_write(
            &sys_config.database_type,
            &sys_config.database_url,
            sys_config.database_write_url.as_deref(),
        )
        .await
        .context("Failed to connect to database")?,
    );

    run_down(
        &ExtensionRegistry::discover()?,
        database.write_provider(),
        config,
        extension,
        count,
    )
    .await
}

pub async fn execute_migrate_down_standalone(
    db_ctx: &DatabaseContext,
    config: &CliConfig,
    extension: &str,
    count: u32,
) -> Result<()> {
    let database = db_ctx.db_pool();
    run_down(
        &ExtensionRegistry::discover()?,
        database.write_provider(),
        config,
        extension,
        count,
    )
    .await
}

async fn run_down(
    registry: &ExtensionRegistry,
    write_provider: &dyn DatabaseProvider,
    config: &CliConfig,
    extension_id: &str,
    count: u32,
) -> Result<()> {
    let ext = registry
        .get(extension_id)
        .ok_or_else(|| anyhow!("Extension '{}' not found", extension_id))?;

    let migration_service = MigrationService::new(write_provider);
    let result = migration_service
        .run_down_migrations(ext.as_ref(), count)
        .await
        .map_err(|e| anyhow!("Down migration failed: {}", e))?;

    let output = DbMigrateDownOutput {
        extension: extension_id.to_string(),
        migrations_reverted: result.migrations_run,
        message: format!(
            "Reverted {} migration(s) for '{}'",
            result.migrations_run, extension_id
        ),
    };

    if config.is_json_output() {
        let result = CommandResult::text(output).with_title("Database Admin");
        render_result(&result);
    } else {
        CliService::success(&output.message);
    }

    Ok(())
}