move global config access out of ModelConfig, and move ModelConfig into goose_providers (#9769)
This commit is contained in:
@@ -19,13 +19,13 @@ use goose::config::{
|
||||
configure_tetrate, Config, ConfigError, ExperimentManager, ExtensionEntry, GooseMode,
|
||||
PermissionManager,
|
||||
};
|
||||
use goose::model::ModelConfig;
|
||||
#[cfg(feature = "telemetry")]
|
||||
use goose::posthog::{get_telemetry_choice, TELEMETRY_ENABLED_KEY};
|
||||
use goose::providers::base::ConfigKey;
|
||||
use goose::providers::provider_test::test_provider_configuration;
|
||||
use goose::providers::{create, providers, retry_operation, RetryConfig};
|
||||
use goose::session::SessionType;
|
||||
use goose_providers::thinking::ThinkingEffort;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::io::IsTerminal;
|
||||
@@ -339,7 +339,7 @@ async fn handle_oauth_configuration(provider_name: &str, key_name: &str) -> anyh
|
||||
));
|
||||
|
||||
// Create a temporary provider instance to handle OAuth
|
||||
let temp_model = ModelConfig::new("temp")?.with_canonical_limits(provider_name);
|
||||
let temp_model = goose::model_config::model_config_from_user_config(provider_name, "temp")?;
|
||||
match create(provider_name, temp_model, Vec::new()).await {
|
||||
Ok(provider) => match provider.configure_oauth().await {
|
||||
Ok(_) => {
|
||||
@@ -736,8 +736,10 @@ pub async fn configure_provider_dialog() -> anyhow::Result<bool> {
|
||||
|
||||
let spin = spinner();
|
||||
spin.start("Attempting to fetch supported models...");
|
||||
let temp_model_config =
|
||||
ModelConfig::new(&provider_meta.default_model)?.with_canonical_limits(provider_name);
|
||||
let temp_model_config = goose::model_config::model_config_from_user_config(
|
||||
provider_name,
|
||||
&provider_meta.default_model,
|
||||
)?;
|
||||
let temp_provider = create(provider_name, temp_model_config, Vec::new()).await?;
|
||||
let models_res = retry_operation(&RetryConfig::default(), || async {
|
||||
temp_provider.fetch_recommended_models().await
|
||||
@@ -765,20 +767,22 @@ pub async fn configure_provider_dialog() -> anyhow::Result<bool> {
|
||||
{
|
||||
let supports_thinking = match temp_provider.fetch_model_info(&model).await {
|
||||
Ok(model_info) => model_info.reasoning,
|
||||
Err(_) => goose::model::ModelConfig::new(&model)
|
||||
Err(_) => goose_providers::model::ModelConfig::new(&model)
|
||||
.map(|c| c.is_reasoning_model())
|
||||
.unwrap_or(false),
|
||||
};
|
||||
|
||||
if supports_thinking {
|
||||
let effort: &str = cliclack::select("Select thinking effort:")
|
||||
let effort: ThinkingEffort = cliclack::select("Select thinking effort:")
|
||||
.item("off", "Off - No extended thinking", "")
|
||||
.item("low", "Low - Better latency, lighter reasoning", "")
|
||||
.item("medium", "Medium - Moderate thinking", "")
|
||||
.item("high", "High - Deep reasoning", "")
|
||||
.item("max", "Max - No constraints on thinking depth", "")
|
||||
.initial_value("off")
|
||||
.interact()?;
|
||||
.interact()?
|
||||
.parse()
|
||||
.map_err(|_| anyhow::anyhow!("invalid thinking effort"))?;
|
||||
config.set_goose_thinking_effort(effort)?;
|
||||
}
|
||||
}
|
||||
@@ -1552,7 +1556,7 @@ pub async fn configure_tool_permissions_dialog() -> anyhow::Result<()> {
|
||||
let model: String = config
|
||||
.get_goose_model()
|
||||
.expect("No model configured. Please set model first");
|
||||
let model_config = ModelConfig::new(&model)?.with_canonical_limits(&provider_name);
|
||||
let model_config = goose::model_config::model_config_from_user_config(&provider_name, &model)?;
|
||||
|
||||
let agent = Agent::new();
|
||||
|
||||
@@ -1772,14 +1776,15 @@ 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_goose_model()?;
|
||||
let model_config = match goose::model::ModelConfig::new(&configured_model) {
|
||||
Ok(config) => config.with_canonical_limits("openrouter"),
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Invalid model configuration: {}", e);
|
||||
eprintln!("Your settings have been saved. Please check your model configuration.");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let model_config =
|
||||
match goose::model_config::model_config_from_user_config("openrouter", &configured_model) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Invalid model configuration: {}", e);
|
||||
eprintln!("Your settings have been saved. Please check your model configuration.");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
match create("openrouter", model_config, Vec::new()).await {
|
||||
Ok(provider) => {
|
||||
@@ -1853,14 +1858,15 @@ pub async fn handle_tetrate_auth() -> anyhow::Result<()> {
|
||||
// Test configuration
|
||||
println!("\nTesting configuration...");
|
||||
let configured_model: String = config.get_goose_model()?;
|
||||
let model_config = match goose::model::ModelConfig::new(&configured_model) {
|
||||
Ok(config) => config.with_canonical_limits("tetrate"),
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Invalid model configuration: {}", e);
|
||||
eprintln!("Your settings have been saved. Please check your model configuration.");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
let model_config =
|
||||
match goose::model_config::model_config_from_user_config("tetrate", &configured_model) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
eprintln!("⚠️ Invalid model configuration: {}", e);
|
||||
eprintln!("Your settings have been saved. Please check your model configuration.");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
match create("tetrate", model_config, Vec::new()).await {
|
||||
Ok(provider) => {
|
||||
|
||||
@@ -73,9 +73,8 @@ async fn check_provider(
|
||||
}
|
||||
};
|
||||
|
||||
let model_config = goose::model::ModelConfig::new(&model)
|
||||
.map_err(|e| ProviderCheckError::InvalidModel(e.to_string()))?
|
||||
.with_canonical_limits(&provider);
|
||||
let model_config = goose::model_config::model_config_from_user_config(&provider, &model)
|
||||
.map_err(|e| ProviderCheckError::InvalidModel(e.to_string()))?;
|
||||
|
||||
let provider_client = goose::providers::create(&provider, model_config, Vec::new())
|
||||
.await
|
||||
|
||||
@@ -345,9 +345,7 @@ pub async fn handle_term_info() -> Result<()> {
|
||||
.ok()
|
||||
.and_then(|model_name| {
|
||||
config.get_goose_provider().ok().and_then(|provider_name| {
|
||||
goose::model::ModelConfig::new(&model_name)
|
||||
.ok()
|
||||
.map(|c| c.with_canonical_limits(&provider_name))
|
||||
goose::model_config::model_config_from_user_config(&provider_name, &model_name).ok()
|
||||
})
|
||||
})
|
||||
.map(|mc| mc.context_limit())
|
||||
|
||||
@@ -9,7 +9,6 @@ use anyhow::Result;
|
||||
use goose::agents::{Agent, AgentConfig, GoosePlatform};
|
||||
use goose::config::permission::PermissionManager;
|
||||
use goose::config::GooseMode;
|
||||
use goose::model::ModelConfig;
|
||||
use goose::providers::{create, testprovider::TestProvider};
|
||||
use goose::session::session_manager::SessionType;
|
||||
use goose::session::SessionManager;
|
||||
@@ -188,7 +187,7 @@ where
|
||||
|
||||
let inner_provider = create(
|
||||
&factory_name,
|
||||
ModelConfig::new(config.model_name)?.with_canonical_limits(&factory_name),
|
||||
goose::model_config::model_config_from_user_config(&factory_name, config.model_name)?,
|
||||
Vec::new(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
@@ -6,6 +6,7 @@ use console::style;
|
||||
use goose::agents::{Agent, Container, ExtensionError};
|
||||
use goose::config::resolve_extensions_for_new_session;
|
||||
use goose::config::{Config, ExtensionConfig, GooseMode};
|
||||
use goose::model_config::model_config_from_user_config;
|
||||
use goose::providers::create;
|
||||
use goose::recipe::Recipe;
|
||||
use goose::session::session_manager::SessionType;
|
||||
@@ -229,14 +230,14 @@ async fn load_extensions(
|
||||
struct ResolvedProviderConfig {
|
||||
provider_name: String,
|
||||
model_name: String,
|
||||
model_config: goose::model::ModelConfig,
|
||||
model_config: goose_providers::model::ModelConfig,
|
||||
}
|
||||
|
||||
fn resolve_provider_and_model(
|
||||
session_config: &SessionBuilderConfig,
|
||||
config: &Config,
|
||||
saved_provider: Option<String>,
|
||||
saved_model_config: Option<goose::model::ModelConfig>,
|
||||
saved_model_config: Option<goose_providers::model::ModelConfig>,
|
||||
) -> ResolvedProviderConfig {
|
||||
let recipe_settings = session_config
|
||||
.recipe
|
||||
@@ -277,14 +278,16 @@ fn resolve_provider_and_model(
|
||||
}
|
||||
config
|
||||
} else {
|
||||
let temperature = recipe_settings.and_then(|s| s.temperature);
|
||||
goose::model::ModelConfig::new(&model_name)
|
||||
.unwrap_or_else(|e| {
|
||||
output::render_error(&format!("Failed to create model configuration: {}", e));
|
||||
process::exit(1);
|
||||
})
|
||||
.with_canonical_limits(&provider_name)
|
||||
.with_temperature(temperature)
|
||||
let mut config =
|
||||
goose::model_config::model_config_from_user_config(&provider_name, &model_name)
|
||||
.unwrap_or_else(|e| {
|
||||
output::render_error(&format!("Failed to create model configuration: {}", e));
|
||||
process::exit(1);
|
||||
});
|
||||
if let Some(temp) = recipe_settings.and_then(|s| s.temperature) {
|
||||
config = config.with_temperature(Some(temp));
|
||||
}
|
||||
config
|
||||
};
|
||||
|
||||
ResolvedProviderConfig {
|
||||
@@ -575,12 +578,15 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> CliSession {
|
||||
))
|
||||
.yellow()
|
||||
);
|
||||
let fallback_model_config = goose::model::ModelConfig::new(&fallback_model)
|
||||
.unwrap_or_else(|e| {
|
||||
output::render_error(&format!("Failed to create model configuration: {}", e));
|
||||
process::exit(1);
|
||||
})
|
||||
.with_canonical_limits(&fallback_provider);
|
||||
let fallback_model_config =
|
||||
model_config_from_user_config(fallback_provider.as_str(), &fallback_model)
|
||||
.unwrap_or_else(|e| {
|
||||
output::render_error(&format!(
|
||||
"Failed to create model configuration: {}",
|
||||
e
|
||||
));
|
||||
process::exit(1);
|
||||
});
|
||||
match create(
|
||||
&fallback_provider,
|
||||
fallback_model_config,
|
||||
|
||||
@@ -13,6 +13,7 @@ use crate::session::task_execution_display::{
|
||||
format_task_execution_notification, TASK_EXECUTION_NOTIFICATION_TYPE,
|
||||
};
|
||||
use goose::conversation::Conversation;
|
||||
use std::env;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
use tokio::signal::ctrl_c;
|
||||
@@ -57,6 +58,8 @@ use tokio;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use tracing::warn;
|
||||
|
||||
const GOOSE_PLANNER_CONTEXT_LIMIT: &str = "GOOSE_PLANNER_CONTEXT_LIMIT";
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
struct JsonOutput {
|
||||
messages: Vec<Message>,
|
||||
@@ -842,8 +845,11 @@ impl CliSession {
|
||||
let new_model_config =
|
||||
build_switched_model_config(¤t_provider_name, model_name, ¤t_model_config)?;
|
||||
|
||||
let configured_effort = Config::global().get_goose_thinking_effort();
|
||||
let new_effort = new_model_config.thinking_effort().or(configured_effort);
|
||||
let current_effort = current_model_config.thinking_effort().or(configured_effort);
|
||||
if new_model_config.model_name == current_model_config.model_name
|
||||
&& new_model_config.thinking_effort() == current_model_config.thinking_effort()
|
||||
&& new_effort == current_effort
|
||||
{
|
||||
output::goose_mode_message(&format!(
|
||||
"Session already using model '{}' for provider '{}'",
|
||||
@@ -2200,7 +2206,6 @@ fn handle_agent_error(e: &anyhow::Error, is_stream_json_mode: bool) {
|
||||
}
|
||||
|
||||
async fn get_reasoner() -> Result<Arc<dyn Provider>, anyhow::Error> {
|
||||
use goose::model::ModelConfig;
|
||||
use goose::providers::create;
|
||||
|
||||
let config = Config::global();
|
||||
@@ -2225,8 +2230,19 @@ async fn get_reasoner() -> Result<Arc<dyn Provider>, anyhow::Error> {
|
||||
.expect("No model configured. Run 'goose configure' first")
|
||||
};
|
||||
|
||||
let planner_context_limit = match env::var(GOOSE_PLANNER_CONTEXT_LIMIT)
|
||||
.ok()
|
||||
.map(|v| v.parse::<usize>())
|
||||
{
|
||||
Some(Ok(n)) if n >= 4096 => Some(n),
|
||||
Some(Ok(_)) => anyhow::bail!("{} must be at least 4096", GOOSE_PLANNER_CONTEXT_LIMIT),
|
||||
Some(Err(e)) => anyhow::bail!("{}: {}", GOOSE_PLANNER_CONTEXT_LIMIT, e),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let model_config =
|
||||
ModelConfig::new_with_context_env(model, &provider, Some("GOOSE_PLANNER_CONTEXT_LIMIT"))?;
|
||||
goose::model_config::model_config_from_user_config(&provider, model.as_str())?
|
||||
.with_context_limit(planner_context_limit);
|
||||
let extensions = goose::config::extensions::get_enabled_extensions_with_config(config);
|
||||
let reasoner = create(&provider, model_config, extensions).await?;
|
||||
|
||||
@@ -2249,12 +2265,11 @@ fn format_elapsed_time(duration: std::time::Duration) -> String {
|
||||
fn build_switched_model_config(
|
||||
provider_name: &str,
|
||||
model_name: &str,
|
||||
current_model_config: &goose::model::ModelConfig,
|
||||
) -> Result<goose::model::ModelConfig> {
|
||||
goose::model::ModelConfig::new(model_name)
|
||||
current_model_config: &goose_providers::model::ModelConfig,
|
||||
) -> Result<goose_providers::model::ModelConfig> {
|
||||
goose::model_config::model_config_from_user_config(provider_name, model_name)
|
||||
.map(|config| {
|
||||
config
|
||||
.with_canonical_limits(provider_name)
|
||||
.with_temperature(current_model_config.temperature)
|
||||
.with_toolshim(current_model_config.toolshim)
|
||||
.with_toolshim_model(current_model_config.toolshim_model.clone())
|
||||
@@ -2404,7 +2419,7 @@ mod tests {
|
||||
("GOOSE_TOOLSHIM_OLLAMA_MODEL", None::<&str>),
|
||||
]);
|
||||
|
||||
let current_model_config = goose::model::ModelConfig {
|
||||
let current_model_config = goose_providers::model::ModelConfig {
|
||||
model_name: "gpt-4o".to_string(),
|
||||
context_limit: Some(128_000),
|
||||
temperature: Some(0.25),
|
||||
@@ -2421,7 +2436,7 @@ mod tests {
|
||||
|
||||
let switched =
|
||||
build_switched_model_config("openai", "gpt-5.4", ¤t_model_config).unwrap();
|
||||
let expected = goose::model::ModelConfig::new_or_fail("gpt-5.4")
|
||||
let expected = goose_providers::model::ModelConfig::new_or_fail("gpt-5.4")
|
||||
.with_canonical_limits("openai")
|
||||
.with_temperature(Some(0.25))
|
||||
.with_toolshim(true)
|
||||
@@ -2448,8 +2463,8 @@ mod tests {
|
||||
("GOOSE_THINKING_EFFORT", None::<&str>),
|
||||
]);
|
||||
|
||||
let current =
|
||||
goose::model::ModelConfig::new_or_fail("gpt-5.4-high").with_canonical_limits("openai");
|
||||
let current = goose_providers::model::ModelConfig::new_or_fail("gpt-5.4-high")
|
||||
.with_canonical_limits("openai");
|
||||
assert_eq!(current.model_name, "gpt-5.4");
|
||||
assert_eq!(
|
||||
current.thinking_effort(),
|
||||
|
||||
Reference in New Issue
Block a user