summaryrefslogtreecommitdiffstats
path: root/src/config/mod.rs
diff options
context:
space:
mode:
authorsigoden <sigoden@gmail.com>2024-11-19 18:10:07 +0800
committerGitHub <noreply@github.com>2024-11-19 18:10:07 +0800
commit8c7e58ad1d76a8e74f73d0a95fa12ffcda400e9f (patch)
treeb3f84b1c87063b646a3641e3f40cdbf8139abd2c /src/config/mod.rs
parentbb1c34d0b84e342232c4e0b7f3f0c1fb3a9334c0 (diff)
downloadaichat-8c7e58ad1d76a8e74f73d0a95fa12ffcda400e9f.tar.gz
feat: support autonaming session (#1001)
Diffstat (limited to 'src/config/mod.rs')
-rw-r--r--src/config/mod.rs142
1 files changed, 118 insertions, 24 deletions
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 136fee1..e578620 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -5,7 +5,9 @@ mod session;
pub use self::agent::{list_agents, Agent};
pub use self::input::Input;
-pub use self::role::{Role, RoleLike, CODE_ROLE, EXPLAIN_SHELL_ROLE, SHELL_ROLE};
+pub use self::role::{
+ Role, RoleLike, CODE_ROLE, CREATE_TITLE_ROLE, EXPLAIN_SHELL_ROLE, SHELL_ROLE,
+};
use self::session::Session;
use crate::client::{
@@ -37,6 +39,10 @@ use std::{
};
use syntect::highlighting::ThemeSet;
+pub const TEMP_ROLE_NAME: &str = "%%";
+pub const TEMP_RAG_NAME: &str = "temp";
+pub const TEMP_SESSION_NAME: &str = "temp";
+
/// Monokai Extended
const DARK_THEME: &[u8] = include_bytes!("../../assets/monokai-extended.theme.bin");
const LIGHT_THEME: &[u8] = include_bytes!("../../assets/monokai-extended-light.theme.bin");
@@ -52,10 +58,6 @@ const FUNCTIONS_FILE_NAME: &str = "functions.json";
const FUNCTIONS_BIN_DIR_NAME: &str = "bin";
const AGENTS_DIR_NAME: &str = "agents";
-pub const TEMP_ROLE_NAME: &str = "%%";
-pub const TEMP_RAG_NAME: &str = "temp";
-pub const TEMP_SESSION_NAME: &str = "temp";
-
const CLIENTS_FIELD: &str = "clients";
const SERVE_ADDR: &str = "127.0.0.1:8000";
@@ -339,7 +341,10 @@ impl Config {
}
pub fn session_file(&self, name: &str) -> PathBuf {
- self.sessions_dir().join(format!("{name}.yaml"))
+ match name.split_once("/") {
+ Some((dir, name)) => self.sessions_dir().join(dir).join(format!("{name}.yaml")),
+ None => self.sessions_dir().join(format!("{name}.yaml")),
+ }
}
pub fn rag_file(&self, name: &str) -> PathBuf {
@@ -1081,7 +1086,10 @@ impl Config {
let session_name = match &self.session {
Some(session) => match name {
Some(v) => v.to_string(),
- None => session.name().to_string(),
+ None => session
+ .autoname()
+ .unwrap_or_else(|| session.name())
+ .to_string(),
},
None => bail!("No session"),
};
@@ -1124,9 +1132,9 @@ impl Config {
Ok(())
}
- pub fn set_append_conversation(&mut self) -> Result<()> {
+ pub fn set_save_session_this_time(&mut self) -> Result<()> {
if let Some(session) = self.session.as_mut() {
- session.set_append_conversation();
+ session.set_save_session_this_time();
} else {
bail!("No session")
}
@@ -1137,14 +1145,42 @@ impl Config {
list_file_names(self.sessions_dir(), ".yaml")
}
- pub fn should_compress_session(&mut self) -> bool {
- if let Some(session) = self.session.as_mut() {
- if session.need_compress(self.compress_threshold) {
- session.set_compressing(true);
- return true;
+ pub fn list_autoname_sessions(&self) -> Vec<String> {
+ list_file_names(self.sessions_dir().join("_"), ".yaml")
+ }
+
+ pub fn maybe_compress_session(config: GlobalConfig) {
+ let mut need_compress = false;
+ {
+ let mut config = config.write();
+ let compress_threshold = config.compress_threshold;
+ if let Some(session) = config.session.as_mut() {
+ if session.need_compress(compress_threshold) {
+ session.set_compressing(true);
+ need_compress = true;
+ }
}
+ };
+ if !need_compress {
+ return;
}
- false
+ let color = if config.read().light_theme {
+ nu_ansi_term::Color::LightGray
+ } else {
+ nu_ansi_term::Color::DarkGray
+ };
+ print!(
+ "\n📢 {}\n",
+ color.italic().paint("Compressing the session."),
+ );
+ tokio::spawn(async move {
+ if let Err(err) = Config::compress_session(&config).await {
+ warn!("Failed to compress the session: {err}");
+ }
+ if let Some(session) = config.write().session.as_mut() {
+ session.set_compressing(false);
+ }
+ });
}
pub async fn compress_session(config: &GlobalConfig) -> Result<()> {
@@ -1156,7 +1192,13 @@ impl Config {
}
None => bail!("No session"),
}
- let input = Input::from_str(config, config.read().summarize_prompt(), None);
+
+ let prompt = config
+ .read()
+ .summarize_prompt
+ .clone()
+ .unwrap_or_else(|| SUMMARIZE_PROMPT.into());
+ let input = Input::from_str(config, &prompt, None);
let client = input.create_client()?;
let summary = client.chat_completions(input).await?.text;
let summary_prompt = config
@@ -1171,10 +1213,6 @@ impl Config {
Ok(())
}
- pub fn summarize_prompt(&self) -> &str {
- self.summarize_prompt.as_deref().unwrap_or(SUMMARIZE_PROMPT)
- }
-
pub fn is_compressing_session(&self) -> bool {
self.session
.as_ref()
@@ -1182,10 +1220,51 @@ impl Config {
.unwrap_or_default()
}
- pub fn end_compressing_session(&mut self) {
- if let Some(session) = self.session.as_mut() {
- session.set_compressing(false);
+ pub fn maybe_autoname_session(config: GlobalConfig) {
+ let mut need_autoname = false;
+ if let Some(session) = config.write().session.as_mut() {
+ if session.need_autoname() {
+ session.set_autonaming(true);
+ need_autoname = true;
+ }
+ }
+ if !need_autoname {
+ return;
+ }
+ let color = if config.read().light_theme {
+ nu_ansi_term::Color::LightGray
+ } else {
+ nu_ansi_term::Color::DarkGray
+ };
+ print!("\n📢 {}\n", color.italic().paint("Autonaming the session."),);
+ tokio::spawn(async move {
+ if let Err(err) = Config::autoname_session(&config).await {
+ warn!("Failed to autonaming the session: {err}");
+ }
+ if let Some(session) = config.write().session.as_mut() {
+ session.set_autonaming(false);
+ }
+ });
+ }
+
+ pub async fn autoname_session(config: &GlobalConfig) -> Result<()> {
+ let text = match config
+ .read()
+ .session
+ .as_ref()
+ .and_then(|v| v.chat_history_for_autonaming())
+ {
+ Some(v) => v,
+ None => bail!("No chat history"),
+ };
+ let role = config.read().retrieve_role(CREATE_TITLE_ROLE)?;
+ let input = Input::from_str(config, &text, Some(role));
+ let client = input.create_client()?;
+ let text = client.chat_completions(input).await?.text;
+ if let Some(session) = config.write().session.as_mut() {
+ session.set_autoname(&text);
}
+ Ok(())
}
pub async fn use_rag(
@@ -1562,7 +1641,19 @@ impl Config {
.into_iter()
.map(|v| (v.id(), Some(v.description())))
.collect(),
- ".session" => map_completion_values(self.list_sessions()),
+ ".session" => {
+ if args[0].starts_with("_/") {
+ map_completion_values(
+ self.list_autoname_sessions()
+ .iter()
+ .rev()
+ .map(|v| format!("_/{}", v))
+ .collect::<Vec<String>>(),
+ )
+ } else {
+ map_completion_values(self.list_sessions())
+ }
+ }
".rag" => map_completion_values(Self::list_rags()),
".agent" => map_completion_values(list_agents()),
".starter" => match &self.agent {
@@ -1772,6 +1863,9 @@ impl Config {
}
if let Some(session) = &self.session {
output.insert("session", session.name().to_string());
+ if let Some(autoname) = session.autoname() {
+ output.insert("session_autoname", autoname.to_string());
+ }
output.insert("dirty", session.dirty().to_string());
let (tokens, percent) = session.tokens_usage();
output.insert("consume_tokens", tokens.to_string());