diff --git a/poc-memory/src/agents/daemon.rs b/poc-memory/src/agents/daemon.rs index 203a665..6aa71c9 100644 --- a/poc-memory/src/agents/daemon.rs +++ b/poc-memory/src/agents/daemon.rs @@ -1074,6 +1074,18 @@ pub fn run_daemon() -> Result<(), String> { }); } + daemon.add_rpc_handler(|cmd, _ctx| { + if cmd != "reload-config" { return None; } + let changed = crate::config::reload(); + let config = crate::config::get(); + let api = config.api_base_url.as_deref().unwrap_or("(none)"); + let model = config.api_model.as_deref().unwrap_or("(default)"); + log_event("daemon", "config-reload", + &format!("changed={}, api={}, model={}", changed, api, model)); + Some(format!("{{\"ok\":true,\"changed\":{},\"api_base_url\":\"{}\",\"api_model\":\"{}\"}}\n", + changed, api, model)) + }); + daemon.add_rpc_handler(|cmd, _ctx| { if !cmd.starts_with("record-hits ") { return None; } let keys: Vec<&str> = cmd.strip_prefix("record-hits ") diff --git a/poc-memory/src/cli/misc.rs b/poc-memory/src/cli/misc.rs index 249c86f..52a452d 100644 --- a/poc-memory/src/cli/misc.rs +++ b/poc-memory/src/cli/misc.rs @@ -268,7 +268,7 @@ pub fn cmd_load_context(stats: bool) -> Result<(), String> { println!("{}", "-".repeat(42)); for group in &cfg.context_groups { - let entries = get_group_content(group, &store, cfg); + let entries = get_group_content(group, &store, &cfg); let words: usize = entries.iter() .map(|(_, c)| c.split_whitespace().count()) .sum(); @@ -287,7 +287,7 @@ pub fn cmd_load_context(stats: bool) -> Result<(), String> { println!(); for group in &cfg.context_groups { - let entries = get_group_content(group, &store, cfg); + let entries = get_group_content(group, &store, &cfg); if !entries.is_empty() && group.source == crate::config::ContextSource::Journal { println!("--- recent journal entries ({}/{}) ---", entries.len(), cfg.journal_max); diff --git a/poc-memory/src/config.rs b/poc-memory/src/config.rs index 3c13c60..f6078ff 100644 --- a/poc-memory/src/config.rs +++ b/poc-memory/src/config.rs @@ -13,9 +13,9 @@ // {"group": "orientation", "keys": ["where-am-i.md"], "source": "file"} use std::path::PathBuf; -use std::sync::OnceLock; +use std::sync::{Arc, OnceLock, RwLock}; -static CONFIG: OnceLock = OnceLock::new(); +static CONFIG: OnceLock>> = OnceLock::new(); #[derive(Debug, Clone, PartialEq)] pub enum ContextSource { @@ -210,7 +210,23 @@ fn expand_home(path: &str) -> PathBuf { } } -/// Get the global config (loaded once on first access). -pub fn get() -> &'static Config { - CONFIG.get_or_init(Config::load_from_file) +/// Get the global config (cheap Arc clone). +pub fn get() -> Arc { + CONFIG + .get_or_init(|| RwLock::new(Arc::new(Config::load_from_file()))) + .read() + .unwrap() + .clone() +} + +/// Reload the config from disk. Returns true if changed. +pub fn reload() -> bool { + let lock = CONFIG.get_or_init(|| RwLock::new(Arc::new(Config::load_from_file()))); + let new = Config::load_from_file(); + let mut current = lock.write().unwrap(); + let changed = format!("{:?}", **current) != format!("{:?}", new); + if changed { + *current = Arc::new(new); + } + changed } diff --git a/poc-memory/src/main.rs b/poc-memory/src/main.rs index 6ea7822..f9b1540 100644 --- a/poc-memory/src/main.rs +++ b/poc-memory/src/main.rs @@ -469,6 +469,8 @@ enum DaemonCmd { }, /// Interactive TUI Tui, + /// Reload config file without restarting + ReloadConfig, } #[derive(Subcommand)] @@ -1057,6 +1059,12 @@ fn cmd_daemon(sub: DaemonCmd) -> Result<(), String> { DaemonCmd::Consolidate => daemon::rpc_consolidate(), DaemonCmd::Run { agent, count } => daemon::rpc_run_agent(&agent, count), DaemonCmd::Tui => tui::run_tui(), + DaemonCmd::ReloadConfig => { + match daemon::send_rpc_pub("reload-config") { + Some(resp) => { eprintln!("{}", resp.trim()); Ok(()) } + None => Err("daemon not running".into()), + } + } } }