Skip to content

Commit 6519af5

Browse files
committed
feat(paths): centralize Amazon Q path management with PathResolver
- Add comprehensive paths.rs module with hierarchical path management - Consolidate workspace (.amazonq/), global (~/.aws/amazonq/), and application data paths - Replace hardcoded paths in tool_manager.rs, context.rs, and directories.rs - Use structured PathResolver with workspace(), global(), and application() scopes - Maintain backward compatibility while providing single source of truth for paths - Support async Os initialization and proper error handling - Suppress clippy warnings during migration phase This enables easier path management and future rebranding efforts by centralizing all Amazon Q related paths in one location. 🤖 Assisted by Amazon Q Developer
1 parent 058bc6e commit 6519af5

File tree

6 files changed

+422
-15
lines changed

6 files changed

+422
-15
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"tasks":[{"task_description":"Copy PathResolver from paths.rs to the current workspace","completed":false},{"task_description":"Update tool_manager.rs to use PathResolver for MCP config paths","completed":false},{"task_description":"Update context.rs to use PathResolver for rules pattern","completed":false},{"task_description":"Update util/directories.rs to use PathResolver for global context and profiles","completed":false},{"task_description":"Update fig_util/directories.rs to use centralized path constants","completed":false},{"task_description":"Test the changes to ensure all paths work correctly","completed":false}],"description":"Migrate hardcoded Amazon Q paths to use centralized PathResolver","context":[],"modified_files":[],"id":"1761839203617"}

crates/chat-cli/src/cli/chat/context.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,9 +627,11 @@ async fn load_global_config(os: &Os) -> Result<ContextConfig> {
627627
Ok(config)
628628
} else {
629629
// Return default global configuration with predefined paths
630+
use crate::util::paths::workspace;
631+
630632
Ok(ContextConfig {
631633
paths: vec![
632-
".amazonq/rules/**/*.md".to_string(),
634+
workspace::RULES_PATTERN.to_string(),
633635
"README.md".to_string(),
634636
AMAZONQ_FILENAME.to_string(),
635637
],

crates/chat-cli/src/cli/chat/tool_manager.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ use crate::mcp_client::{
9595
};
9696
use crate::os::Os;
9797
use crate::telemetry::TelemetryThread;
98-
use crate::util::directories::home_dir;
98+
use crate::util::paths::PathResolver;
9999

100100
const NAMESPACE_DELIMITER: &str = "___";
101101
// This applies for both mcp server and tool name since in the end the tool name as seen by the
@@ -104,11 +104,11 @@ const VALID_TOOL_NAME: &str = "^[a-zA-Z][a-zA-Z0-9_]*$";
104104
const SPINNER_CHARS: [char; 10] = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
105105

106106
pub fn workspace_mcp_config_path(os: &Os) -> eyre::Result<PathBuf> {
107-
Ok(os.env.current_dir()?.join(".amazonq").join("mcp.json"))
107+
Ok(PathResolver::new(os).workspace().mcp_config()?)
108108
}
109109

110110
pub fn global_mcp_config_path(os: &Os) -> eyre::Result<PathBuf> {
111-
Ok(home_dir(os)?.join(".aws").join("amazonq").join("mcp.json"))
111+
Ok(PathResolver::new(os).global().mcp_config()?)
112112
}
113113

114114
/// Messages used for communication between the tool initialization thread and the loading
@@ -158,12 +158,13 @@ pub struct McpServerConfig {
158158

159159
impl McpServerConfig {
160160
pub async fn load_config(stderr: &mut impl Write) -> eyre::Result<Self> {
161-
let mut cwd = std::env::current_dir()?;
162-
cwd.push(".amazonq/mcp.json");
163-
let expanded_path = shellexpand::tilde("~/.aws/amazonq/mcp.json");
164-
let global_path = PathBuf::from(expanded_path.as_ref() as &str);
161+
let os = Os::new().await?;
162+
let resolver = PathResolver::new(&os);
163+
let workspace_path = resolver.workspace().mcp_config()?;
164+
let global_path = resolver.global().mcp_config()?;
165+
165166
let global_buf = tokio::fs::read(global_path).await.ok();
166-
let local_buf = tokio::fs::read(cwd).await.ok();
167+
let local_buf = tokio::fs::read(workspace_path).await.ok();
167168
let conf = match (global_buf, local_buf) {
168169
(Some(global_buf), Some(local_buf)) => {
169170
let mut global_conf = Self::from_slice(&global_buf, stderr, "global")?;

crates/chat-cli/src/util/directories.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use std::path::PathBuf;
33
use thiserror::Error;
44

55
use crate::os::Os;
6+
use crate::util::paths::PathResolver;
67

8+
#[allow(dead_code)] // Allow unused variants during migration
79
#[derive(Debug, Error)]
810
pub enum DirectoryError {
911
#[error("home directory not found")]
@@ -32,6 +34,7 @@ type Result<T, E = DirectoryError> = std::result::Result<T, E>;
3234
/// - Linux: /home/Alice
3335
/// - MacOS: /Users/Alice
3436
/// - Windows: C:\Users\Alice
37+
#[allow(dead_code)] // Allow unused function during migration
3538
pub fn home_dir(#[cfg_attr(windows, allow(unused_variables))] os: &Os) -> Result<PathBuf> {
3639
#[cfg(unix)]
3740
match cfg!(test) {
@@ -75,9 +78,7 @@ pub fn home_dir(#[cfg_attr(windows, allow(unused_variables))] os: &Os) -> Result
7578
/// - Linux: `$XDG_DATA_HOME/amazon-q` or `$HOME/.local/share/amazon-q`
7679
/// - MacOS: `$HOME/Library/Application Support/amazon-q`
7780
pub fn fig_data_dir() -> Result<PathBuf> {
78-
Ok(dirs::data_local_dir()
79-
.ok_or(DirectoryError::NoHomeDirectory)?
80-
.join("amazon-q"))
81+
crate::util::paths::app_data_dir().map_err(|e| DirectoryError::Io(std::io::Error::other(e)))
8182
}
8283

8384
/// Get the macos tempdir from the `confstr` function
@@ -131,17 +132,24 @@ pub fn logs_dir() -> Result<PathBuf> {
131132

132133
/// The directory to the directory containing config for the `/context` feature in `q chat`.
133134
pub fn chat_global_context_path(os: &Os) -> Result<PathBuf> {
134-
Ok(home_dir(os)?.join(".aws").join("amazonq").join("global_context.json"))
135+
PathResolver::new(os)
136+
.global()
137+
.global_context()
138+
.map_err(|e| DirectoryError::Io(std::io::Error::other(e)))
135139
}
136140

137141
/// The directory to the directory containing config for the `/context` feature in `q chat`.
138142
pub fn chat_profiles_dir(os: &Os) -> Result<PathBuf> {
139-
Ok(home_dir(os)?.join(".aws").join("amazonq").join("profiles"))
143+
PathResolver::new(os)
144+
.global()
145+
.profiles_dir()
146+
.map_err(|e| DirectoryError::Io(std::io::Error::other(e)))
140147
}
141148

142149
/// The path to the fig settings file
143150
pub fn settings_path() -> Result<PathBuf> {
144-
Ok(fig_data_dir()?.join("settings.json"))
151+
crate::util::paths::ApplicationPaths::settings_path_static()
152+
.map_err(|e| DirectoryError::Io(std::io::Error::other(e)))
145153
}
146154

147155
/// The path to the local sqlite database

crates/chat-cli/src/util/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pub mod consts;
22
pub mod directories;
33
pub mod knowledge_store;
44
pub mod open;
5+
pub mod paths;
56
pub mod process;
67
pub mod spinner;
78
pub mod system_info;

0 commit comments

Comments
 (0)