feat: new onboarding flow (#7266)

This commit is contained in:
Lifei Zhou
2026-03-17 12:33:41 +11:00
committed by GitHub
parent a518c42cbc
commit 4604354bc2
40 changed files with 1800 additions and 441 deletions
+2
View File
@@ -469,6 +469,7 @@ derive_utoipa!(Icon as IconSchema);
super::routes::recipe::recipe_to_yaml,
super::routes::setup::start_openrouter_setup,
super::routes::setup::start_tetrate_setup,
super::routes::setup::start_nanogpt_setup,
super::routes::tunnel::start_tunnel,
super::routes::tunnel::stop_tunnel,
super::routes::tunnel::get_tunnel_status,
@@ -510,6 +511,7 @@ derive_utoipa!(Icon as IconSchema);
goose::providers::catalog::ProviderTemplate,
goose::providers::catalog::ModelTemplate,
goose::providers::catalog::ModelCapabilities,
super::routes::config_management::CreateCustomProviderResponse,
super::routes::config_management::CheckProviderRequest,
super::routes::config_management::SetProviderRequest,
super::routes::config_management::ModelInfoQuery,
@@ -633,19 +633,24 @@ pub async fn validate_config() -> Result<Json<String>, ErrorResponse> {
Ok(Json("Config file is valid".to_string()))
}
#[derive(Serialize, ToSchema)]
pub struct CreateCustomProviderResponse {
pub provider_name: String,
}
#[utoipa::path(
post,
path = "/config/custom-providers",
request_body = UpdateCustomProviderRequest,
responses(
(status = 200, description = "Custom provider created successfully", body = String),
(status = 200, description = "Custom provider created successfully", body = CreateCustomProviderResponse),
(status = 400, description = "Invalid request"),
(status = 500, description = "Internal server error")
)
)]
pub async fn create_custom_provider(
Json(request): Json<UpdateCustomProviderRequest>,
) -> Result<Json<String>, ErrorResponse> {
) -> Result<Json<CreateCustomProviderResponse>, ErrorResponse> {
let config = goose::config::declarative_providers::create_custom_provider(
goose::config::declarative_providers::CreateCustomProviderParams {
engine: request.engine,
@@ -663,7 +668,9 @@ pub async fn create_custom_provider(
goose::providers::refresh_custom_providers().await?;
Ok(Json(format!("Custom provider added - ID: {}", config.id())))
Ok(Json(CreateCustomProviderResponse {
provider_name: config.id().to_string(),
}))
}
#[utoipa::path(
+35 -2
View File
@@ -1,6 +1,7 @@
use crate::routes::errors::ErrorResponse;
use crate::state::AppState;
use axum::{routing::post, Json, Router};
use goose::config::signup_nanogpt::{complete_nanogpt_auth, configure_nanogpt};
use goose::config::signup_openrouter::OpenRouterAuth;
use goose::config::signup_tetrate::{configure_tetrate, TetrateAuth};
use goose::config::{configure_openrouter, Config};
@@ -18,6 +19,7 @@ pub fn routes(state: Arc<AppState>) -> Router {
Router::new()
.route("/handle_openrouter", post(start_openrouter_setup))
.route("/handle_tetrate", post(start_tetrate_setup))
.route("/handle_nanogpt", post(start_nanogpt_setup))
.with_state(state)
}
@@ -50,7 +52,7 @@ async fn start_openrouter_setup() -> Result<Json<SetupResponse>, ErrorResponse>
}
Err(e) => Ok(Json(SetupResponse {
success: false,
message: format!("Setup failed: {}", e),
message: e.to_string(),
})),
}
}
@@ -84,7 +86,38 @@ async fn start_tetrate_setup() -> Result<Json<SetupResponse>, ErrorResponse> {
}
Err(e) => Ok(Json(SetupResponse {
success: false,
message: format!("Setup failed: {}", e),
message: e.to_string(),
})),
}
}
#[utoipa::path(
post,
path = "/handle_nanogpt",
responses(
(status = 200, body=SetupResponse)
),
)]
async fn start_nanogpt_setup() -> Result<Json<SetupResponse>, ErrorResponse> {
match complete_nanogpt_auth().await {
Ok(api_key) => {
let config = Config::global();
if let Err(e) = configure_nanogpt(config, api_key) {
return Ok(Json(SetupResponse {
success: false,
message: format!("Failed to configure NanoGPT: {}", e),
}));
}
Ok(Json(SetupResponse {
success: true,
message: "NanoGPT setup completed successfully".to_string(),
}))
}
Err(e) => Ok(Json(SetupResponse {
success: false,
message: e.to_string(),
})),
}
}