Skip to main content

systemprompt_cli/commands/core/contexts/
delete.rs

1//! `core contexts delete` command.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use anyhow::{Context, Result, bail};
7use clap::Args;
8use systemprompt_agent::repository::context::ContextRepository;
9use systemprompt_logging::CliService;
10
11use super::resolve::resolve_context;
12use super::types::ContextDeletedOutput;
13use crate::context::CommandContext;
14use crate::session::get_or_create_session;
15use crate::shared::CommandOutput;
16
17#[derive(Debug, Args)]
18pub struct DeleteArgs {
19    #[arg(help = "Context ID (full, partial prefix, or name)")]
20    pub context: String,
21
22    #[arg(short = 'y', long, help = "Skip confirmation prompt")]
23    pub yes: bool,
24}
25
26pub(super) async fn execute(args: DeleteArgs, ctx: &CommandContext) -> Result<CommandOutput> {
27    let session_ctx = get_or_create_session(ctx).await?;
28    let pool = ctx.db_pool().await?;
29    execute_with_pool(args, &session_ctx.session, &pool, &ctx.cli, ctx.prompter()).await
30}
31
32pub async fn execute_with_pool(
33    args: DeleteArgs,
34    session: &systemprompt_cloud::CliSession,
35    pool: &systemprompt_database::DbPool,
36    config: &crate::cli_settings::CliConfig,
37    prompter: &dyn crate::interactive::Prompter,
38) -> Result<CommandOutput> {
39    let repo = ContextRepository::new(pool);
40
41    let context_id = resolve_context(&args.context, &session.user_id, &repo).await?;
42
43    if context_id == session.context_id {
44        bail!(
45            "Cannot delete the active context. Switch to a different context first with 'contexts \
46             use <id>'."
47        );
48    }
49
50    let context = repo
51        .get_context(&context_id, &session.user_id)
52        .await
53        .context("Failed to fetch context details")?;
54
55    if !args.yes && !config.is_interactive() {
56        bail!("--yes is required in non-interactive mode");
57    }
58
59    if !args.yes {
60        CliService::warning(&format!(
61            "You are about to delete context '{}' ({})",
62            context.name,
63            context_id.as_str()
64        ));
65
66        if !prompter.confirm("Are you sure?", false)? {
67            CliService::info("Deletion cancelled");
68            let cancelled = ContextDeletedOutput {
69                id: context_id,
70                message: "Deletion cancelled".to_owned(),
71            };
72            return Ok(CommandOutput::card_value(
73                "Context Delete Cancelled",
74                &cancelled,
75            ));
76        }
77    }
78
79    repo.delete_context(&context_id, &session.user_id)
80        .await
81        .context("Failed to delete context")?;
82
83    let output = ContextDeletedOutput {
84        id: context_id.clone(),
85        message: format!("Context '{}' deleted successfully", context.name),
86    };
87
88    if !config.is_json_output() {
89        CliService::success(&output.message);
90    }
91
92    Ok(CommandOutput::card_value("Context Deleted", &output))
93}