Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 2 additions & 11 deletions clippy-baselines/too_many_lines.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,10 @@
crates/goose-bench/src/eval_suites/core/developer/simple_repo_clone_test.rs::run
crates/goose-cli/src/cli.rs::cli
crates/goose-cli/src/commands/configure.rs::configure_extensions_dialog
crates/goose-cli/src/commands/configure.rs::configure_provider_dialog
crates/goose-cli/src/commands/configure.rs::configure_tool_permissions_dialog
crates/goose-cli/src/commands/configure.rs::handle_configure
crates/goose-cli/src/commands/project.rs::handle_project_default
crates/goose-cli/src/commands/project.rs::handle_projects_interactive
crates/goose-cli/src/commands/web.rs::process_message_streaming
crates/goose-cli/src/session/builder.rs::build_session
crates/goose-cli/src/session/export.rs::tool_response_to_markdown
crates/goose-cli/src/session/mod.rs::interactive
crates/goose-cli/src/session/mod.rs::process_agent_response
crates/goose-mcp/src/computercontroller/docx_tool.rs::docx_tool
crates/goose-mcp/src/computercontroller/mod.rs::new
crates/goose-mcp/src/computercontroller/pdf_tool.rs::pdf_tool
crates/goose-mcp/src/memory/mod.rs::new
Expand All @@ -23,12 +16,10 @@ crates/goose/src/agents/agent.rs::create_recipe
crates/goose/src/agents/agent.rs::dispatch_tool_call
crates/goose/src/agents/agent.rs::reply
crates/goose/src/agents/agent.rs::reply_internal
crates/goose/src/agents/extension_manager.rs::add_extension
crates/goose/src/providers/formats/anthropic.rs::format_messages
crates/goose/src/providers/formats/anthropic.rs::response_to_streaming_message<S>
crates/goose/src/providers/formats/anthropic.rs::response_to_streaming_message
crates/goose/src/providers/formats/databricks.rs::format_messages
crates/goose/src/providers/formats/google.rs::format_messages
crates/goose/src/providers/formats/openai.rs::format_messages
crates/goose/src/providers/formats/openai.rs::response_to_streaming_message<S>
crates/goose/src/providers/gcpvertexai.rs::post_with_location
crates/goose/src/providers/formats/openai.rs::response_to_streaming_message
crates/goose/src/providers/snowflake.rs::post
1 change: 1 addition & 0 deletions crates/goose-server/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ derive_utoipa!(Icon as IconSchema);
super::routes::config_management::remove_custom_provider,
super::routes::config_management::check_provider,
super::routes::config_management::set_config_provider,
super::routes::config_management::configure_provider_oauth,
super::routes::config_management::get_pricing,
super::routes::prompts::get_prompts,
super::routes::prompts::get_prompt,
Expand Down
59 changes: 59 additions & 0 deletions crates/goose-server/src/routes/config_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,13 @@ fn mask_secret(secret: Value) -> String {
format!("{}{}", visible, mask)
}

fn is_valid_provider_name(provider_name: &str) -> bool {
!provider_name.is_empty()
&& provider_name
.chars()
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
}

#[utoipa::path(
post,
path = "/config/read",
Expand Down Expand Up @@ -823,6 +830,54 @@ pub async fn set_config_provider(
Ok(())
}

#[utoipa::path(
post,
path = "/config/providers/{name}/oauth",
params(
("name" = String, Path, description = "Provider name")
),
responses(
(status = 200, description = "OAuth configuration completed"),
(status = 400, description = "OAuth configuration failed")
)
)]
pub async fn configure_provider_oauth(
Path(provider_name): Path<String>,
) -> Result<Json<String>, (StatusCode, String)> {
use goose::model::ModelConfig;
use goose::providers::create;

if !is_valid_provider_name(&provider_name) {
return Err((StatusCode::BAD_REQUEST, "Invalid provider name".to_string()));
}

let temp_model =
ModelConfig::new("temp").map_err(|e| (StatusCode::BAD_REQUEST, e.to_string()))?;

let provider = create(&provider_name, temp_model).await.map_err(|e| {
(
StatusCode::BAD_REQUEST,
format!("Failed to create provider: {}", e),
)
})?;

provider.configure_oauth().await.map_err(|e| {
(
StatusCode::BAD_REQUEST,
format!("OAuth configuration failed: {}", e),
)
})?;

// Mark the provider as configured after successful OAuth
let configured_marker = format!("{}_configured", provider_name);
let config = goose::config::Config::global();
config
.set_param(&configured_marker, true)
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;

Ok(Json("OAuth configuration completed".to_string()))
}

pub fn routes(state: Arc<AppState>) -> Router {
Router::new()
.route("/config", get(read_all_config))
Expand Down Expand Up @@ -851,6 +906,10 @@ pub fn routes(state: Arc<AppState>) -> Router {
.route("/config/custom-providers/{id}", get(get_custom_provider))
.route("/config/check_provider", post(check_provider))
.route("/config/set_provider", post(set_config_provider))
.route(
"/config/providers/{name}/oauth",
post(configure_provider_oauth),
)
.with_state(state)
}

Expand Down
10 changes: 10 additions & 0 deletions crates/goose-server/src/routes/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ pub fn check_provider_configured(metadata: &ProviderMetadata, provider_type: Pro
.is_ok();
}
}

// Special case: OAuth providers - check for configured marker
let has_oauth_key = metadata.config_keys.iter().any(|key| key.oauth_flow);
if has_oauth_key {
let configured_marker = format!("{}_configured", metadata.name);
if matches!(config.get_param::<bool>(&configured_marker), Ok(true)) {
return true;
}
}

// Special case: Zero-config providers (no config keys)
if metadata.config_keys.is_empty() {
// Check if the provider has been explicitly configured via the UI
Expand Down
1 change: 1 addition & 0 deletions crates/goose/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ rand = "0.8.5"
utoipa = { version = "4.1", features = ["chrono"] }
tokio-cron-scheduler = "0.14.0"
urlencoding = "2.1"
v_htmlescape = "0.15"
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "sqlite", "chrono", "json"] }

# For Bedrock provider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3024,6 +3024,10 @@
"provider_model": "gpt-5.1-codex-mini",
"canonical_model": "openai/gpt-5.1-codex-mini"
},
{
"provider_model": "gpt-5.2-codex",
"canonical_model": "openai/gpt-5.2-codex"
},
{
"provider_model": "gpt-5.2",
"canonical_model": "openai/gpt-5.2"
Expand Down
21 changes: 21 additions & 0 deletions crates/goose/src/providers/canonical/data/canonical_models.json
Original file line number Diff line number Diff line change
Expand Up @@ -2181,6 +2181,27 @@
"image": 0.0
}
},
{
"id": "openai/gpt-5.2-codex",
"name": "OpenAI: GPT-5.2-Codex",
"context_length": 400000,
"max_completion_tokens": 128000,
"input_modalities": [
"file",
"image",
"text"
],
"output_modalities": [
"text"
],
"supports_tools": true,
"pricing": {
"prompt": 1.75e-6,
"completion": 0.000014,
"request": 0.0,
"image": 0.0
}
},
{
"id": "openai/gpt-5.2-pro",
"name": "OpenAI: GPT-5.2 Pro",
Expand Down
5 changes: 4 additions & 1 deletion crates/goose/src/providers/canonical/name_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ fn swap_claude_word_order(model: &str) -> Option<String> {
}

fn is_hosting_provider(provider: &str) -> bool {
matches!(provider, "databricks" | "openrouter" | "azure" | "bedrock")
matches!(
provider,
"databricks" | "openrouter" | "azure" | "bedrock" | "chatgpt_codex"
)
}

/// Infer the real provider from model name patterns
Expand Down
Loading
Loading