systemprompt_cli/commands/core/contexts/
new.rs1use anyhow::{Context, Result};
7use chrono::Utc;
8use clap::Args;
9use systemprompt_agent::models::context::ContextKind;
10use systemprompt_agent::repository::context::ContextRepository;
11use systemprompt_cloud::{SessionKey, SessionStore};
12use systemprompt_logging::CliService;
13
14use super::types::ContextSwitchedOutput;
15use crate::CliConfig;
16use crate::context::CommandContext;
17use crate::paths::ResolvedPaths;
18use crate::session::{CliSessionContext, get_or_create_session};
19use crate::shared::CommandOutput;
20use std::path::Path;
21use systemprompt_database::DbPool;
22
23#[derive(Debug, Args)]
24pub struct NewArgs {
25 #[arg(long, help = "Name for the new context")]
26 pub name: Option<String>,
27}
28
29pub(super) async fn execute(args: NewArgs, ctx: &CommandContext) -> Result<CommandOutput> {
30 let session_ctx = get_or_create_session(ctx).await?;
31 let pool = ctx.db_pool().await?;
32 let sessions_dir = ResolvedPaths::discover().sessions_dir();
33 execute_resolved(args, &ctx.cli, &session_ctx, &pool, &sessions_dir).await
34}
35
36pub async fn execute_resolved(
37 args: NewArgs,
38 cli: &CliConfig,
39 session_ctx: &CliSessionContext,
40 pool: &DbPool,
41 sessions_dir: &Path,
42) -> Result<CommandOutput> {
43 let repo = ContextRepository::new(pool)?;
44
45 let name = args
46 .name
47 .unwrap_or_else(|| format!("Context - {}", Utc::now().format("%Y-%m-%d %H:%M")));
48
49 let context_id = repo
50 .create_context(
51 &session_ctx.session.user_id,
52 Some(&session_ctx.session.session_id),
53 &name,
54 ContextKind::User,
55 )
56 .await
57 .context("Failed to create context")?;
58
59 let mut store = SessionStore::load_or_create(sessions_dir)?;
60
61 let session_key = SessionKey::from_tenant_id(
62 session_ctx
63 .profile
64 .cloud
65 .as_ref()
66 .and_then(|c| c.tenant_id.as_ref()),
67 );
68
69 let mut session = session_ctx.session.clone();
70 session.set_context_id(context_id.clone());
71 store.upsert_session(&session_key, session);
72 store.save(sessions_dir)?;
73
74 let output = ContextSwitchedOutput {
75 id: context_id.clone(),
76 name: name.clone(),
77 message: format!("Created and switched to context '{}'", name),
78 };
79
80 if !cli.is_json_output() {
81 CliService::success(&output.message);
82 CliService::key_value("ID", context_id.as_str());
83 CliService::key_value("Name", &name);
84 }
85
86 Ok(CommandOutput::card_value("New Context Created", &output))
87}