diff --git a/crates/goose-server/src/openapi.rs b/crates/goose-server/src/openapi.rs index 295af9f2ac66..b60bddd0fe4b 100644 --- a/crates/goose-server/src/openapi.rs +++ b/crates/goose-server/src/openapi.rs @@ -400,6 +400,8 @@ impl<'__s> ToSchema<'__s> for AnnotatedSchema { super::routes::recipe::scan_recipe, super::routes::recipe::list_recipes, super::routes::recipe::delete_recipe, + super::routes::setup::start_openrouter_setup, + super::routes::setup::start_tetrate_setup, ), components(schemas( super::routes::config_management::UpsertConfigQuery, @@ -496,6 +498,7 @@ impl<'__s> ToSchema<'__s> for AnnotatedSchema { super::routes::agent::ResumeAgentRequest, super::routes::agent::StartAgentResponse, super::routes::agent::ErrorResponse, + super::routes::setup::SetupResponse, )) )] pub struct ApiDoc; diff --git a/crates/goose-server/src/routes/setup.rs b/crates/goose-server/src/routes/setup.rs index 0c716d500a9e..46406a16dd89 100644 --- a/crates/goose-server/src/routes/setup.rs +++ b/crates/goose-server/src/routes/setup.rs @@ -1,12 +1,13 @@ use crate::state::AppState; -use axum::{extract::State, http::StatusCode, routing::post, Json, Router}; +use axum::{http::StatusCode, routing::post, Json, Router}; use goose::config::signup_openrouter::OpenRouterAuth; use goose::config::signup_tetrate::{configure_tetrate, TetrateAuth}; use goose::config::{configure_openrouter, Config}; use serde::Serialize; use std::sync::Arc; +use utoipa::ToSchema; -#[derive(Serialize)] +#[derive(Serialize, ToSchema)] pub struct SetupResponse { pub success: bool, pub message: String, @@ -19,9 +20,14 @@ pub fn routes(state: Arc) -> Router { .with_state(state) } -async fn start_openrouter_setup( - State(_state): State>, -) -> Result, StatusCode> { +#[utoipa::path( + post, + path = "/handle_openrouter", + responses( + (status = 200, body=SetupResponse) + ), +)] +async fn start_openrouter_setup() -> Result, StatusCode> { tracing::info!("Starting OpenRouter setup flow"); let mut auth_flow = OpenRouterAuth::new().map_err(|e| { @@ -61,9 +67,14 @@ async fn start_openrouter_setup( } } -async fn start_tetrate_setup( - State(_state): State>, -) -> Result, StatusCode> { +#[utoipa::path( + post, + path = "/handle_tetrate", + responses( + (status = 200, body=SetupResponse) + ), +)] +async fn start_tetrate_setup() -> Result, StatusCode> { tracing::info!("Starting Tetrate Agent Router Service setup flow"); let mut auth_flow = TetrateAuth::new().map_err(|e| { diff --git a/ui/desktop/openapi.json b/ui/desktop/openapi.json index 92ed5c4edbc5..46e18a0fd2a4 100644 --- a/ui/desktop/openapi.json +++ b/ui/desktop/openapi.json @@ -886,6 +886,46 @@ ] } }, + "/handle_openrouter": { + "post": { + "tags": [ + "super::routes::setup" + ], + "operationId": "start_openrouter_setup", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetupResponse" + } + } + } + } + } + } + }, + "/handle_tetrate": { + "post": { + "tags": [ + "super::routes::setup" + ], + "operationId": "start_tetrate_setup", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetupResponse" + } + } + } + } + } + } + }, "/recipes/create": { "post": { "tags": [ @@ -3608,6 +3648,21 @@ } } }, + "SetupResponse": { + "type": "object", + "required": [ + "success", + "message" + ], + "properties": { + "message": { + "type": "string" + }, + "success": { + "type": "boolean" + } + } + }, "StartAgentRequest": { "type": "object", "required": [ diff --git a/ui/desktop/src/api/sdk.gen.ts b/ui/desktop/src/api/sdk.gen.ts index 20dbc7797aae..39ac4c781667 100644 --- a/ui/desktop/src/api/sdk.gen.ts +++ b/ui/desktop/src/api/sdk.gen.ts @@ -1,7 +1,7 @@ // This file is auto-generated by @hey-api/openapi-ts import type { Options as ClientOptions, TDataShape, Client } from './client'; -import type { AddSubRecipesData, AddSubRecipesResponses, AddSubRecipesErrors, ExtendPromptData, ExtendPromptResponses, ExtendPromptErrors, ResumeAgentData, ResumeAgentResponses, ResumeAgentErrors, UpdateSessionConfigData, UpdateSessionConfigResponses, UpdateSessionConfigErrors, StartAgentData, StartAgentResponses, StartAgentErrors, GetToolsData, GetToolsResponses, GetToolsErrors, UpdateAgentProviderData, UpdateAgentProviderResponses, UpdateAgentProviderErrors, UpdateRouterToolSelectorData, UpdateRouterToolSelectorResponses, UpdateRouterToolSelectorErrors, ReadAllConfigData, ReadAllConfigResponses, BackupConfigData, BackupConfigResponses, BackupConfigErrors, CreateCustomProviderData, CreateCustomProviderResponses, CreateCustomProviderErrors, RemoveCustomProviderData, RemoveCustomProviderResponses, RemoveCustomProviderErrors, GetExtensionsData, GetExtensionsResponses, GetExtensionsErrors, AddExtensionData, AddExtensionResponses, AddExtensionErrors, RemoveExtensionData, RemoveExtensionResponses, RemoveExtensionErrors, InitConfigData, InitConfigResponses, InitConfigErrors, UpsertPermissionsData, UpsertPermissionsResponses, UpsertPermissionsErrors, ProvidersData, ProvidersResponses, GetProviderModelsData, GetProviderModelsResponses, GetProviderModelsErrors, ReadConfigData, ReadConfigResponses, ReadConfigErrors, RecoverConfigData, RecoverConfigResponses, RecoverConfigErrors, RemoveConfigData, RemoveConfigResponses, RemoveConfigErrors, UpsertConfigData, UpsertConfigResponses, UpsertConfigErrors, ValidateConfigData, ValidateConfigResponses, ValidateConfigErrors, ConfirmPermissionData, ConfirmPermissionResponses, ConfirmPermissionErrors, ManageContextData, ManageContextResponses, ManageContextErrors, CreateRecipeData, CreateRecipeResponses, CreateRecipeErrors, DecodeRecipeData, DecodeRecipeResponses, DecodeRecipeErrors, DeleteRecipeData, DeleteRecipeResponses, DeleteRecipeErrors, EncodeRecipeData, EncodeRecipeResponses, EncodeRecipeErrors, ListRecipesData, ListRecipesResponses, ListRecipesErrors, ScanRecipeData, ScanRecipeResponses, CreateScheduleData, CreateScheduleResponses, CreateScheduleErrors, DeleteScheduleData, DeleteScheduleResponses, DeleteScheduleErrors, ListSchedulesData, ListSchedulesResponses, ListSchedulesErrors, UpdateScheduleData, UpdateScheduleResponses, UpdateScheduleErrors, InspectRunningJobData, InspectRunningJobResponses, InspectRunningJobErrors, KillRunningJobData, KillRunningJobResponses, PauseScheduleData, PauseScheduleResponses, PauseScheduleErrors, RunNowHandlerData, RunNowHandlerResponses, RunNowHandlerErrors, SessionsHandlerData, SessionsHandlerResponses, SessionsHandlerErrors, UnpauseScheduleData, UnpauseScheduleResponses, UnpauseScheduleErrors, ListSessionsData, ListSessionsResponses, ListSessionsErrors, GetSessionHistoryData, GetSessionHistoryResponses, GetSessionHistoryErrors, StatusData, StatusResponses } from './types.gen'; +import type { AddSubRecipesData, AddSubRecipesResponses, AddSubRecipesErrors, ExtendPromptData, ExtendPromptResponses, ExtendPromptErrors, ResumeAgentData, ResumeAgentResponses, ResumeAgentErrors, UpdateSessionConfigData, UpdateSessionConfigResponses, UpdateSessionConfigErrors, StartAgentData, StartAgentResponses, StartAgentErrors, GetToolsData, GetToolsResponses, GetToolsErrors, UpdateAgentProviderData, UpdateAgentProviderResponses, UpdateAgentProviderErrors, UpdateRouterToolSelectorData, UpdateRouterToolSelectorResponses, UpdateRouterToolSelectorErrors, ReadAllConfigData, ReadAllConfigResponses, BackupConfigData, BackupConfigResponses, BackupConfigErrors, CreateCustomProviderData, CreateCustomProviderResponses, CreateCustomProviderErrors, RemoveCustomProviderData, RemoveCustomProviderResponses, RemoveCustomProviderErrors, GetExtensionsData, GetExtensionsResponses, GetExtensionsErrors, AddExtensionData, AddExtensionResponses, AddExtensionErrors, RemoveExtensionData, RemoveExtensionResponses, RemoveExtensionErrors, InitConfigData, InitConfigResponses, InitConfigErrors, UpsertPermissionsData, UpsertPermissionsResponses, UpsertPermissionsErrors, ProvidersData, ProvidersResponses, GetProviderModelsData, GetProviderModelsResponses, GetProviderModelsErrors, ReadConfigData, ReadConfigResponses, ReadConfigErrors, RecoverConfigData, RecoverConfigResponses, RecoverConfigErrors, RemoveConfigData, RemoveConfigResponses, RemoveConfigErrors, UpsertConfigData, UpsertConfigResponses, UpsertConfigErrors, ValidateConfigData, ValidateConfigResponses, ValidateConfigErrors, ConfirmPermissionData, ConfirmPermissionResponses, ConfirmPermissionErrors, ManageContextData, ManageContextResponses, ManageContextErrors, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, CreateRecipeData, CreateRecipeResponses, CreateRecipeErrors, DecodeRecipeData, DecodeRecipeResponses, DecodeRecipeErrors, DeleteRecipeData, DeleteRecipeResponses, DeleteRecipeErrors, EncodeRecipeData, EncodeRecipeResponses, EncodeRecipeErrors, ListRecipesData, ListRecipesResponses, ListRecipesErrors, ScanRecipeData, ScanRecipeResponses, CreateScheduleData, CreateScheduleResponses, CreateScheduleErrors, DeleteScheduleData, DeleteScheduleResponses, DeleteScheduleErrors, ListSchedulesData, ListSchedulesResponses, ListSchedulesErrors, UpdateScheduleData, UpdateScheduleResponses, UpdateScheduleErrors, InspectRunningJobData, InspectRunningJobResponses, InspectRunningJobErrors, KillRunningJobData, KillRunningJobResponses, PauseScheduleData, PauseScheduleResponses, PauseScheduleErrors, RunNowHandlerData, RunNowHandlerResponses, RunNowHandlerErrors, SessionsHandlerData, SessionsHandlerResponses, SessionsHandlerErrors, UnpauseScheduleData, UnpauseScheduleResponses, UnpauseScheduleErrors, ListSessionsData, ListSessionsResponses, ListSessionsErrors, GetSessionHistoryData, GetSessionHistoryResponses, GetSessionHistoryErrors, StatusData, StatusResponses } from './types.gen'; import { client as _heyApiClient } from './client.gen'; export type Options = ClientOptions & { @@ -260,6 +260,20 @@ export const manageContext = (options: Opt }); }; +export const startOpenrouterSetup = (options?: Options) => { + return (options?.client ?? _heyApiClient).post({ + url: '/handle_openrouter', + ...options + }); +}; + +export const startTetrateSetup = (options?: Options) => { + return (options?.client ?? _heyApiClient).post({ + url: '/handle_tetrate', + ...options + }); +}; + /** * Create a Recipe configuration from the current session */ diff --git a/ui/desktop/src/api/types.gen.ts b/ui/desktop/src/api/types.gen.ts index c5648ccaf9e7..6dba19df178a 100644 --- a/ui/desktop/src/api/types.gen.ts +++ b/ui/desktop/src/api/types.gen.ts @@ -782,6 +782,11 @@ export type Settings = { temperature?: number | null; }; +export type SetupResponse = { + message: string; + success: boolean; +}; + export type StartAgentRequest = { recipe?: Recipe | null; working_dir: string; @@ -1615,6 +1620,32 @@ export type ManageContextResponses = { export type ManageContextResponse = ManageContextResponses[keyof ManageContextResponses]; +export type StartOpenrouterSetupData = { + body?: never; + path?: never; + query?: never; + url: '/handle_openrouter'; +}; + +export type StartOpenrouterSetupResponses = { + 200: SetupResponse; +}; + +export type StartOpenrouterSetupResponse = StartOpenrouterSetupResponses[keyof StartOpenrouterSetupResponses]; + +export type StartTetrateSetupData = { + body?: never; + path?: never; + query?: never; + url: '/handle_tetrate'; +}; + +export type StartTetrateSetupResponses = { + 200: SetupResponse; +}; + +export type StartTetrateSetupResponse = StartTetrateSetupResponses[keyof StartTetrateSetupResponses]; + export type CreateRecipeData = { body: CreateRecipeRequest; path?: never; diff --git a/ui/desktop/src/utils/openRouterSetup.ts b/ui/desktop/src/utils/openRouterSetup.ts index 10dffe0f23bd..daa46fb51b7c 100644 --- a/ui/desktop/src/utils/openRouterSetup.ts +++ b/ui/desktop/src/utils/openRouterSetup.ts @@ -1,24 +1,17 @@ +import { startOpenrouterSetup } from '../api'; + export interface OpenRouterSetupStatus { isRunning: boolean; error: string | null; } export async function startOpenRouterSetup(): Promise<{ success: boolean; message: string }> { - const baseUrl = `${window.appConfig.get('GOOSE_API_HOST')}:${window.appConfig.get('GOOSE_PORT')}`; - const response = await fetch(`${baseUrl}/handle_openrouter`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - }); - - if (!response.ok) { - console.error('Failed to start Openrouter setup:', response.statusText); + try { + return (await startOpenrouterSetup({ throwOnError: true })).data; + } catch (e) { return { success: false, - message: `Failed to start Openrouter setup ['${response.status}]`, + message: `Failed to start Openrouter setup ['${e}]`, }; } - - return await response.json(); } diff --git a/ui/desktop/src/utils/tetrateSetup.ts b/ui/desktop/src/utils/tetrateSetup.ts index 554aa67bc160..8b19122afade 100644 --- a/ui/desktop/src/utils/tetrateSetup.ts +++ b/ui/desktop/src/utils/tetrateSetup.ts @@ -1,25 +1,17 @@ +import { startTetrateSetup as startTetrateSetupApi } from '../api'; + export interface TetrateSetupStatus { isRunning: boolean; error: string | null; } export async function startTetrateSetup(): Promise<{ success: boolean; message: string }> { - const baseUrl = `${window.appConfig.get('GOOSE_API_HOST')}:${window.appConfig.get('GOOSE_PORT')}`; - const response = await fetch(`${baseUrl}/handle_tetrate`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - }); - - if (!response.ok) { - console.error('Failed to start Tetrate setup:', response.statusText); + try { + return (await startTetrateSetupApi({ throwOnError: true })).data; + } catch (e) { return { success: false, - message: `Failed to start Tetrate setup ['${response.status}]`, + message: `Failed to start Tetrate setup ['${e}]`, }; } - - const result = await response.json(); - return result; }