From 185e773a2ce50a9ed9ae175abb3d61aff6af2532 Mon Sep 17 00:00:00 2001 From: syui Date: Tue, 24 Mar 2026 16:09:41 +0900 Subject: [PATCH] refactor(config): centralize OS config paths into config.rs helpers --- src/agent.rs | 15 ++------------- src/config.rs | 25 +++++++++++++++++++++++++ src/headless.rs | 15 ++------------- src/tui.rs | 12 +++--------- 4 files changed, 32 insertions(+), 35 deletions(-) diff --git a/src/agent.rs b/src/agent.rs index 1882272..aceed5f 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -292,12 +292,7 @@ impl Drop for Agent { /// Load user/bot identity from shared config. fn load_user_context() -> String { - let home = std::env::var("HOME").unwrap_or_default(); - let path = if cfg!(target_os = "macos") { - format!("{home}/Library/Application Support/ai.syui.log/config.json") - } else { - format!("{home}/.config/ai.syui.log/config.json") - }; + let path = crate::config::shared_config_path(); let config: serde_json::Value = std::fs::read_to_string(&path).ok() .and_then(|s| serde_json::from_str(&s).ok()) .unwrap_or_default(); @@ -310,13 +305,7 @@ fn load_user_context() -> String { /// Load last 3 session summaries for agent context. fn recent_session_summary() -> String { - let dir = if cfg!(target_os = "macos") { - let home = std::env::var("HOME").unwrap_or_default(); - format!("{home}/Library/Application Support/ai.syui.gpt/sessions") - } else { - let home = std::env::var("HOME").unwrap_or_default(); - format!("{home}/.local/share/aishell/sessions") - }; + let dir = crate::config::sessions_dir(); let mut files: Vec<_> = std::fs::read_dir(&dir) .into_iter().flatten().flatten() diff --git a/src/config.rs b/src/config.rs index 5a5788f..30d864e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,31 @@ use serde::Deserialize; use std::path::Path; +/// OS standard config directory. +pub fn config_dir() -> String { + let home = std::env::var("HOME").unwrap_or_default(); + if cfg!(target_os = "macos") { + format!("{home}/Library/Application Support") + } else { + std::env::var("XDG_CONFIG_HOME").unwrap_or_else(|_| format!("{home}/.config")) + } +} + +/// Path to shared config: $cfg/ai.syui.log/config.json +pub fn shared_config_path() -> String { + format!("{}/ai.syui.log/config.json", config_dir()) +} + +/// Path to aigpt config: $cfg/ai.syui.gpt/config.json +pub fn gpt_config_path() -> String { + format!("{}/ai.syui.gpt/config.json", config_dir()) +} + +/// Path to sessions dir: $cfg/ai.syui.gpt/sessions +pub fn sessions_dir() -> String { + format!("{}/ai.syui.gpt/sessions", config_dir()) +} + #[derive(Clone, Deserialize)] pub struct AgentConfig { pub name: String, diff --git a/src/headless.rs b/src/headless.rs index 867b32e..92eecb2 100644 --- a/src/headless.rs +++ b/src/headless.rs @@ -575,13 +575,7 @@ fn save_to_aigpt_memory(decision: &str, agents: &[serde_json::Value]) { } fn aigpt_memory_dir() -> Option { - let home = std::env::var("HOME").ok()?; - let config_path = if cfg!(target_os = "macos") { - format!("{home}/Library/Application Support/ai.syui.gpt/config.json") - } else { - format!("{home}/.config/ai.syui.gpt/config.json") - }; - + let config_path = config::gpt_config_path(); let content = std::fs::read_to_string(&config_path).ok()?; let config: serde_json::Value = serde_json::from_str(&content).ok()?; @@ -628,12 +622,7 @@ fn days_to_ymd(mut days: u64) -> (u64, u64, u64) { } fn session_base_dir() -> String { - let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string()); - if cfg!(target_os = "macos") { - format!("{home}/Library/Application Support/ai.syui.gpt/sessions") - } else { - format!("{home}/.local/share/aishell/sessions") - } + config::sessions_dir() } // ── AI integration ───────────────────────────────────────── diff --git a/src/tui.rs b/src/tui.rs index 2520de7..4874f45 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -664,12 +664,7 @@ fn parse_agent_commands(text: &str) -> Vec<(String, String, String)> { /// Load identity context from atproto config + recent chat. fn load_identity_context() -> String { - let home = std::env::var("HOME").unwrap_or_default(); - let config_path = if cfg!(target_os = "macos") { - format!("{home}/Library/Application Support/ai.syui.log/config.json") - } else { - format!("{home}/.config/ai.syui.log/config.json") - }; + let config_path = crate::config::shared_config_path(); let config: serde_json::Value = match std::fs::read_to_string(&config_path) { Ok(s) => serde_json::from_str(&s).unwrap_or_default(), @@ -693,14 +688,13 @@ fn load_identity_context() -> String { let expanded = expand_tilde(bot_path); let chat_dir = format!( "{}/{}/ai.syui.log.chat", - if expanded.is_empty() { format!("{home}/.config/ai.syui.log/at") } else { expanded.clone() }, + if expanded.is_empty() { format!("{}/ai.syui.log/at", crate::config::config_dir()) } else { expanded.clone() }, config["bot"]["did"].as_str().unwrap_or("did") ); - // Also check user's chat dir let user_did = config["did"].as_str().unwrap_or(""); let user_chat_dir = format!("{}/{}/ai.syui.log.chat", - if expanded.is_empty() { format!("{home}/.config/ai.syui.log/at") } else { expanded }, + if expanded.is_empty() { format!("{}/ai.syui.log/at", crate::config::config_dir()) } else { expanded }, user_did );