Stringly typed config (#5463)
This commit is contained in:
@@ -101,11 +101,11 @@ impl GooseAcpAgent {
|
||||
let config = Config::global();
|
||||
|
||||
let provider_name: String = config
|
||||
.get_param("GOOSE_PROVIDER")
|
||||
.get_goose_provider()
|
||||
.map_err(|e| anyhow::anyhow!("No provider configured: {}", e))?;
|
||||
|
||||
let model_name: String = config
|
||||
.get_param("GOOSE_MODEL")
|
||||
.get_goose_model()
|
||||
.map_err(|e| anyhow::anyhow!("No model configured: {}", e))?;
|
||||
|
||||
let model_config = goose::model::ModelConfig {
|
||||
|
||||
@@ -14,7 +14,8 @@ use goose::config::paths::Paths;
|
||||
use goose::config::permission::PermissionLevel;
|
||||
use goose::config::signup_tetrate::TetrateAuth;
|
||||
use goose::config::{
|
||||
configure_tetrate, Config, ConfigError, ExperimentManager, ExtensionEntry, PermissionManager,
|
||||
configure_tetrate, Config, ConfigError, ExperimentManager, ExtensionEntry, GooseMode,
|
||||
PermissionManager,
|
||||
};
|
||||
use goose::conversation::message::Message;
|
||||
use goose::model::ModelConfig;
|
||||
@@ -421,7 +422,7 @@ fn select_model_from_list(
|
||||
}
|
||||
|
||||
fn try_store_secret(config: &Config, key_name: &str, value: String) -> anyhow::Result<bool> {
|
||||
match config.set_secret(key_name, Value::String(value)) {
|
||||
match config.set_secret(key_name, &value) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(e) => {
|
||||
cliclack::outro(style(format!(
|
||||
@@ -450,7 +451,7 @@ pub async fn configure_provider_dialog() -> anyhow::Result<bool> {
|
||||
.collect();
|
||||
|
||||
// Get current default provider if it exists
|
||||
let current_provider: Option<String> = config.get_param("GOOSE_PROVIDER").ok();
|
||||
let current_provider: Option<String> = config.get_goose_provider().ok();
|
||||
let default_provider = current_provider.unwrap_or_default();
|
||||
|
||||
// Select provider
|
||||
@@ -487,7 +488,7 @@ pub async fn configure_provider_dialog() -> anyhow::Result<bool> {
|
||||
return Ok(false);
|
||||
}
|
||||
} else {
|
||||
config.set_param(&key.name, Value::String(env_value))?;
|
||||
config.set_param(&key.name, &env_value)?;
|
||||
}
|
||||
let _ = cliclack::log::info(format!("Saved {} to {}", key.name, config.path()));
|
||||
}
|
||||
@@ -529,7 +530,7 @@ pub async fn configure_provider_dialog() -> anyhow::Result<bool> {
|
||||
return Ok(false);
|
||||
}
|
||||
} else {
|
||||
config.set_param(&key.name, Value::String(value))?;
|
||||
config.set_param(&key.name, &value)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -558,9 +559,9 @@ pub async fn configure_provider_dialog() -> anyhow::Result<bool> {
|
||||
};
|
||||
|
||||
if key.secret {
|
||||
config.set_secret(&key.name, Value::String(value))?;
|
||||
config.set_secret(&key.name, &value)?;
|
||||
} else {
|
||||
config.set_param(&key.name, Value::String(value))?;
|
||||
config.set_param(&key.name, &value)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -648,9 +649,8 @@ pub async fn configure_provider_dialog() -> anyhow::Result<bool> {
|
||||
|
||||
match result {
|
||||
Ok((_message, _usage)) => {
|
||||
// Update config with new values only if the test succeeds
|
||||
config.set_param("GOOSE_PROVIDER", Value::String(provider_name.to_string()))?;
|
||||
config.set_param("GOOSE_MODEL", Value::String(model.clone()))?;
|
||||
config.set_goose_provider(provider_name)?;
|
||||
config.set_goose_model(&model)?;
|
||||
print_config_file_saved()?;
|
||||
Ok(true)
|
||||
}
|
||||
@@ -877,7 +877,7 @@ pub fn configure_extensions_dialog() -> anyhow::Result<()> {
|
||||
|
||||
// Try to store in keychain
|
||||
let keychain_key = key.to_string();
|
||||
match config.set_secret(&keychain_key, Value::String(value.clone())) {
|
||||
match config.set_secret(&keychain_key, &value) {
|
||||
Ok(_) => {
|
||||
// Successfully stored in keychain, add to env_keys
|
||||
env_keys.push(keychain_key);
|
||||
@@ -973,7 +973,7 @@ pub fn configure_extensions_dialog() -> anyhow::Result<()> {
|
||||
|
||||
// Try to store in keychain
|
||||
let keychain_key = key.to_string();
|
||||
match config.set_secret(&keychain_key, Value::String(value.clone())) {
|
||||
match config.set_secret(&keychain_key, &value) {
|
||||
Ok(_) => {
|
||||
// Successfully stored in keychain, add to env_keys
|
||||
env_keys.push(keychain_key);
|
||||
@@ -1093,7 +1093,7 @@ pub fn configure_extensions_dialog() -> anyhow::Result<()> {
|
||||
|
||||
// Try to store in keychain
|
||||
let keychain_key = key.to_string();
|
||||
match config.set_secret(&keychain_key, Value::String(value.clone())) {
|
||||
match config.set_secret(&keychain_key, &Value::String(value.clone())) {
|
||||
Ok(_) => {
|
||||
// Successfully stored in keychain, add to env_keys
|
||||
env_keys.push(keychain_key);
|
||||
@@ -1273,46 +1273,35 @@ pub fn configure_goose_mode_dialog() -> anyhow::Result<()> {
|
||||
|
||||
let mode = cliclack::select("Which goose mode would you like to configure?")
|
||||
.item(
|
||||
"auto",
|
||||
GooseMode::Auto,
|
||||
"Auto Mode",
|
||||
"Full file modification, extension usage, edit, create and delete files freely"
|
||||
)
|
||||
.item(
|
||||
"approve",
|
||||
GooseMode::Approve,
|
||||
"Approve Mode",
|
||||
"All tools, extensions and file modifications will require human approval"
|
||||
)
|
||||
.item(
|
||||
"smart_approve",
|
||||
GooseMode::SmartApprove,
|
||||
"Smart Approve Mode",
|
||||
"Editing, creating, deleting files and using extensions will require human approval"
|
||||
)
|
||||
.item(
|
||||
"chat",
|
||||
GooseMode::Chat,
|
||||
"Chat Mode",
|
||||
"Engage with the selected provider without using tools, extensions, or file modification"
|
||||
)
|
||||
.interact()?;
|
||||
|
||||
match mode {
|
||||
"auto" => {
|
||||
config.set_param("GOOSE_MODE", Value::String("auto".to_string()))?;
|
||||
cliclack::outro("Set to Auto Mode - full file modification enabled")?;
|
||||
}
|
||||
"approve" => {
|
||||
config.set_param("GOOSE_MODE", Value::String("approve".to_string()))?;
|
||||
cliclack::outro("Set to Approve Mode - all tools and modifications require approval")?;
|
||||
}
|
||||
"smart_approve" => {
|
||||
config.set_param("GOOSE_MODE", Value::String("smart_approve".to_string()))?;
|
||||
cliclack::outro("Set to Smart Approve Mode - modifications require approval")?;
|
||||
}
|
||||
"chat" => {
|
||||
config.set_param("GOOSE_MODE", Value::String("chat".to_string()))?;
|
||||
cliclack::outro("Set to Chat Mode - no tools or modifications enabled")?;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
config.set_goose_mode(mode)?;
|
||||
let msg = match mode {
|
||||
GooseMode::Auto => "Set to Auto Mode - full file modification enabled",
|
||||
GooseMode::Approve => "Set to Approve Mode - all tools and modifications require approval",
|
||||
GooseMode::SmartApprove => "Set to Smart Approve Mode - modifications require approval",
|
||||
GooseMode::Chat => "Set to Chat Mode - no tools or modifications enabled",
|
||||
};
|
||||
cliclack::outro(msg)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1321,28 +1310,25 @@ pub fn configure_goose_router_strategy_dialog() -> anyhow::Result<()> {
|
||||
|
||||
let enable_router = cliclack::select("Would you like to enable smart tool routing?")
|
||||
.item(
|
||||
"true",
|
||||
true,
|
||||
"Enable Router",
|
||||
"Use LLM-based intelligence to select tools",
|
||||
)
|
||||
.item(
|
||||
"false",
|
||||
false,
|
||||
"Disable Router",
|
||||
"Use the default tool selection strategy",
|
||||
)
|
||||
.interact()?;
|
||||
|
||||
match enable_router {
|
||||
"true" => {
|
||||
config.set_param("GOOSE_ENABLE_ROUTER", Value::String("true".to_string()))?;
|
||||
cliclack::outro("Router enabled - using LLM-based intelligence for tool selection")?;
|
||||
}
|
||||
"false" => {
|
||||
config.set_param("GOOSE_ENABLE_ROUTER", Value::String("false".to_string()))?;
|
||||
cliclack::outro("Router disabled - using default tool selection")?;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
config.set_param("GOOSE_ENABLE_ROUTER", enable_router)?;
|
||||
let msg = if enable_router {
|
||||
"Router enabled - using LLM-based intelligence for tool selection"
|
||||
} else {
|
||||
"Router disabled - using default tool selection"
|
||||
};
|
||||
cliclack::outro(msg)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1360,15 +1346,15 @@ pub fn configure_tool_output_dialog() -> anyhow::Result<()> {
|
||||
|
||||
match tool_log_level {
|
||||
"high" => {
|
||||
config.set_param("GOOSE_CLI_MIN_PRIORITY", Value::from(0.8))?;
|
||||
config.set_param("GOOSE_CLI_MIN_PRIORITY", 0.8)?;
|
||||
cliclack::outro("Showing tool output of high importance only.")?;
|
||||
}
|
||||
"medium" => {
|
||||
config.set_param("GOOSE_CLI_MIN_PRIORITY", Value::from(0.2))?;
|
||||
config.set_param("GOOSE_CLI_MIN_PRIORITY", 0.2)?;
|
||||
cliclack::outro("Showing tool output of medium importance.")?;
|
||||
}
|
||||
"all" => {
|
||||
config.set_param("GOOSE_CLI_MIN_PRIORITY", Value::from(0.0))?;
|
||||
config.set_param("GOOSE_CLI_MIN_PRIORITY", 0.0)?;
|
||||
cliclack::outro("Showing all tool output.")?;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@@ -1441,11 +1427,11 @@ pub async fn configure_tool_permissions_dialog() -> anyhow::Result<()> {
|
||||
let config = Config::global();
|
||||
|
||||
let provider_name: String = config
|
||||
.get_param("GOOSE_PROVIDER")
|
||||
.get_goose_provider()
|
||||
.expect("No provider configured. Please set model provider first");
|
||||
|
||||
let model: String = config
|
||||
.get_param("GOOSE_MODEL")
|
||||
.get_goose_model()
|
||||
.expect("No model configured. Please set model first");
|
||||
let model_config = ModelConfig::new(&model)?;
|
||||
|
||||
@@ -1591,7 +1577,7 @@ fn configure_recipe_dialog() -> anyhow::Result<()> {
|
||||
if input_value.clone().trim().is_empty() {
|
||||
config.delete(key_name)?;
|
||||
} else {
|
||||
config.set_param(key_name, Value::String(input_value))?;
|
||||
config.set_param(key_name, &input_value)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1618,7 +1604,7 @@ pub fn configure_max_turns_dialog() -> anyhow::Result<()> {
|
||||
.interact()?;
|
||||
|
||||
let max_turns: u32 = max_turns_input.parse()?;
|
||||
config.set_param("GOOSE_MAX_TURNS", Value::from(max_turns))?;
|
||||
config.set_param("GOOSE_MAX_TURNS", max_turns)?;
|
||||
|
||||
cliclack::outro(format!(
|
||||
"Set maximum turns to {} - goose will ask for input after {} consecutive actions",
|
||||
@@ -1651,7 +1637,7 @@ pub async fn handle_openrouter_auth() -> anyhow::Result<()> {
|
||||
|
||||
// Test configuration - get the model that was configured
|
||||
println!("\nTesting configuration...");
|
||||
let configured_model: String = config.get_param("GOOSE_MODEL")?;
|
||||
let configured_model: String = config.get_goose_model()?;
|
||||
let model_config = match goose::model::ModelConfig::new(&configured_model) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
@@ -1729,7 +1715,7 @@ pub async fn handle_tetrate_auth() -> anyhow::Result<()> {
|
||||
|
||||
// Test configuration
|
||||
println!("\nTesting configuration...");
|
||||
let configured_model: String = config.get_param("GOOSE_MODEL")?;
|
||||
let configured_model: String = config.get_goose_model()?;
|
||||
let model_config = match goose::model::ModelConfig::new(&configured_model) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
|
||||
@@ -139,7 +139,7 @@ pub async fn handle_web(
|
||||
|
||||
let config = goose::config::Config::global();
|
||||
|
||||
let provider_name: String = match config.get_param("GOOSE_PROVIDER") {
|
||||
let provider_name: String = match config.get_goose_provider() {
|
||||
Ok(p) => p,
|
||||
Err(_) => {
|
||||
eprintln!("No provider configured. Run 'goose configure' first");
|
||||
@@ -147,7 +147,7 @@ pub async fn handle_web(
|
||||
}
|
||||
};
|
||||
|
||||
let model: String = match config.get_param("GOOSE_MODEL") {
|
||||
let model: String = match config.get_goose_model() {
|
||||
Ok(m) => m,
|
||||
Err(_) => {
|
||||
eprintln!("No model configured. Run 'goose configure' first");
|
||||
|
||||
@@ -11,7 +11,6 @@ use goose::recipe::build_recipe::{
|
||||
};
|
||||
use goose::recipe::validate_recipe::parse_and_validate_parameters;
|
||||
use goose::recipe::Recipe;
|
||||
use serde_json::Value;
|
||||
|
||||
fn create_user_prompt_callback() -> impl Fn(&str, &str) -> Result<String> {
|
||||
|key: &str, description: &str| -> Result<String> {
|
||||
@@ -98,7 +97,7 @@ pub fn collect_missing_secrets(requirements: &[SecretRequirement]) -> Result<()>
|
||||
.unwrap_or_else(|_| String::new());
|
||||
|
||||
if !value.trim().is_empty() {
|
||||
config.set_secret(&req.key, Value::String(value))?;
|
||||
config.set_secret(&req.key, &value)?;
|
||||
println!("✅ Secret stored securely for {}", req.extension_name);
|
||||
} else {
|
||||
println!("⏭️ Skipped {} for {}", req.key, req.extension_name);
|
||||
|
||||
@@ -208,7 +208,7 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> CliSession {
|
||||
.as_ref()
|
||||
.and_then(|s| s.goose_provider.clone())
|
||||
})
|
||||
.or_else(|| config.get_param("GOOSE_PROVIDER").ok())
|
||||
.or_else(|| config.get_goose_provider().ok())
|
||||
.expect("No provider configured. Run 'goose configure' first");
|
||||
|
||||
let model_name = session_config
|
||||
@@ -219,7 +219,7 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> CliSession {
|
||||
.as_ref()
|
||||
.and_then(|s| s.goose_model.clone())
|
||||
})
|
||||
.or_else(|| config.get_param("GOOSE_MODEL").ok())
|
||||
.or_else(|| config.get_goose_model().ok())
|
||||
.expect("No model configured. Run 'goose configure' first");
|
||||
|
||||
let temperature = session_config.settings.as_ref().and_then(|s| s.temperature);
|
||||
|
||||
@@ -12,6 +12,7 @@ use crate::session::task_execution_display::{
|
||||
};
|
||||
use goose::conversation::Conversation;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub use self::export::message_to_markdown;
|
||||
pub use builder::{build_session, SessionBuilderConfig, SessionSettings};
|
||||
@@ -28,7 +29,7 @@ use completion::GooseCompleter;
|
||||
use goose::agents::extension::{Envs, ExtensionConfig};
|
||||
use goose::agents::types::RetryConfig;
|
||||
use goose::agents::{Agent, SessionConfig};
|
||||
use goose::config::Config;
|
||||
use goose::config::{Config, GooseMode};
|
||||
use goose::providers::pricing::initialize_pricing_cache;
|
||||
use goose::session::SessionManager;
|
||||
use input::InputResult;
|
||||
@@ -545,21 +546,18 @@ impl CliSession {
|
||||
save_history(&mut editor);
|
||||
|
||||
let config = Config::global();
|
||||
let mode = mode.to_lowercase();
|
||||
|
||||
// Check if mode is valid
|
||||
if !["auto", "approve", "chat", "smart_approve"].contains(&mode.as_str()) {
|
||||
output::render_error(&format!(
|
||||
"Invalid mode '{}'. Mode must be one of: auto, approve, chat",
|
||||
mode
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
config
|
||||
.set_param("GOOSE_MODE", Value::String(mode.to_string()))
|
||||
.unwrap();
|
||||
output::goose_mode_message(&format!("Goose mode set to '{}'", mode));
|
||||
let mode = match GooseMode::from_str(&mode.to_lowercase()) {
|
||||
Ok(mode) => mode,
|
||||
Err(_) => {
|
||||
output::render_error(&format!(
|
||||
"Invalid mode '{}'. Mode must be one of: auto, approve, chat, smart_approve",
|
||||
mode
|
||||
));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
config.set_goose_mode(mode)?;
|
||||
output::goose_mode_message(&format!("Goose mode set to '{:?}'", mode));
|
||||
continue;
|
||||
}
|
||||
input::InputResult::Plan(options) => {
|
||||
@@ -787,12 +785,9 @@ impl CliSession {
|
||||
self.run_mode = RunMode::Normal;
|
||||
// set goose mode: auto if that isn't already the case
|
||||
let config = Config::global();
|
||||
let curr_goose_mode =
|
||||
config.get_param("GOOSE_MODE").unwrap_or("auto".to_string());
|
||||
if curr_goose_mode != "auto" {
|
||||
config
|
||||
.set_param("GOOSE_MODE", Value::String("auto".to_string()))
|
||||
.unwrap();
|
||||
let curr_goose_mode = config.get_goose_mode().unwrap_or(GooseMode::Auto);
|
||||
if curr_goose_mode != GooseMode::Auto {
|
||||
config.set_goose_mode(GooseMode::Auto).unwrap();
|
||||
}
|
||||
|
||||
// clear the messages before acting on the plan
|
||||
@@ -807,10 +802,8 @@ impl CliSession {
|
||||
output::hide_thinking();
|
||||
|
||||
// Reset run & goose mode
|
||||
if curr_goose_mode != "auto" {
|
||||
config
|
||||
.set_param("GOOSE_MODE", Value::String(curr_goose_mode.to_string()))
|
||||
.unwrap();
|
||||
if curr_goose_mode != GooseMode::Auto {
|
||||
config.set_goose_mode(curr_goose_mode)?;
|
||||
}
|
||||
} else {
|
||||
// add the plan response (assistant message) & carry the conversation forward
|
||||
@@ -1324,7 +1317,7 @@ impl CliSession {
|
||||
.unwrap_or(false);
|
||||
|
||||
let provider_name = config
|
||||
.get_param::<String>("GOOSE_PROVIDER")
|
||||
.get_goose_provider()
|
||||
.unwrap_or_else(|_| "unknown".to_string());
|
||||
|
||||
// Do not get costing information if show cost is disabled
|
||||
@@ -1488,7 +1481,7 @@ async fn get_reasoner() -> Result<Arc<dyn Provider>, anyhow::Error> {
|
||||
} else {
|
||||
println!("WARNING: GOOSE_PLANNER_PROVIDER not found. Using default provider...");
|
||||
config
|
||||
.get_param::<String>("GOOSE_PROVIDER")
|
||||
.get_goose_provider()
|
||||
.expect("No provider configured. Run 'goose configure' first")
|
||||
};
|
||||
|
||||
@@ -1498,7 +1491,7 @@ async fn get_reasoner() -> Result<Arc<dyn Provider>, anyhow::Error> {
|
||||
} else {
|
||||
println!("WARNING: GOOSE_PLANNER_MODEL not found. Using default model...");
|
||||
config
|
||||
.get_param::<String>("GOOSE_MODEL")
|
||||
.get_goose_model()
|
||||
.expect("No model configured. Run 'goose configure' first")
|
||||
};
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ thread_local! {
|
||||
pub fn set_theme(theme: Theme) {
|
||||
let config = Config::global();
|
||||
config
|
||||
.set_param("GOOSE_CLI_THEME", Value::String(theme.as_config_string()))
|
||||
.set_param("GOOSE_CLI_THEME", theme.as_config_string())
|
||||
.expect("Failed to set theme");
|
||||
CURRENT_THEME.with(|t| *t.borrow_mut() = theme);
|
||||
|
||||
@@ -79,7 +79,7 @@ pub fn set_theme(theme: Theme) {
|
||||
Theme::Ansi => "ansi",
|
||||
};
|
||||
|
||||
if let Err(e) = config.set_param("GOOSE_CLI_THEME", Value::String(theme_str.to_string())) {
|
||||
if let Err(e) = config.set_param("GOOSE_CLI_THEME", theme_str) {
|
||||
eprintln!("Failed to save theme setting to config: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user