feat: 配置回退到 ~/.ias/ 目录

配置加载顺序(当前目录 → 全局目录 → 默认):
  1. .env              → ~/.ias/.env        → 无
  2. config.json        → ~/.ias/config.json  → 默认内置
  3. resources/skills/  (始终从项目目录加载)

现在可以在任意目录运行 ias,如:
  cd /tmp && ias whoami    # 读取 ~/.ias/ 的配置
This commit is contained in:
2026-06-02 09:51:22 +08:00
parent 1497b1bba0
commit e88f3240c4
2 changed files with 42 additions and 14 deletions
+32 -13
View File
@@ -142,27 +142,46 @@ impl Default for AppConfig {
impl AppConfig {
/// 从文件加载配置,缺失字段回退到环境变量
/// 尝试顺序:path → ~/.ias/config.json → 默认
pub fn from_file(path: impl AsRef<Path>) -> Self {
let path = path.as_ref();
// 尝试指定路径
if path.exists() {
match std::fs::read_to_string(path) {
Ok(content) => {
// 先做环境变量替换
let resolved = resolve_env_vars(&content);
match serde_json::from_str(&resolved) {
Ok(cfg) => return cfg,
Err(e) => {
tracing::warn!("解析配置文件失败 ({}): {},使用默认配置", path.display(), e);
}
}
}
Err(e) => {
tracing::warn!("读取配置文件失败 ({}): {},使用默认配置", path.display(), e);
match Self::try_load(path) {
Some(cfg) => return cfg,
None => tracing::warn!("解析配置文件失败: {},尝试回退", path.display()),
}
}
// 回退到 ~/.ias/config.json
let home = dirs::home_dir();
if let Some(home) = home {
let fallback = home.join(".ias").join("config.json");
if fallback.exists() {
tracing::info!("使用全局配置: {}", fallback.display());
match Self::try_load(&fallback) {
Some(cfg) => return cfg,
None => tracing::warn!("解析全局配置失败: {}", fallback.display()),
}
}
}
tracing::info!("使用默认配置");
Self::default()
}
fn try_load(path: &Path) -> Option<Self> {
let content = std::fs::read_to_string(path).ok()?;
let resolved = resolve_env_vars(&content);
match serde_json::from_str(&resolved) {
Ok(cfg) => Some(cfg),
Err(e) => {
tracing::warn!("解析配置文件失败 ({}): {}", path.display(), e);
None
}
}
}
}
/// 替换字符串中的 `${VAR_NAME}` 为环境变量值
+10 -1
View File
@@ -28,7 +28,16 @@ async fn main() {
let is_service = matches!(cli.command, Commands::Service);
logger::init_logger(Some(".data/logs"), is_service);
dotenvy::dotenv().ok();
// .env 加载:先当前目录,再 ~/.ias/.env
if std::path::Path::new(".env").exists() {
dotenvy::dotenv().ok();
} else if let Ok(home) = std::env::var("HOME") {
let fallback = std::path::PathBuf::from(&home).join(".ias").join(".env");
if fallback.exists() {
dotenvy::from_path(&fallback).ok();
tracing::info!("使用全局环境配置: {}", fallback.display());
}
}
let config = AppConfig::from_file("config.json");