diff --git a/Cargo.lock b/Cargo.lock index 7044d99416f4..8f8f79596d96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2633,6 +2633,7 @@ dependencies = [ "fs2", "futures", "include_dir", + "indexmap 2.12.0", "indoc", "insta", "jsonschema", @@ -2900,7 +2901,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.7.1", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -2919,7 +2920,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.2.0", - "indexmap 2.7.1", + "indexmap 2.12.0", "slab", "tokio", "tokio-util", @@ -2963,6 +2964,12 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "hashlink" version = "0.8.4" @@ -3511,13 +3518,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.16.0", "serde", + "serde_core", ] [[package]] @@ -3969,7 +3977,7 @@ dependencies = [ "chrono", "encoding_rs", "flate2", - "indexmap 2.7.1", + "indexmap 2.12.0", "itoa", "log", "md-5", @@ -4872,7 +4880,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ "base64 0.22.1", - "indexmap 2.7.1", + "indexmap 2.12.0", "quick-xml 0.32.0", "serde", "time", @@ -5025,7 +5033,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d35f4dc9988d1326b065b4def5e950c3ed727aa03e3151b86cc9e2aec6b03f54" dependencies = [ "futures", - "indexmap 2.7.1", + "indexmap 2.12.0", "nix 0.29.0", "tokio", "tracing", @@ -5992,7 +6000,7 @@ version = "1.0.142" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.12.0", "itoa", "memchr", "ryu", @@ -6041,7 +6049,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.7.1", + "indexmap 2.12.0", "serde", "serde_derive", "serde_json", @@ -6067,7 +6075,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.12.0", "itoa", "ryu", "serde", @@ -6314,7 +6322,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.7.1", + "indexmap 2.12.0", "log", "memchr", "once_cell", @@ -7078,7 +7086,7 @@ version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.12.0", "serde", "serde_spanned", "toml_datetime", @@ -7562,7 +7570,7 @@ version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.12.0", "serde", "serde_json", "utoipa-gen", @@ -8679,7 +8687,7 @@ dependencies = [ "crc32fast", "crossbeam-utils", "flate2", - "indexmap 2.7.1", + "indexmap 2.12.0", "memchr", "zopfli", ] diff --git a/crates/goose-cli/src/commands/info.rs b/crates/goose-cli/src/commands/info.rs index 0f0debc1c28a..3bedde5e439a 100644 --- a/crates/goose-cli/src/commands/info.rs +++ b/crates/goose-cli/src/commands/info.rs @@ -40,26 +40,22 @@ pub fn handle_info(verbose: bool) -> Result<()> { // Print verbose info if requested if verbose { println!("\n{}", style("goose Configuration:").cyan().bold()); - match config.load_values() { - Ok(values) => { - if values.is_empty() { - println!(" No configuration values set"); - println!( - " Run '{}' to configure goose", - style("goose configure").cyan() - ); - } else { - let sorted_values: std::collections::BTreeMap<_, _> = - values.iter().map(|(k, v)| (k.clone(), v.clone())).collect(); - - if let Ok(yaml) = serde_yaml::to_string(&sorted_values) { - for line in yaml.lines() { - println!(" {}", line); - } - } + let values = config.all_values()?; + if values.is_empty() { + println!(" No configuration values set"); + println!( + " Run '{}' to configure goose", + style("goose configure").cyan() + ); + } else { + let sorted_values: std::collections::BTreeMap<_, _> = + values.iter().map(|(k, v)| (k.clone(), v.clone())).collect(); + + if let Ok(yaml) = serde_yaml::to_string(&sorted_values) { + for line in yaml.lines() { + println!(" {}", line); } } - Err(e) => println!(" Error loading configuration: {}", e), } } diff --git a/crates/goose-server/src/routes/config_management.rs b/crates/goose-server/src/routes/config_management.rs index 2761fdb7a1a4..f40e86b2f299 100644 --- a/crates/goose-server/src/routes/config_management.rs +++ b/crates/goose-server/src/routes/config_management.rs @@ -272,7 +272,7 @@ pub async fn read_all_config() -> Result, StatusCode> { let config = Config::global(); let values = config - .load_values() + .all_values() .map_err(|_| StatusCode::UNPROCESSABLE_ENTITY)?; Ok(Json(ConfigResponse { config: values })) @@ -509,7 +509,7 @@ pub async fn init_config() -> Result, StatusCode> { // Use the shared function to load init-config.yaml match goose::config::base::load_init_config_from_workspace() { - Ok(init_values) => match config.save_values(init_values) { + Ok(init_values) => match config.initialize_if_empty(init_values) { Ok(_) => Ok(Json("Config initialized successfully".to_string())), Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), }, @@ -584,7 +584,7 @@ pub async fn recover_config() -> Result, StatusCode> { let config = Config::global(); // Force a reload which will trigger recovery if needed - match config.load_values() { + match config.all_values() { Ok(values) => { let recovered_keys: Vec = values.keys().cloned().collect(); if recovered_keys.is_empty() { diff --git a/crates/goose/Cargo.toml b/crates/goose/Cargo.toml index f015819b7622..b3617556b037 100644 --- a/crates/goose/Cargo.toml +++ b/crates/goose/Cargo.toml @@ -108,6 +108,7 @@ schemars = { version = "1.0.4", default-features = false, features = ["derive"] insta = "1.43.2" paste = "1.0.0" shellexpand = "3.1.1" +indexmap = "2.12.0" [target.'cfg(target_os = "windows")'.dependencies] diff --git a/crates/goose/src/agents/extension.rs b/crates/goose/src/agents/extension.rs index 284a98cf5b7f..9f1daa6cd279 100644 --- a/crates/goose/src/agents/extension.rs +++ b/crates/goose/src/agents/extension.rs @@ -215,6 +215,8 @@ pub enum ExtensionConfig { Sse { /// The name used to identify this extension name: String, + #[serde(default)] + #[schema(required)] description: String, uri: String, #[serde(default)] @@ -234,6 +236,8 @@ pub enum ExtensionConfig { Stdio { /// The name used to identify this extension name: String, + #[serde(default)] + #[schema(required)] description: String, cmd: String, args: Vec, @@ -252,6 +256,8 @@ pub enum ExtensionConfig { Builtin { /// The name used to identify this extension name: String, + #[serde(default)] + #[schema(required)] description: String, display_name: Option, // needed for the UI timeout: Option, @@ -265,6 +271,8 @@ pub enum ExtensionConfig { Platform { /// The name used to identify this extension name: String, + #[serde(default)] + #[schema(required)] description: String, #[serde(default)] bundled: Option, @@ -276,6 +284,8 @@ pub enum ExtensionConfig { StreamableHttp { /// The name used to identify this extension name: String, + #[serde(default)] + #[schema(required)] description: String, uri: String, #[serde(default)] @@ -297,6 +307,8 @@ pub enum ExtensionConfig { Frontend { /// The name used to identify this extension name: String, + #[serde(default)] + #[schema(required)] description: String, /// The tools provided by the frontend tools: Vec, @@ -312,6 +324,8 @@ pub enum ExtensionConfig { InlinePython { /// The name used to identify this extension name: String, + #[serde(default)] + #[schema(required)] description: String, /// The Python code to execute code: String, diff --git a/crates/goose/src/config/base.rs b/crates/goose/src/config/base.rs index 550695120b92..0ad26428d39b 100644 --- a/crates/goose/src/config/base.rs +++ b/crates/goose/src/config/base.rs @@ -5,6 +5,7 @@ use keyring::Entry; use once_cell::sync::OnceCell; use serde::{Deserialize, Serialize}; use serde_json::Value; +use serde_yaml::Mapping; use std::collections::HashMap; use std::env; use std::fs::OpenOptions; @@ -152,6 +153,10 @@ macro_rules! declare_param { }; } +fn parse_yaml_content(content: &str) -> Result { + serde_yaml::from_str(content).map_err(|e| e.into()) +} + impl Config { /// Get the global configuration instance. /// @@ -204,8 +209,7 @@ impl Config { self.config_path.to_string_lossy().to_string() } - // Load current values from the config file - pub fn load_values(&self) -> Result, ConfigError> { + fn load(&self) -> Result { if self.config_path.exists() { self.load_values_with_recovery() } else { @@ -221,19 +225,27 @@ impl Config { tracing::info!("No backup found, creating default configuration"); // Try to load from init-config.yaml if it exists, otherwise use empty config - let default_config = self - .load_init_config_if_exists() - .unwrap_or_else(|_| HashMap::new()); + let default_config = self.load_init_config_if_exists().unwrap_or_default(); self.create_and_save_default_config(default_config) } } + pub fn all_values(&self) -> Result, ConfigError> { + self.load().map(|m| { + HashMap::from_iter(m.into_iter().filter_map(|(k, v)| { + k.as_str() + .map(|k| k.to_string()) + .zip(serde_json::to_value(v).ok()) + })) + }) + } + // Helper method to create and save default config with consistent logging fn create_and_save_default_config( &self, - default_config: HashMap, - ) -> Result, ConfigError> { + default_config: Mapping, + ) -> Result { // Try to write the default config to disk match self.save_values(default_config.clone()) { Ok(_) => { @@ -255,12 +267,10 @@ impl Config { } } - // Load values with automatic recovery from corruption - fn load_values_with_recovery(&self) -> Result, ConfigError> { + fn load_values_with_recovery(&self) -> Result { let file_content = std::fs::read_to_string(&self.config_path)?; - // First attempt: try to parse the current config - match self.parse_yaml_content(&file_content) { + match parse_yaml_content(&file_content) { Ok(values) => Ok(values), Err(parse_error) => { tracing::warn!( @@ -277,40 +287,21 @@ impl Config { // Last resort: create a fresh default config file tracing::error!("Could not recover config file, creating fresh default configuration. Original error: {}", parse_error); - // Try to load from init-config.yaml if it exists, otherwise use empty config - let default_config = self - .load_init_config_if_exists() - .unwrap_or_else(|_| HashMap::new()); + let default_config = self.load_init_config_if_exists().unwrap_or_default(); self.create_and_save_default_config(default_config) } } } - // Parse YAML content into HashMap - fn parse_yaml_content(&self, content: &str) -> Result, ConfigError> { - if content.trim().is_empty() { - return Ok(HashMap::new()); - } - - let yaml_value: serde_yaml::Value = serde_yaml::from_str(content)?; - let json_value: Value = serde_json::to_value(yaml_value)?; - - match json_value { - Value::Object(map) => Ok(map.into_iter().collect()), - _ => Ok(HashMap::new()), - } - } - - // Try to restore from backup file - fn try_restore_from_backup(&self) -> Result, ConfigError> { + fn try_restore_from_backup(&self) -> Result { let backup_paths = self.get_backup_paths(); for backup_path in backup_paths { if backup_path.exists() { match std::fs::read_to_string(&backup_path) { Ok(backup_content) => { - match self.parse_yaml_content(&backup_content) { + match parse_yaml_content(&backup_content) { Ok(values) => { // Successfully parsed backup, restore it as the main config if let Err(e) = self.save_values(values.clone()) { @@ -370,13 +361,11 @@ impl Config { paths } - // Try to load init-config.yaml from workspace root if it exists - fn load_init_config_if_exists(&self) -> Result, ConfigError> { + fn load_init_config_if_exists(&self) -> Result { load_init_config_from_workspace() } - // Save current values to the config file - pub fn save_values(&self, values: HashMap) -> Result<(), ConfigError> { + fn save_values(&self, values: Mapping) -> Result<(), ConfigError> { // Create backup before writing new config self.create_backup_if_needed()?; @@ -416,6 +405,15 @@ impl Config { Ok(()) } + pub fn initialize_if_empty(&self, values: Mapping) -> Result<(), ConfigError> { + let _guard = self.guard.lock().unwrap(); + if !self.exists() { + self.save_values(values) + } else { + Ok(()) + } + } + // Create backup of current config file if it exists and is valid fn create_backup_if_needed(&self) -> Result<(), ConfigError> { if !self.config_path.exists() { @@ -424,7 +422,7 @@ impl Config { // Check if current config is valid before backing it up let current_content = std::fs::read_to_string(&self.config_path)?; - if self.parse_yaml_content(¤t_content).is_err() { + if parse_yaml_content(¤t_content).is_err() { // Don't back up corrupted files return Ok(()); } @@ -483,8 +481,7 @@ impl Config { Ok(()) } - // Load current secrets from the keyring - pub fn load_secrets(&self) -> Result, ConfigError> { + pub fn all_secrets(&self) -> Result, ConfigError> { match &self.secrets { SecretStorage::Keyring { service } => { let entry = Entry::new(service, KEYRING_USERNAME)?; @@ -585,21 +582,17 @@ impl Config { /// - The value cannot be deserialized into the requested type /// - There is an error reading the config file pub fn get_param Deserialize<'de>>(&self, key: &str) -> Result { - // First check environment variables (convert to uppercase) let env_key = key.to_uppercase(); if let Ok(val) = env::var(&env_key) { let value = Self::parse_env_value(&val)?; return Ok(serde_json::from_value(value)?); } - // Load current values from file - let values = self.load_values()?; - - // Then check our stored values + let values = self.load()?; values .get(key) .ok_or_else(|| ConfigError::NotFound(key.to_string())) - .and_then(|v| Ok(serde_json::from_value(v.clone())?)) + .and_then(|v| Ok(serde_yaml::from_value(v.clone())?)) } /// Set a configuration value in the config file (non-secret). @@ -617,8 +610,8 @@ impl Config { /// - There is an error serializing the value pub fn set_param(&self, key: &str, value: V) -> Result<(), ConfigError> { let _guard = self.guard.lock().unwrap(); - let mut values = self.load_values()?; - values.insert(key.to_string(), serde_json::to_value(&value)?); + let mut values = self.load()?; + values.insert(serde_yaml::to_value(key)?, serde_yaml::to_value(value)?); self.save_values(values) } @@ -639,8 +632,8 @@ impl Config { // Lock before reading to prevent race condition. let _guard = self.guard.lock().unwrap(); - let mut values = self.load_values()?; - values.remove(key); + let mut values = self.load()?; + values.shift_remove(key); self.save_values(values) } @@ -670,7 +663,7 @@ impl Config { } // Then check keyring - let values = self.load_secrets()?; + let values = self.all_secrets()?; values .get(key) .ok_or_else(|| ConfigError::NotFound(key.to_string())) @@ -698,7 +691,7 @@ impl Config { // Lock before reading to prevent race condition. let _guard = self.guard.lock().unwrap(); - let mut values = self.load_secrets()?; + let mut values = self.all_secrets()?; values.insert(key.to_string(), serde_json::to_value(value)?); match &self.secrets { @@ -729,7 +722,7 @@ impl Config { // Lock before reading to prevent race condition. let _guard = self.guard.lock().unwrap(); - let mut values = self.load_secrets()?; + let mut values = self.all_secrets()?; values.remove(key); match &self.secrets { @@ -754,7 +747,7 @@ impl Config { /// Load init-config.yaml from workspace root if it exists. /// This function is shared between the config recovery and the init_config endpoint. -pub fn load_init_config_from_workspace() -> Result, ConfigError> { +pub fn load_init_config_from_workspace() -> Result { let workspace_root = match std::env::current_exe() { Ok(mut exe_path) => { while let Some(parent) = exe_path.parent() { @@ -787,23 +780,7 @@ pub fn load_init_config_from_workspace() -> Result, Confi } let init_content = std::fs::read_to_string(&init_config_path)?; - let init_values: HashMap = - match serde_yaml::from_str::(&init_content) { - Ok(yaml_value) => { - let json_value: Value = serde_json::to_value(yaml_value)?; - match json_value { - Value::Object(map) => map.into_iter().collect(), - _ => HashMap::new(), - } - } - Err(e) => { - tracing::warn!("Failed to parse init-config.yaml: {}", e); - return Err(ConfigError::DeserializeError(e.to_string())); - } - }; - - tracing::info!("Loaded init-config.yaml with {} keys", init_values.len()); - Ok(init_values) + parse_yaml_content(&init_content) } #[cfg(test)] @@ -902,7 +879,7 @@ mod tests { config.set_param("another_key", 42)?; config.set_param("third_key", true)?; - let _values = config.load_values()?; + let _values = config.load()?; let result: Result = config.get_param("key"); assert!(matches!(result, Err(ConfigError::NotFound(_)))); @@ -994,11 +971,11 @@ mod tests { let temp_file = NamedTempFile::new().unwrap(); let config = Arc::new(Config::new(temp_file.path(), TEST_KEYRING_SERVICE)?); let barrier = Arc::new(Barrier::new(3)); // For 3 concurrent threads - let values = Arc::new(Mutex::new(HashMap::new())); + let values = Arc::new(Mutex::new(Mapping::new())); let mut handles = vec![]; // Initialize with empty values - config.save_values(HashMap::new())?; + config.save_values(Default::default())?; // Spawn 3 threads that will try to write simultaneously for i in 0..3 { @@ -1011,7 +988,10 @@ mod tests { // Get the lock and update values let mut values = values.lock().unwrap(); - values.insert(format!("key{}", i), Value::String(format!("value{}", i))); + values.insert( + serde_yaml::to_value(format!("key{}", i)).unwrap(), + serde_yaml::to_value(format!("value{}", i)).unwrap(), + ); // Write all values config.save_values(values.clone())?; @@ -1026,7 +1006,7 @@ mod tests { } // Verify all values were written correctly - let final_values = config.load_values()?; + let final_values = config.all_values()?; // Print the final values for debugging println!("Final values: {:?}", final_values); @@ -1088,7 +1068,7 @@ mod tests { std::fs::write(temp_file.path(), "invalid: yaml: content: [unclosed")?; // Try to load values - should recover from backup - let recovered_values = config.load_values()?; + let recovered_values = config.all_values()?; println!("Recovered values: {:?}", recovered_values); // Should have recovered the data @@ -1109,7 +1089,7 @@ mod tests { std::fs::write(temp_file.path(), "invalid: yaml: content: [unclosed")?; // Try to load values - should create a fresh default config - let recovered_values = config.load_values()?; + let recovered_values = config.all_values()?; // Should return empty config assert_eq!(recovered_values.len(), 0); @@ -1122,7 +1102,7 @@ mod tests { assert!(parsed.is_mapping()); // Should be able to load it again without issues - let reloaded_values = config.load_values()?; + let reloaded_values = config.all_values()?; assert_eq!(reloaded_values.len(), 0); Ok(()) @@ -1140,7 +1120,7 @@ mod tests { let config = Config::new(config_path, TEST_KEYRING_SERVICE)?; // Try to load values - should create a fresh default config file - let values = config.load_values()?; + let values = config.all_values()?; // Should return empty config assert_eq!(values.len(), 0); @@ -1154,7 +1134,7 @@ mod tests { assert!(parsed.is_mapping()); // Should be able to load it again without issues - let reloaded_values = config.load_values()?; + let reloaded_values = config.all_values()?; assert_eq!(reloaded_values.len(), 0); Ok(()) @@ -1183,7 +1163,7 @@ mod tests { assert!(!config_path.exists()); // Try to load values - should recover from backup - let recovered_values = config.load_values()?; + let recovered_values = config.all_values()?; // Should have recovered the data from backup assert!( diff --git a/crates/goose/src/config/extensions.rs b/crates/goose/src/config/extensions.rs index fac3d6f23c67..4ad4e84de300 100644 --- a/crates/goose/src/config/extensions.rs +++ b/crates/goose/src/config/extensions.rs @@ -1,9 +1,9 @@ use super::base::Config; use crate::agents::extension::PLATFORM_EXTENSIONS; use crate::agents::ExtensionConfig; +use indexmap::IndexMap; use serde::{Deserialize, Serialize}; -use serde_json::Value; -use std::collections::HashMap; +use serde_yaml::Mapping; use tracing::warn; use utoipa::ToSchema; @@ -27,56 +27,32 @@ pub fn name_to_key(name: &str) -> String { .to_lowercase() } -fn get_extensions_map() -> HashMap { - let raw: Value = Config::global() - .get_param::(EXTENSIONS_CONFIG_KEY) +fn get_extensions_map() -> IndexMap { + let raw: Mapping = Config::global() + .get_param(EXTENSIONS_CONFIG_KEY) .unwrap_or_else(|err| { warn!( "Failed to load {}: {err}. Falling back to empty object.", EXTENSIONS_CONFIG_KEY ); - Value::Object(serde_json::Map::new()) + Default::default() }); - let mut extensions_map: HashMap = match raw { - Value::Object(obj) => { - let mut m = HashMap::with_capacity(obj.len()); - for (k, mut v) in obj { - if let Value::Object(ref mut inner) = v { - match inner.get("description") { - Some(Value::Null) | None => { - inner.insert("description".to_string(), Value::String(String::new())); - } - _ => {} - } - } - match serde_json::from_value::(v.clone()) { - Ok(entry) => { - m.insert(k, entry); - } - Err(err) => { - let bad_json = serde_json::to_string(&v).unwrap_or_else(|e| { - format!("") - }); - warn!( - extension = %k, - error = %err, - bad_json = %bad_json, - "Skipping malformed extension" - ); - } - } + let mut extensions_map = IndexMap::with_capacity(raw.len()); + for (k, v) in raw { + match (k, serde_yaml::from_value::(v)) { + (serde_yaml::Value::String(s), Ok(entry)) => { + extensions_map.insert(s, entry); + } + (k, v) => { + warn!( + key = ?k, + value = ?v, + "Skipping malformed extension config entry" + ); } - m - } - other => { - warn!( - "Expected object for {}, got {}. Using empty map.", - EXTENSIONS_CONFIG_KEY, other - ); - HashMap::new() } - }; + } if !extensions_map.is_empty() { for (name, def) in PLATFORM_EXTENSIONS.iter() { @@ -99,7 +75,7 @@ fn get_extensions_map() -> HashMap { extensions_map } -fn save_extensions_map(extensions: HashMap) { +fn save_extensions_map(extensions: IndexMap) { let config = Config::global(); if let Err(e) = config.set_param(EXTENSIONS_CONFIG_KEY, &extensions) { // TODO(jack) why is this just a debug statement? @@ -124,7 +100,7 @@ pub fn set_extension(entry: ExtensionEntry) { pub fn remove_extension(key: &str) { let mut extensions = get_extensions_map(); - extensions.remove(key); + extensions.shift_remove(key); save_extensions_map(extensions); } diff --git a/crates/goose/src/providers/bedrock.rs b/crates/goose/src/providers/bedrock.rs index ff5300484316..f6c601b2697a 100644 --- a/crates/goose/src/providers/bedrock.rs +++ b/crates/goose/src/providers/bedrock.rs @@ -61,8 +61,8 @@ impl BedrockProvider { } }; - set_aws_env_vars(config.load_values()); - set_aws_env_vars(config.load_secrets()); + set_aws_env_vars(config.all_values()); + set_aws_env_vars(config.all_secrets()); let sdk_config = aws_config::load_from_env().await; diff --git a/crates/goose/src/providers/sagemaker_tgi.rs b/crates/goose/src/providers/sagemaker_tgi.rs index e26c08eaf7b8..a5210b5b91fa 100644 --- a/crates/goose/src/providers/sagemaker_tgi.rs +++ b/crates/goose/src/providers/sagemaker_tgi.rs @@ -53,8 +53,8 @@ impl SageMakerTgiProvider { } }; - set_aws_env_vars(config.load_values()); - set_aws_env_vars(config.load_secrets()); + set_aws_env_vars(config.all_values()); + set_aws_env_vars(config.all_secrets()); let aws_config = aws_config::load_from_env().await;