From 582f56e915a7c88eb0372496e298c9944f5832ae Mon Sep 17 00:00:00 2001 From: Patrick Jackson Date: Tue, 26 Mar 2024 17:00:28 -0600 Subject: feat: add `save_session` config item and `--save-session` cli option (#370) * fix: sessions should save when exiting * feat: improve save sessions * feat: do not allow saving the temp session name * feat: allow creating a session without interactive use * feat: add `save_session` config and `--save-session` option --------- Co-authored-by: sigoden --- src/cli.rs | 5 ++++- src/config/mod.rs | 35 ++++++++++++++++++++++++----------- src/main.rs | 8 +++++--- src/repl/mod.rs | 2 +- 4 files changed, 34 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/cli.rs b/src/cli.rs index 5f35df4..344e2a6 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -12,13 +12,16 @@ pub struct Cli { /// Create or reuse a session #[clap(short = 's', long)] pub session: Option>, + /// Whether to save the session automatically + #[clap(long)] + pub save_session: bool, /// Execute commands using natural language #[clap(short = 'e', long)] pub execute: bool, /// Generate only code #[clap(short = 'c', long)] pub code: bool, - /// Attach files to the message to be sent. + /// Attach files to the message to be sent #[clap(short = 'f', long, num_args = 1.., value_name = "FILE")] pub file: Option>, /// Disable syntax highlighting diff --git a/src/config/mod.rs b/src/config/mod.rs index bcebdd0..e2fe864 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -67,6 +67,8 @@ pub struct Config { pub keybindings: Keybindings, /// Set a default role or session (role:, session:) pub prelude: String, + /// Whether to save the session automatically + pub save_session: bool, /// Compress session if tokens exceed this value (>=1000) pub compress_threshold: usize, /// The prompt for summarizing session messages @@ -110,6 +112,7 @@ impl Default for Config { auto_copy: false, keybindings: Default::default(), prelude: String::new(), + save_session: false, compress_threshold: 2000, summarize_prompt: "Summarize the discussion briefly in 200 words or less to use as a prompt for future context.".to_string(), summary_prompt: "This is a summary of the chat history as a recap: ".into(), @@ -584,8 +587,9 @@ impl Config { None => { let session_file = Self::session_file(TEMP_SESSION_NAME)?; if session_file.exists() { - remove_file(session_file) - .with_context(|| "Failed to clean previous session")?; + remove_file(session_file).with_context(|| { + format!("Failed to cleanup previous '{TEMP_SESSION_NAME}' session") + })?; } self.session = Some(Session::new( TEMP_SESSION_NAME, @@ -623,20 +627,29 @@ impl Config { Ok(()) } - pub fn end_session(&mut self) -> Result<()> { + /// End the current session, saving it if necessary + /// The single argument `interactive` ensures that non-interactive sessions will never prompt + pub fn end_session(&mut self, interactive: bool) -> Result<()> { if let Some(mut session) = self.session.take() { self.last_message = None; self.temperature = self.default_temperature; if session.dirty { - let ans = Confirm::new("Save session?").with_default(false).prompt()?; - if !ans { - return Ok(()); - } - let mut name = session.name().to_string(); - if session.is_temp() { - name = Text::new("Session name:").with_default(&name).prompt()?; + // If it's a temporary session, we'll always prompt to save on exit + // If it's named, we'll save automatically if they've set the save flag and prompt if they haven't + if !self.save_session || session.is_temp() { + if !interactive { + // If we're not interactive, we will not prompt and will not save + return Ok(()); + } + let ans = Confirm::new("Save session?").with_default(false).prompt()?; + if !ans { + return Ok(()); + } + while session.is_temp() || session.name().is_empty() { + session.name = Text::new("Session name:").prompt()?; + } } - let session_path = Self::session_file(&name)?; + let session_path = Self::session_file(session.name())?; let sessions_dir = session_path.parent().ok_or_else(|| { anyhow!("Unable to save session file to {}", session_path.display()) })?; diff --git a/src/main.rs b/src/main.rs index 589676e..502f6d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,6 +54,9 @@ fn main() -> Result<()> { if let Some(wrap) = &cli.wrap { config.write().set_wrap(wrap)?; } + if cli.save_session { + config.write().save_session = true; + } if cli.light_theme { config.write().light_theme = true; } @@ -111,9 +114,6 @@ fn start_directive( no_stream: bool, code_mode: bool, ) -> Result<()> { - if let Some(session) = &config.read().session { - session.guard_save()?; - } let input = Input::new( text, include.unwrap_or_default(), @@ -141,7 +141,9 @@ fn start_directive( let abort = create_abort_signal(); render_stream(&input, client.as_ref(), config, abort)? }; + // Save the message/session config.write().save_message(input, &output)?; + config.write().end_session(false)?; Ok(()) } diff --git a/src/repl/mod.rs b/src/repl/mod.rs index 26a3fb4..1633774 100644 --- a/src/repl/mod.rs +++ b/src/repl/mod.rs @@ -212,7 +212,7 @@ impl Repl { self.config.write().clear_role()?; } Some("session") => { - self.config.write().end_session()?; + self.config.write().end_session(true)?; } Some(_) => unknown_command()?, None => { -- cgit v1.2.3