From b2976eb474d926d2ce5f2b38f18b73576705fb70 Mon Sep 17 00:00:00 2001 From: bhagwan Date: Tue, 17 Feb 2026 23:27:13 -0500 Subject: [PATCH] fix(config): support both legacy and new ZEROCLAW_WORKSPACE structure ZEROCLAW_WORKSPACE can now be either: - Legacy path: /path/to/workspace (config at /path/to/.zeroclaw/config.toml) - Parent path: /path/to (config at /path/to/config.toml, workspace at /path/to/workspace) This maintains backward compatibility with Docker's legacy folder structure while also supporting the new parent-dir layout. --- src/config/schema.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/config/schema.rs b/src/config/schema.rs index 86ac587..5f9731b 100644 --- a/src/config/schema.rs +++ b/src/config/schema.rs @@ -1865,10 +1865,11 @@ pub(crate) fn persist_active_workspace_config_dir(config_dir: &Path) -> Result<( Ok(()) } -fn resolve_config_dir_for_workspace(workspace_dir: &Path) -> PathBuf { +fn resolve_config_dir_for_workspace(workspace_dir: &Path) -> (PathBuf, PathBuf) { let workspace_config_dir = workspace_dir.to_path_buf(); + let workspace_dir = workspace_dir.join("workspace").to_path_buf(); if workspace_config_dir.join("config.toml").exists() { - return workspace_config_dir; + return (workspace_config_dir, workspace_dir); } let legacy_config_dir = workspace_dir @@ -1876,18 +1877,18 @@ fn resolve_config_dir_for_workspace(workspace_dir: &Path) -> PathBuf { .map(|parent| parent.join(".zeroclaw")); if let Some(legacy_dir) = legacy_config_dir { if legacy_dir.join("config.toml").exists() { - return legacy_dir; + return (legacy_dir, workspace_config_dir); } if workspace_dir .file_name() .is_some_and(|name| name == std::ffi::OsStr::new("workspace")) { - return legacy_dir; + return (legacy_dir, workspace_config_dir); } } - workspace_config_dir + (workspace_config_dir, workspace_dir) } fn decrypt_optional_secret( @@ -1934,8 +1935,7 @@ impl Config { // 3. Default ~/.zeroclaw layout let (zeroclaw_dir, workspace_dir) = match std::env::var("ZEROCLAW_WORKSPACE") { Ok(custom_workspace) if !custom_workspace.is_empty() => { - let workspace = PathBuf::from(custom_workspace); - (resolve_config_dir_for_workspace(&workspace), workspace) + resolve_config_dir_for_workspace(&PathBuf::from(custom_workspace)) } _ => load_persisted_workspace_dirs(&default_zeroclaw_dir)? .unwrap_or((default_zeroclaw_dir, default_workspace_dir)), @@ -2053,7 +2053,9 @@ impl Config { // Workspace directory: ZEROCLAW_WORKSPACE if let Ok(workspace) = std::env::var("ZEROCLAW_WORKSPACE") { if !workspace.is_empty() { - self.workspace_dir = PathBuf::from(workspace); + let (_, workspace_dir) = + resolve_config_dir_for_workspace(&PathBuf::from(workspace)); + self.workspace_dir = workspace_dir; } }