Persist dynamic extension config so we can resume recipe sessions w/ extensions (#4331)
This commit is contained in:
@@ -4,7 +4,7 @@ use agent_client_protocol::{
|
||||
};
|
||||
use anyhow::Result;
|
||||
use goose::agents::Agent;
|
||||
use goose::config::{Config, ExtensionConfigManager};
|
||||
use goose::config::{get_all_extensions, Config};
|
||||
use goose::conversation::message::{Message, MessageContent};
|
||||
use goose::conversation::Conversation;
|
||||
use goose::providers::create;
|
||||
@@ -124,8 +124,7 @@ impl GooseAcpAgent {
|
||||
agent.update_provider(provider.clone()).await?;
|
||||
|
||||
// Load and add extensions just like the normal CLI
|
||||
let extensions_to_run: Vec<_> = ExtensionConfigManager::get_all()
|
||||
.map_err(|e| anyhow::anyhow!("Failed to load extensions: {}", e))?
|
||||
let extensions_to_run: Vec<_> = get_all_extensions()
|
||||
.into_iter()
|
||||
.filter(|ext| ext.enabled)
|
||||
.map(|ext| ext.config)
|
||||
|
||||
@@ -9,12 +9,12 @@ use goose::agents::platform_tools::{
|
||||
use goose::agents::Agent;
|
||||
use goose::agents::{extension::Envs, ExtensionConfig};
|
||||
use goose::config::custom_providers::CustomProviderConfig;
|
||||
use goose::config::extensions::name_to_key;
|
||||
use goose::config::permission::PermissionLevel;
|
||||
use goose::config::{
|
||||
Config, ConfigError, ExperimentManager, ExtensionConfigManager, ExtensionEntry,
|
||||
PermissionManager,
|
||||
use goose::config::extensions::{
|
||||
get_all_extension_names, get_all_extensions, get_enabled_extensions, get_extension_by_name,
|
||||
name_to_key, remove_extension, set_extension, set_extension_enabled,
|
||||
};
|
||||
use goose::config::permission::PermissionLevel;
|
||||
use goose::config::{Config, ConfigError, ExperimentManager, ExtensionEntry, PermissionManager};
|
||||
use goose::conversation::message::Message;
|
||||
use goose::model::ModelConfig;
|
||||
use goose::providers::{create, providers};
|
||||
@@ -105,10 +105,10 @@ pub async fn handle_configure() -> Result<(), Box<dyn Error>> {
|
||||
);
|
||||
// Since we are setting up for the first time, we'll also enable the developer system
|
||||
// This operation is best-effort and errors are ignored
|
||||
ExtensionConfigManager::set(ExtensionEntry {
|
||||
set_extension(ExtensionEntry {
|
||||
enabled: true,
|
||||
config: ExtensionConfig::default(),
|
||||
})?;
|
||||
});
|
||||
}
|
||||
Ok(false) => {
|
||||
let _ = config.clear();
|
||||
@@ -641,7 +641,7 @@ pub async fn configure_provider_dialog() -> Result<bool, Box<dyn Error>> {
|
||||
/// Configure extensions that can be used with goose
|
||||
/// Dialog for toggling which extensions are enabled/disabled
|
||||
pub fn toggle_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
let extensions = ExtensionConfigManager::get_all()?;
|
||||
let extensions = get_all_extensions();
|
||||
|
||||
if extensions.is_empty() {
|
||||
cliclack::outro(
|
||||
@@ -682,10 +682,10 @@ pub fn toggle_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
// Update enabled status for each extension
|
||||
for name in extension_status.iter().map(|(name, _)| name) {
|
||||
ExtensionConfigManager::set_enabled(
|
||||
set_extension_enabled(
|
||||
&name_to_key(name),
|
||||
selected.iter().any(|s| s.as_str() == name),
|
||||
)?;
|
||||
);
|
||||
}
|
||||
|
||||
cliclack::outro("Extension settings updated successfully")?;
|
||||
@@ -768,7 +768,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
.map(|(_, name, desc)| (name.to_string(), desc.to_string()))
|
||||
.unwrap_or_else(|| (extension.clone(), extension.clone()));
|
||||
|
||||
ExtensionConfigManager::set(ExtensionEntry {
|
||||
set_extension(ExtensionEntry {
|
||||
enabled: true,
|
||||
config: ExtensionConfig::Builtin {
|
||||
name: extension.clone(),
|
||||
@@ -778,12 +778,12 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
description,
|
||||
available_tools: Vec::new(),
|
||||
},
|
||||
})?;
|
||||
});
|
||||
|
||||
cliclack::outro(format!("Enabled {} extension", style(extension).green()))?;
|
||||
}
|
||||
"stdio" => {
|
||||
let extensions = ExtensionConfigManager::get_all_names()?;
|
||||
let extensions = get_all_extension_names();
|
||||
let name: String = cliclack::input("What would you like to call this extension?")
|
||||
.placeholder("my-extension")
|
||||
.validate(move |input: &String| {
|
||||
@@ -866,7 +866,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionConfigManager::set(ExtensionEntry {
|
||||
set_extension(ExtensionEntry {
|
||||
enabled: true,
|
||||
config: ExtensionConfig::Stdio {
|
||||
name: name.clone(),
|
||||
@@ -879,12 +879,12 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
bundled: None,
|
||||
available_tools: Vec::new(),
|
||||
},
|
||||
})?;
|
||||
});
|
||||
|
||||
cliclack::outro(format!("Added {} extension", style(name).green()))?;
|
||||
}
|
||||
"sse" => {
|
||||
let extensions = ExtensionConfigManager::get_all_names()?;
|
||||
let extensions = get_all_extension_names();
|
||||
let name: String = cliclack::input("What would you like to call this extension?")
|
||||
.placeholder("my-remote-extension")
|
||||
.validate(move |input: &String| {
|
||||
@@ -962,7 +962,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionConfigManager::set(ExtensionEntry {
|
||||
set_extension(ExtensionEntry {
|
||||
enabled: true,
|
||||
config: ExtensionConfig::Sse {
|
||||
name: name.clone(),
|
||||
@@ -974,12 +974,12 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
bundled: None,
|
||||
available_tools: Vec::new(),
|
||||
},
|
||||
})?;
|
||||
});
|
||||
|
||||
cliclack::outro(format!("Added {} extension", style(name).green()))?;
|
||||
}
|
||||
"streamable_http" => {
|
||||
let extensions = ExtensionConfigManager::get_all_names()?;
|
||||
let extensions = get_all_extension_names();
|
||||
let name: String = cliclack::input("What would you like to call this extension?")
|
||||
.placeholder("my-remote-extension")
|
||||
.validate(move |input: &String| {
|
||||
@@ -1082,7 +1082,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionConfigManager::set(ExtensionEntry {
|
||||
set_extension(ExtensionEntry {
|
||||
enabled: true,
|
||||
config: ExtensionConfig::StreamableHttp {
|
||||
name: name.clone(),
|
||||
@@ -1095,7 +1095,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
bundled: None,
|
||||
available_tools: Vec::new(),
|
||||
},
|
||||
})?;
|
||||
});
|
||||
|
||||
cliclack::outro(format!("Added {} extension", style(name).green()))?;
|
||||
}
|
||||
@@ -1106,7 +1106,7 @@ pub fn configure_extensions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
|
||||
pub fn remove_extension_dialog() -> Result<(), Box<dyn Error>> {
|
||||
let extensions = ExtensionConfigManager::get_all()?;
|
||||
let extensions = get_all_extensions();
|
||||
|
||||
// Create a list of extension names and their enabled status
|
||||
let mut extension_status: Vec<(String, bool)> = extensions
|
||||
@@ -1151,7 +1151,7 @@ pub fn remove_extension_dialog() -> Result<(), Box<dyn Error>> {
|
||||
.interact()?;
|
||||
|
||||
for name in selected {
|
||||
ExtensionConfigManager::remove(&name_to_key(name))?;
|
||||
remove_extension(&name_to_key(name));
|
||||
let mut permission_manager = PermissionManager::default();
|
||||
permission_manager.remove_extension(&name_to_key(name));
|
||||
cliclack::outro(format!("Removed {} extension", style(name).green()))?;
|
||||
@@ -1386,11 +1386,9 @@ pub fn toggle_experiments_dialog() -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
|
||||
pub async fn configure_tool_permissions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
let mut extensions: Vec<String> = ExtensionConfigManager::get_all()
|
||||
.unwrap_or_default()
|
||||
let mut extensions: Vec<String> = get_enabled_extensions()
|
||||
.into_iter()
|
||||
.filter(|ext| ext.enabled)
|
||||
.map(|ext| ext.config.name().clone())
|
||||
.map(|ext| ext.name().clone())
|
||||
.collect();
|
||||
extensions.push("platform".to_string());
|
||||
|
||||
@@ -1423,7 +1421,7 @@ pub async fn configure_tool_permissions_dialog() -> Result<(), Box<dyn Error>> {
|
||||
let agent = Agent::new();
|
||||
let new_provider = create(&provider_name, model_config)?;
|
||||
agent.update_provider(new_provider).await?;
|
||||
if let Ok(Some(config)) = ExtensionConfigManager::get_config_by_name(&selected_extension_name) {
|
||||
if let Some(config) = get_extension_by_name(&selected_extension_name) {
|
||||
agent
|
||||
.add_extension(config.clone())
|
||||
.await
|
||||
@@ -1706,13 +1704,13 @@ pub async fn handle_openrouter_auth() -> Result<(), Box<dyn Error>> {
|
||||
println!("✓ Configuration test passed!");
|
||||
|
||||
// Enable the developer extension by default if not already enabled
|
||||
let entries = ExtensionConfigManager::get_all()?;
|
||||
let entries = get_all_extensions();
|
||||
let has_developer = entries
|
||||
.iter()
|
||||
.any(|e| e.config.name() == "developer" && e.enabled);
|
||||
|
||||
if !has_developer {
|
||||
match ExtensionConfigManager::set(ExtensionEntry {
|
||||
set_extension(ExtensionEntry {
|
||||
enabled: true,
|
||||
config: ExtensionConfig::Builtin {
|
||||
name: "developer".to_string(),
|
||||
@@ -1724,12 +1722,8 @@ pub async fn handle_openrouter_auth() -> Result<(), Box<dyn Error>> {
|
||||
description: "Developer extension".to_string(),
|
||||
available_tools: Vec::new(),
|
||||
},
|
||||
}) {
|
||||
Ok(_) => println!("✓ Developer extension enabled"),
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Failed to enable developer extension: {}", e)
|
||||
}
|
||||
}
|
||||
});
|
||||
println!("✓ Developer extension enabled");
|
||||
}
|
||||
|
||||
cliclack::outro("OpenRouter setup complete! You can now use goose.")?;
|
||||
@@ -1809,13 +1803,13 @@ pub async fn handle_tetrate_auth() -> Result<(), Box<dyn Error>> {
|
||||
println!("✓ Configuration test passed!");
|
||||
|
||||
// Enable the developer extension by default if not already enabled
|
||||
let entries = ExtensionConfigManager::get_all()?;
|
||||
let entries = get_all_extensions();
|
||||
let has_developer = entries
|
||||
.iter()
|
||||
.any(|e| e.config.name() == "developer" && e.enabled);
|
||||
|
||||
if !has_developer {
|
||||
match ExtensionConfigManager::set(ExtensionEntry {
|
||||
set_extension(ExtensionEntry {
|
||||
enabled: true,
|
||||
config: ExtensionConfig::Builtin {
|
||||
name: "developer".to_string(),
|
||||
@@ -1827,12 +1821,8 @@ pub async fn handle_tetrate_auth() -> Result<(), Box<dyn Error>> {
|
||||
description: "Developer extension".to_string(),
|
||||
available_tools: Vec::new(),
|
||||
},
|
||||
}) {
|
||||
Ok(_) => println!("✓ Developer extension enabled"),
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Failed to enable developer extension: {}", e)
|
||||
}
|
||||
}
|
||||
});
|
||||
println!("✓ Developer extension enabled");
|
||||
}
|
||||
|
||||
cliclack::outro("Tetrate Agent Router Service setup complete! You can now use goose.")?;
|
||||
|
||||
@@ -164,16 +164,10 @@ pub async fn handle_web(
|
||||
agent.update_provider(provider).await?;
|
||||
|
||||
// Load and enable extensions from config
|
||||
let extensions = goose::config::ExtensionConfigManager::get_all()?;
|
||||
for ext_config in extensions {
|
||||
if ext_config.enabled {
|
||||
if let Err(e) = agent.add_extension(ext_config.config.clone()).await {
|
||||
eprintln!(
|
||||
"Warning: Failed to load extension {}: {}",
|
||||
ext_config.config.name(),
|
||||
e
|
||||
);
|
||||
}
|
||||
let enabled_configs = goose::config::get_enabled_extensions();
|
||||
for config in enabled_configs {
|
||||
if let Err(e) = agent.add_extension(config.clone()).await {
|
||||
eprintln!("Warning: Failed to load extension {}: {}", config.name(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user