Skip to content

Commit bbf7f69

Browse files
committed
feat: refactored for code quality
1 parent 3cb80f0 commit bbf7f69

File tree

6 files changed

+93
-83
lines changed

6 files changed

+93
-83
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,10 @@ pub const AGENT_FORMAT_TOOLS_DOC_URL: &str =
2626

2727
pub const AGENT_MIGRATION_DOC_URL: &str =
2828
"https://github.com/aws/amazon-q-developer-cli/blob/main/docs/legacy-profile-to-agent-migration.md";
29+
30+
31+
// The environment variable name where we set additional metadata for the AWS CLI user agent.
32+
pub const USER_AGENT_ENV_VAR: &str = "AWS_EXECUTION_ENV";
33+
pub const USER_AGENT_APP_NAME: &str = "AmazonQ-For-CLI";
34+
pub const USER_AGENT_VERSION_KEY: &str = "Version";
35+
pub const USER_AGENT_VERSION_VALUE: &str = env!("CARGO_PKG_VERSION");

crates/chat-cli/src/cli/chat/tools/execute/mod.rs

Lines changed: 38 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,7 @@ use crate::cli::chat::tools::{
2323
use crate::cli::chat::util::truncate_safe;
2424
use crate::os::Os;
2525

26-
/// The environment variable name where we set additional metadata for the AWS CLI user agent.
27-
const USER_AGENT_ENV_VAR: &str = "AWS_EXECUTION_ENV";
28-
const USER_AGENT_APP_NAME: &str = "AmazonQ-For-CLI";
29-
const USER_AGENT_VERSION_KEY: &str = "Version";
30-
const USER_AGENT_VERSION_VALUE: &str = env!("CARGO_PKG_VERSION");
26+
use super::user_agent_env_vars;
3127

3228
// Platform-specific modules
3329
#[cfg(windows)]
@@ -135,7 +131,8 @@ impl ExecuteCommand {
135131
}
136132

137133
pub async fn invoke(&self, output: &mut impl Write) -> Result<InvokeOutput> {
138-
let output = run_command(&self.command, MAX_TOOL_RESPONSE_SIZE / 3, Some(output)).await?;
134+
let os = Os::new().await?;
135+
let output = run_command(&os, &self.command, MAX_TOOL_RESPONSE_SIZE / 3, Some(output)).await?;
139136
let clean_stdout = sanitize_unicode_tags(&output.stdout);
140137
let clean_stderr = sanitize_unicode_tags(&output.stderr);
141138

@@ -253,32 +250,6 @@ pub fn format_output(output: &str, max_size: usize) -> String {
253250
)
254251
}
255252

256-
/// Helper function to set up environment variables with user agent metadata for CloudTrail tracking
257-
pub fn setup_env_vars() -> std::collections::HashMap<String, String> {
258-
let mut env_vars: std::collections::HashMap<String, String> = std::env::vars().collect();
259-
260-
// Set up additional metadata for the AWS CLI user agent
261-
let user_agent_metadata_value = format!(
262-
"{} {}/{}",
263-
USER_AGENT_APP_NAME, USER_AGENT_VERSION_KEY, USER_AGENT_VERSION_VALUE
264-
);
265-
266-
// If the user agent metadata env var already exists, append to it, otherwise set it
267-
if let Some(existing_value) = env_vars.get(USER_AGENT_ENV_VAR) {
268-
if !existing_value.is_empty() {
269-
env_vars.insert(
270-
USER_AGENT_ENV_VAR.to_string(),
271-
format!("{} {}", existing_value, user_agent_metadata_value),
272-
);
273-
} else {
274-
env_vars.insert(USER_AGENT_ENV_VAR.to_string(), user_agent_metadata_value);
275-
}
276-
} else {
277-
env_vars.insert(USER_AGENT_ENV_VAR.to_string(), user_agent_metadata_value);
278-
}
279-
280-
env_vars
281-
}
282253

283254
#[cfg(test)]
284255
mod tests {
@@ -418,10 +389,16 @@ mod tests {
418389
}
419390
}
420391

421-
#[test]
422-
fn test_cloudtrail_tracking() {
423-
// Test that setup_env_vars sets the AWS_EXECUTION_ENV variable correctly
424-
let env_vars = setup_env_vars();
392+
#[tokio::test]
393+
async fn test_cloudtrail_tracking() {
394+
use crate::cli::chat::consts::{
395+
USER_AGENT_APP_NAME, USER_AGENT_ENV_VAR, USER_AGENT_VERSION_KEY, USER_AGENT_VERSION_VALUE,
396+
};
397+
398+
let os = Os::new().await.unwrap();
399+
400+
// Test that user_agent_env_vars sets the AWS_EXECUTION_ENV variable correctly
401+
let env_vars = user_agent_env_vars(&os);
425402

426403
// Check that AWS_EXECUTION_ENV is set
427404
assert!(env_vars.contains_key(USER_AGENT_ENV_VAR));
@@ -441,23 +418,36 @@ mod tests {
441418
assert!(user_agent_value.contains(&expected_metadata));
442419
}
443420

444-
#[test]
445-
fn test_cloudtrail_tracking_with_existing_env() {
446-
// Set an existing AWS_EXECUTION_ENV value
447-
unsafe {
448-
std::env::set_var(USER_AGENT_ENV_VAR, "ExistingValue");
449-
}
421+
#[tokio::test]
422+
async fn test_cloudtrail_tracking_with_existing_env() {
423+
use crate::cli::chat::consts::{
424+
USER_AGENT_APP_NAME, USER_AGENT_ENV_VAR,
425+
};
426+
use crate::os::Env;
427+
428+
// Create a fake environment with an existing AWS_EXECUTION_ENV value
429+
let env = Env::from_slice(&[(USER_AGENT_ENV_VAR, "ExistingValue")]);
430+
431+
// Create a minimal Os struct for testing - we'll manually construct it
432+
let fs = crate::os::Fs::new();
433+
let mut database = crate::database::Database::new().await.unwrap();
434+
let client = crate::api_client::ApiClient::new(&env, &fs, &mut database, None).await.unwrap();
435+
let telemetry = crate::telemetry::TelemetryThread::new(&env, &fs, &mut database).await.unwrap();
450436

451-
let env_vars = setup_env_vars();
437+
let os = crate::os::Os {
438+
env,
439+
fs,
440+
sysinfo: crate::os::SysInfo::new(),
441+
database,
442+
client,
443+
telemetry,
444+
};
445+
446+
let env_vars = user_agent_env_vars(&os);
452447
let user_agent_value = env_vars.get(USER_AGENT_ENV_VAR).unwrap();
453448

454449
// Should contain both the existing value and our metadata
455450
assert!(user_agent_value.contains("ExistingValue"));
456451
assert!(user_agent_value.contains(USER_AGENT_APP_NAME));
457-
458-
// Clean up
459-
unsafe {
460-
std::env::remove_var(USER_AGENT_ENV_VAR);
461-
}
462452
}
463453
}

crates/chat-cli/src/cli/chat/tools/execute/unix.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ use tracing::error;
1313
use super::{
1414
CommandResult,
1515
format_output,
16-
setup_env_vars,
16+
user_agent_env_vars,
1717
};
18+
use crate::os::Os;
1819

1920
/// Run a bash command on Unix systems.
2021
/// # Arguments
@@ -24,14 +25,15 @@ use super::{
2425
/// # Returns
2526
/// A [`CommandResult`]
2627
pub async fn run_command<W: Write>(
28+
os: &Os,
2729
command: &str,
2830
max_result_size: usize,
2931
mut updates: Option<W>,
3032
) -> Result<CommandResult> {
3133
let shell = std::env::var("AMAZON_Q_CHAT_SHELL").unwrap_or("bash".to_string());
3234

3335
// Set up environment variables with user agent metadata for CloudTrail tracking
34-
let env_vars = setup_env_vars();
36+
let env_vars = user_agent_env_vars(os);
3537

3638
// We need to maintain a handle on stderr and stdout, but pipe it to the terminal as well
3739
let mut child = tokio::process::Command::new(shell)

crates/chat-cli/src/cli/chat/tools/execute/windows.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ use tracing::error;
1313
use super::{
1414
CommandResult,
1515
format_output,
16-
setup_env_vars,
16+
user_agent_env_vars,
1717
};
18+
use crate::os::Os;
1819

1920
/// Run a command on Windows using cmd.exe.
2021
/// # Arguments
@@ -24,12 +25,14 @@ use super::{
2425
/// # Returns
2526
/// A [`CommandResult`]
2627
pub async fn run_command<W: Write>(
28+
os: &Os,
2729
command: &str,
2830
max_result_size: usize,
2931
mut updates: Option<W>,
3032
) -> Result<CommandResult> {
33+
3134
// Set up environment variables with user agent metadata for CloudTrail tracking
32-
let env_vars = setup_env_vars();
35+
let env_vars = user_agent_env_vars(os);
3336

3437
// We need to maintain a handle on stderr and stdout, but pipe it to the terminal as well
3538
let mut child = tokio::process::Command::new("cmd")

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

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ use thinking::Thinking;
3737
use tracing::error;
3838
use use_aws::UseAws;
3939

40-
use super::consts::MAX_TOOL_RESPONSE_SIZE;
40+
use super::consts::{
41+
MAX_TOOL_RESPONSE_SIZE, USER_AGENT_APP_NAME, USER_AGENT_ENV_VAR, USER_AGENT_VERSION_KEY,
42+
USER_AGENT_VERSION_VALUE,
43+
};
4144
use super::util::images::RichImageBlocks;
4245
use crate::cli::agent::{
4346
Agent,
@@ -418,6 +421,36 @@ pub fn queue_function_result(result: &str, updates: &mut impl Write, is_error: b
418421
Ok(())
419422
}
420423

424+
/// Helper function to set up environment variables with user agent metadata for CloudTrail tracking
425+
pub fn user_agent_env_vars(os: &Os) -> std::collections::HashMap<String, String> {
426+
let mut env_vars: std::collections::HashMap<String, String> = std::env::vars().collect();
427+
428+
// Set up additional metadata for the AWS CLI user agent
429+
let user_agent_metadata_value = format!(
430+
"{} {}/{}",
431+
USER_AGENT_APP_NAME, USER_AGENT_VERSION_KEY, USER_AGENT_VERSION_VALUE
432+
);
433+
434+
// Check if the user agent metadata env var already exists using Os
435+
let existing_value = os.env.get(USER_AGENT_ENV_VAR).ok();
436+
437+
// If the user agent metadata env var already exists, append to it, otherwise set it
438+
if let Some(existing_value) = existing_value {
439+
if !existing_value.is_empty() {
440+
env_vars.insert(
441+
USER_AGENT_ENV_VAR.to_string(),
442+
format!("{} {}", existing_value, user_agent_metadata_value),
443+
);
444+
} else {
445+
env_vars.insert(USER_AGENT_ENV_VAR.to_string(), user_agent_metadata_value);
446+
}
447+
} else {
448+
env_vars.insert(USER_AGENT_ENV_VAR.to_string(), user_agent_metadata_value);
449+
}
450+
451+
env_vars
452+
}
453+
421454
#[cfg(test)]
422455
mod tests {
423456
use std::path::MAIN_SEPARATOR;

crates/chat-cli/src/cli/chat/tools/use_aws.rs

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,9 @@ use crate::cli::agent::{
2929
};
3030
use crate::os::Os;
3131

32-
const READONLY_OPS: [&str; 6] = ["get", "describe", "list", "ls", "search", "batch_get"];
32+
use super::user_agent_env_vars;
3333

34-
/// The environment variable name where we set additional metadata for the AWS CLI user agent.
35-
const USER_AGENT_ENV_VAR: &str = "AWS_EXECUTION_ENV";
36-
const USER_AGENT_APP_NAME: &str = "AmazonQ-For-CLI";
37-
const USER_AGENT_VERSION_KEY: &str = "Version";
38-
const USER_AGENT_VERSION_VALUE: &str = env!("CARGO_PKG_VERSION");
34+
const READONLY_OPS: [&str; 6] = ["get", "describe", "list", "ls", "search", "batch_get"];
3935

4036
// TODO: we should perhaps composite this struct with an interface that we can use to mock the
4137
// actual cli with. That will allow us to more thoroughly test it.
@@ -54,32 +50,11 @@ impl UseAws {
5450
!READONLY_OPS.iter().any(|op| self.operation_name.starts_with(op))
5551
}
5652

57-
pub async fn invoke(&self, _os: &Os, _updates: impl Write) -> Result<InvokeOutput> {
53+
pub async fn invoke(&self, os: &Os, _updates: impl Write) -> Result<InvokeOutput> {
5854
let mut command = tokio::process::Command::new("aws");
59-
command.envs(std::env::vars());
60-
61-
// Set up environment variables
62-
let mut env_vars: std::collections::HashMap<String, String> = std::env::vars().collect();
63-
64-
// Set up additional metadata for the AWS CLI user agent
65-
let user_agent_metadata_value = format!(
66-
"{} {}/{}",
67-
USER_AGENT_APP_NAME, USER_AGENT_VERSION_KEY, USER_AGENT_VERSION_VALUE
68-
);
6955

70-
// If the user agent metadata env var already exists, append to it, otherwise set it
71-
if let Some(existing_value) = env_vars.get(USER_AGENT_ENV_VAR) {
72-
if !existing_value.is_empty() {
73-
env_vars.insert(
74-
USER_AGENT_ENV_VAR.to_string(),
75-
format!("{} {}", existing_value, user_agent_metadata_value),
76-
);
77-
} else {
78-
env_vars.insert(USER_AGENT_ENV_VAR.to_string(), user_agent_metadata_value);
79-
}
80-
} else {
81-
env_vars.insert(USER_AGENT_ENV_VAR.to_string(), user_agent_metadata_value);
82-
}
56+
// Set up environment variables with user agent metadata for CloudTrail tracking
57+
let env_vars = user_agent_env_vars(os);
8358

8459
command.envs(env_vars).arg("--region").arg(&self.region);
8560
if let Some(profile_name) = self.profile_name.as_deref() {

0 commit comments

Comments
 (0)