Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions crates/chat-cli/src/cli/agent/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,7 @@ impl Agents {
// 2. If the above is missing or invalid, assume one that is specified by chat.defaultAgent
// 3. If the above is missing or invalid, assume the in-memory default
let active_idx = 'active_idx: {
// 1. Command line argument --agent
if let Some(name) = agent_name {
if all_agents.iter().any(|a| a.name.as_str() == name) {
break 'active_idx name.to_string();
Expand All @@ -659,14 +660,38 @@ impl Agents {
style::Print("Error"),
style::SetForegroundColor(Color::Yellow),
style::Print(format!(
": no agent with name {} found. Falling back to user specified default",
": no agent with name {} found. Falling back to local default",
name
)),
style::Print("\n"),
style::SetForegroundColor(Color::Reset)
);
}

// 2. Local settings .amazonq/settings.json
if let Ok(current_dir) = std::env::current_dir() {
if let Ok(local_settings) = crate::database::local_settings::LocalSettings::new(&current_dir).await {
if let Some(local_default) = local_settings.get_string(Setting::ChatDefaultAgent) {
if all_agents.iter().any(|a| a.name == local_default) {
break 'active_idx local_default;
}
let _ = queue!(
output,
style::SetForegroundColor(Color::Red),
style::Print("Error"),
style::SetForegroundColor(Color::Yellow),
style::Print(format!(
": local default agent {} not found. Falling back to global default",
local_default
)),
style::Print("\n"),
style::SetForegroundColor(Color::Reset)
);
}
}
}

// 3. Global settings
if let Some(user_set_default) = os.database.settings.get_string(Setting::ChatDefaultAgent) {
if all_agents.iter().any(|a| a.name == user_set_default) {
break 'active_idx user_set_default;
Expand All @@ -677,14 +702,15 @@ impl Agents {
style::Print("Error"),
style::SetForegroundColor(Color::Yellow),
style::Print(format!(
": user defined default {} not found. Falling back to in-memory default",
": global default agent {} not found. Falling back to in-memory default",
user_set_default
)),
style::Print("\n"),
style::SetForegroundColor(Color::Reset)
);
}

// 4. In-memory default
all_agents.push({
let mut agent = Agent::default();
if mcp_enabled {
Expand Down
68 changes: 68 additions & 0 deletions crates/chat-cli/src/database/local_settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use std::path::Path;

use serde_json::{Map, Value};
use tokio::fs::File;
use tokio::io::AsyncReadExt;

use super::{DatabaseError, settings::Setting};

/// Local settings for a specific workspace/project directory
#[derive(Debug, Clone, Default)]
pub struct LocalSettings(Map<String, Value>);

impl LocalSettings {
/// Create a new LocalSettings instance by reading from the workspace directory
pub async fn new(workspace_dir: &Path) -> Result<Self, DatabaseError> {
let settings_path = workspace_dir.join(".amazonq").join("settings.json");

Ok(Self(match settings_path.exists() {
true => {
let mut file = File::open(&settings_path).await?;
let mut buf = Vec::new();
file.read_to_end(&mut buf).await?;
serde_json::from_slice(&buf)?
},
false => Map::new(),
}))
}

/// Get a setting value
pub fn get(&self, key: Setting) -> Option<&Value> {
self.0.get(key.as_ref())
}

/// Get a string setting value
pub fn get_string(&self, key: Setting) -> Option<String> {
self.get(key).and_then(|value| value.as_str().map(|s| s.into()))
}
}

#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;

#[tokio::test]
async fn test_local_settings_new_empty() {
let temp_dir = TempDir::new().unwrap();
let settings = LocalSettings::new(temp_dir.path()).await.unwrap();
assert!(settings.0.is_empty());
}

#[tokio::test]
async fn test_local_settings_get_string() {
let temp_dir = TempDir::new().unwrap();

// Create a settings file manually
let amazonq_dir = temp_dir.path().join(".amazonq");
tokio::fs::create_dir_all(&amazonq_dir).await.unwrap();
let settings_path = amazonq_dir.join("settings.json");
tokio::fs::write(&settings_path, r#"{"chat.defaultAgent": "test_agent"}"#).await.unwrap();

let settings = LocalSettings::new(temp_dir.path()).await.unwrap();
assert_eq!(
settings.get_string(Setting::ChatDefaultAgent),
Some("test_agent".to_string())
);
}
}
1 change: 1 addition & 0 deletions crates/chat-cli/src/database/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod settings;
pub mod local_settings;

use std::ops::Deref;
use std::path::Path;
Expand Down