From d0debc3187744215d7ae89e0db054a58a88b46fd Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Tue, 17 Feb 2026 09:27:49 +1100 Subject: [PATCH 01/41] onboarding page to start --- ui/desktop/src/App.tsx | 4 + .../components/GooseSidebar/AppSidebar.tsx | 8 + .../onboarding/GettingStartedPage.tsx | 165 +++++++++++++++ .../components/onboarding/OnboardingPage.tsx | 84 ++++++++ .../onboarding/ProviderConfigForm.tsx | 189 ++++++++++++++++++ .../onboarding/ProviderSelector.tsx | 92 +++++++++ 6 files changed, 542 insertions(+) create mode 100644 ui/desktop/src/components/onboarding/GettingStartedPage.tsx create mode 100644 ui/desktop/src/components/onboarding/OnboardingPage.tsx create mode 100644 ui/desktop/src/components/onboarding/ProviderConfigForm.tsx create mode 100644 ui/desktop/src/components/onboarding/ProviderSelector.tsx diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index ba03ed6dc576..07df25da766f 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -16,6 +16,8 @@ import { ToastContainer } from 'react-toastify'; import AnnouncementModal from './components/AnnouncementModal'; import TelemetryOptOutModal from './components/TelemetryOptOutModal'; import ProviderGuard from './components/ProviderGuard'; +import OnboardingPage from './components/onboarding/OnboardingPage'; +import GettingStartedPage from './components/onboarding/GettingStartedPage'; import { createSession } from './sessions'; import { ChatType } from './types/chat'; @@ -633,6 +635,8 @@ export function AppInner() { element={ setDidSelectProvider(true)} />} /> } /> + } /> + } /> } /> (null); + + const handleTetrateSetup = async () => { + try { + const result = await startTetrateSetup(); + if (result.success) { + navigate('/', { replace: true }); + } else { + setSetupState({ + show: true, + title: 'Setup Failed', + message: result.message, + showRetry: true, + type: 'tetrate', + }); + } + } catch (error) { + console.error('Tetrate setup error:', error); + setSetupState({ + show: true, + title: 'Setup Error', + message: 'An unexpected error occurred during setup.', + showRetry: true, + type: 'tetrate', + }); + } + }; + + const handleOpenRouterSetup = async () => { + try { + const result = await startOpenRouterSetup(); + if (result.success) { + navigate('/', { replace: true }); + } else { + setSetupState({ + show: true, + title: 'Setup Failed', + message: result.message, + showRetry: true, + type: 'openrouter', + }); + } + } catch (error) { + console.error('OpenRouter setup error:', error); + setSetupState({ + show: true, + title: 'Setup Error', + message: 'An unexpected error occurred during setup.', + showRetry: true, + type: 'openrouter', + }); + } + }; + + const handleRetry = () => { + if (!setupState) return; + const type = setupState.type; + setSetupState(null); + if (type === 'tetrate') handleTetrateSetup(); + else handleOpenRouterSetup(); + }; + + return ( +
+
+
+
+ {/* Header */} +
+
+ +
+

Get Started

+

+ Sign up for an AI provider to start using Goose. +

+
+ + {/* Tetrate card */} +
+
+
+ + + Agent Router by Tetrate + +
+
+ + + +
+
+

+ Access multiple AI models with automatic setup. Sign up to receive $10 credit. +

+
+ + {/* OpenRouter card */} +
+
+
+ + + OpenRouter + +
+
+ + + +
+
+

+ Access 200+ models with one API. Pay-per-use pricing. +

+
+ + {/* Back link */} +
+ +
+
+
+
+ + {setupState?.show && ( + setSetupState(null)} + /> + )} +
+ ); +} diff --git a/ui/desktop/src/components/onboarding/OnboardingPage.tsx b/ui/desktop/src/components/onboarding/OnboardingPage.tsx new file mode 100644 index 000000000000..235e10fedb91 --- /dev/null +++ b/ui/desktop/src/components/onboarding/OnboardingPage.tsx @@ -0,0 +1,84 @@ +import { useState, useMemo } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { SwitchModelModal } from '../settings/models/subcomponents/SwitchModelModal'; +import { createNavigationHandler } from '../../utils/navigationUtils'; +import { Goose } from '../icons'; +import ProviderSelector from './ProviderSelector'; + +export default function OnboardingPage({ + onProviderSetup, +}: { + onProviderSetup?: () => void; +}) { + const navigate = useNavigate(); + const setView = useMemo(() => createNavigationHandler(navigate), [navigate]); + + const [showSwitchModelModal, setShowSwitchModelModal] = useState(false); + const [switchModelProvider, setSwitchModelProvider] = useState(null); + const [hasSelection, setHasSelection] = useState(false); + + const handleConfigured = (providerName: string) => { + setSwitchModelProvider(providerName); + setShowSwitchModelModal(true); + }; + + const handleModelSelected = () => { + setShowSwitchModelModal(false); + onProviderSetup?.(); + navigate('/', { replace: true }); + }; + + const handleOllamaSetup = () => { + // TODO: integrate with existing OllamaSetup component + navigate('/', { replace: true }); + }; + + return ( +
+
+
+
+
+
+ +
+

Welcome to Goose

+

+ Your local AI agent, automating tasks seamlessly. +

+

+ Select an AI provider to power Goose. +

+
+ + setHasSelection(true)} + /> + +
+ +
+
+
+
+ + {showSwitchModelModal && ( + setShowSwitchModelModal(false)} + setView={setView} + onModelSelected={handleModelSelected} + initialProvider={switchModelProvider} + titleOverride="Choose Model" + /> + )} +
+ ); +} diff --git a/ui/desktop/src/components/onboarding/ProviderConfigForm.tsx b/ui/desktop/src/components/onboarding/ProviderConfigForm.tsx new file mode 100644 index 000000000000..3ddd368be979 --- /dev/null +++ b/ui/desktop/src/components/onboarding/ProviderConfigForm.tsx @@ -0,0 +1,189 @@ +import { useState } from 'react'; +import { configureProviderOauth, ProviderDetails } from '../../api'; +import { useConfig } from '../ConfigContext'; +import DefaultProviderSetupForm, { + ConfigInput, +} from '../settings/providers/modal/subcomponents/forms/DefaultProviderSetupForm'; +import { providerConfigSubmitHandler } from '../settings/providers/modal/subcomponents/handlers/DefaultSubmitHandler'; +import ProviderLogo from '../settings/providers/modal/subcomponents/ProviderLogo'; +import { SecureStorageNotice } from '../settings/providers/modal/subcomponents/SecureStorageNotice'; +import { Button } from '../ui/button'; +import { LogIn } from 'lucide-react'; + +function OllamaForm({ onSetup }: { onSetup: () => void }) { + return ( +
+

+ Ollama runs AI models locally on your computer. +

+ +
+ ); +} + +function OAuthForm({ + provider, + onConfigured, + onError, +}: { + provider: ProviderDetails; + onConfigured: (name: string) => void; + onError: (msg: string) => void; +}) { + const [isLoading, setIsLoading] = useState(false); + + const handleLogin = async () => { + setIsLoading(true); + try { + await configureProviderOauth({ + path: { name: provider.name }, + throwOnError: true, + }); + onConfigured(provider.name); + } catch (err) { + onError(`Sign-in failed: ${err instanceof Error ? err.message : String(err)}`); + } finally { + setIsLoading(false); + } + }; + + return ( +
+ +

+ A browser window will open for you to complete the login. +

+
+ ); +} + +function ApiKeyForm({ + provider, + onConfigured, + onError, +}: { + provider: ProviderDetails; + onConfigured: (name: string) => void; + onError: (msg: string) => void; +}) { + const { upsert } = useConfig(); + const [configValues, setConfigValues] = useState>({}); + const [validationErrors, setValidationErrors] = useState>({}); + const [isSubmitting, setIsSubmitting] = useState(false); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setValidationErrors({}); + + const parameters = provider.metadata.config_keys || []; + const errors: Record = {}; + parameters.forEach((param) => { + if (param.required && !configValues[param.name]?.value && !configValues[param.name]?.serverValue) { + errors[param.name] = `${param.name} is required`; + } + }); + + if (Object.keys(errors).length > 0) { + setValidationErrors(errors); + return; + } + + const toSubmit = Object.fromEntries( + Object.entries(configValues) + .filter(([, entry]) => !!entry.value) + .map(([k, entry]) => [k, entry.value || '']) + ); + + setIsSubmitting(true); + try { + await providerConfigSubmitHandler(upsert, provider, toSubmit); + await upsert('GOOSE_PROVIDER', provider.name, false); + onConfigured(provider.name); + } catch (err) { + onError(`Configuration failed: ${err instanceof Error ? err.message : String(err)}`); + } finally { + setIsSubmitting(false); + } + }; + + return ( +
+ + {provider.metadata.config_keys.some((k) => k.required && k.secret) && ( + + )} +
+ +
+ + ); +} + + +interface ProviderConfigFormProps { + provider: ProviderDetails; + onConfigured: (providerName: string) => void; + onOllamaSetup: () => void; +} + +export default function ProviderConfigForm({ + provider, + onConfigured, + onOllamaSetup, +}: ProviderConfigFormProps) { + const [error, setError] = useState(null); + + const isOAuthProvider = provider.metadata.config_keys.some((key) => key.oauth_flow); + const isOllama = provider.name === 'ollama'; + + const renderForm = () => { + if (isOllama) { + return ; + } + if (isOAuthProvider) { + return ; + } + return ; + }; + + return ( +
+
+
+ +
+

+ {provider.metadata.display_name} +

+

+ {provider.metadata.description} +

+
+
+ + {renderForm()} + + {error && ( +
+ {error} +
+ )} +
+
+ ); +} diff --git a/ui/desktop/src/components/onboarding/ProviderSelector.tsx b/ui/desktop/src/components/onboarding/ProviderSelector.tsx new file mode 100644 index 000000000000..f8f4d5b72da2 --- /dev/null +++ b/ui/desktop/src/components/onboarding/ProviderSelector.tsx @@ -0,0 +1,92 @@ +import { useState, useEffect, useMemo } from 'react'; +import { providers as fetchProviders, ProviderDetails } from '../../api'; +import { Select } from '../ui/Select'; +import ProviderConfigForm from './ProviderConfigForm'; + +interface ProviderOption { + value: string; + label: string; + provider: ProviderDetails; +} + +interface ProviderSelectorProps { + onConfigured: (providerName: string) => void; + onOllamaSetup: () => void; + onFirstSelection?: () => void; +} + +export default function ProviderSelector({ onConfigured, onOllamaSetup, onFirstSelection }: ProviderSelectorProps) { + const [providerList, setProviderList] = useState([]); + const [selectedOption, setSelectedOption] = useState(null); + + useEffect(() => { + const load = async () => { + try { + const response = await fetchProviders({ throwOnError: true }); + if (response.data) { + const list = Array.isArray(response.data) + ? response.data + : (response.data as { providers: ProviderDetails[] }).providers || []; + setProviderList(list); + } + } catch (err) { + console.error('Failed to fetch providers:', err); + } + }; + load(); + }, []); + + const options: ProviderOption[] = useMemo(() => { + return [...providerList] + .sort((a, b) => a.metadata.display_name.localeCompare(b.metadata.display_name)) + .map((provider) => ({ + value: provider.name, + label: provider.metadata.display_name, + provider, + })); + }, [providerList]); + + const fuzzyFilterOption = (option: { label: string; value: string }, inputValue: string) => { + const normalize = (s: string) => s.toLowerCase().replace(/[\s_-]/g, ''); + return ( + normalize(option.label).includes(normalize(inputValue)) || + normalize(option.value).includes(normalize(inputValue)) + ); + }; + + const selectedProvider = selectedOption?.provider ?? null; + + return ( +
+
+ + { - setSelectedOption(option as ProviderOption | null); - if (option) onFirstSelection?.(); - }} - placeholder="Search providers..." - isClearable - isSearchable - autoFocus - filterOption={fuzzyFilterOption} - /> +
+
+ + Free Credits +

+ Sign up with an AI provider and get free credits +

+
+ + {/* Own Provider card */} +
+ + + Use Your Own Provider + +

Connect OpenAI, Anthropic, Google, etc

+
- {selectedProvider && ( + {selectedPath === 'free-credits' && (
- + +
+ )} + + {selectedPath === 'own-provider' && ( +
+
+
+ + {selectedProvider && ( )} + + + + + Add Custom Provider + + setShowCustomModal(false)} + /> + +
); } From 743d49ef15d14eb997046c1728fdedabb1882030 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 18 Feb 2026 23:40:39 +1100 Subject: [PATCH 14/41] changed add custom provider response with provider name only --- crates/goose-server/src/openapi.rs | 1 + .../goose-server/src/routes/config_management.rs | 13 ++++++++++--- ui/desktop/openapi.json | 15 +++++++++++++-- ui/desktop/src/api/index.ts | 2 +- ui/desktop/src/api/types.gen.ts | 8 ++++++-- .../components/onboarding/ProviderSelector.tsx | 7 ++----- 6 files changed, 33 insertions(+), 13 deletions(-) diff --git a/crates/goose-server/src/openapi.rs b/crates/goose-server/src/openapi.rs index f33db83520c7..fa9a0fa131a0 100644 --- a/crates/goose-server/src/openapi.rs +++ b/crates/goose-server/src/openapi.rs @@ -441,6 +441,7 @@ derive_utoipa!(Icon as IconSchema); super::routes::config_management::ToolPermission, super::routes::config_management::UpsertPermissionsQuery, super::routes::config_management::UpdateCustomProviderRequest, + super::routes::config_management::CreateCustomProviderResponse, super::routes::config_management::CheckProviderRequest, super::routes::config_management::SetProviderRequest, super::routes::config_management::ModelInfoQuery, diff --git a/crates/goose-server/src/routes/config_management.rs b/crates/goose-server/src/routes/config_management.rs index 032d55e980a1..9eb6736757fc 100644 --- a/crates/goose-server/src/routes/config_management.rs +++ b/crates/goose-server/src/routes/config_management.rs @@ -625,19 +625,24 @@ pub async fn validate_config() -> Result, 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, -) -> Result, ErrorResponse> { +) -> Result, ErrorResponse> { let config = goose::config::declarative_providers::create_custom_provider( goose::config::declarative_providers::CreateCustomProviderParams { engine: request.engine, @@ -653,7 +658,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( diff --git a/ui/desktop/openapi.json b/ui/desktop/openapi.json index b99429e011c8..466140ae4028 100644 --- a/ui/desktop/openapi.json +++ b/ui/desktop/openapi.json @@ -810,9 +810,9 @@ "200": { "description": "Custom provider created successfully", "content": { - "text/plain": { + "application/json": { "schema": { - "type": "string" + "$ref": "#/components/schemas/CreateCustomProviderResponse" } } } @@ -3696,6 +3696,17 @@ "$ref": "#/components/schemas/Message" } }, + "CreateCustomProviderResponse": { + "type": "object", + "required": [ + "provider_name" + ], + "properties": { + "provider_name": { + "type": "string" + } + } + }, "CreateRecipeRequest": { "type": "object", "required": [ diff --git a/ui/desktop/src/api/index.ts b/ui/desktop/src/api/index.ts index 9a24bb7ac0de..4602e1f05a8a 100644 --- a/ui/desktop/src/api/index.ts +++ b/ui/desktop/src/api/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts export { addExtension, agentAddExtension, agentRemoveExtension, backupConfig, callTool, cancelDownload, checkProvider, configureProviderOauth, confirmToolAction, createCustomProvider, createRecipe, createSchedule, decodeRecipe, deleteModel, deleteRecipe, deleteSchedule, deleteSession, detectProvider, diagnostics, downloadModel, encodeRecipe, exportApp, exportSession, forkSession, getCanonicalModelInfo, getCustomProvider, getDictationConfig, getDownloadProgress, getExtensions, getPrompt, getPrompts, getProviderModels, getSession, getSessionExtensions, getSessionInsights, getSlashCommands, getTools, getTunnelStatus, importApp, importSession, initConfig, inspectRunningJob, killRunningJob, listApps, listModels, listRecipes, listSchedules, listSessions, mcpUiProxy, type Options, parseRecipe, pauseSchedule, providers, readAllConfig, readConfig, readResource, recipeToYaml, recoverConfig, removeConfig, removeCustomProvider, removeExtension, reply, resetPrompt, restartAgent, resumeAgent, runNowHandler, savePrompt, saveRecipe, scanRecipe, scheduleRecipe, searchSessions, sendTelemetryEvent, sessionsHandler, setConfigProvider, setRecipeSlashCommand, startAgent, startOpenrouterSetup, startTetrateSetup, startTunnel, status, stopAgent, stopTunnel, systemInfo, transcribeDictation, unpauseSchedule, updateAgentProvider, updateCustomProvider, updateFromSession, updateSchedule, updateSessionName, updateSessionUserRecipeValues, updateWorkingDir, upsertConfig, upsertPermissions, validateConfig } from './sdk.gen'; -export type { ActionRequired, ActionRequiredData, AddExtensionData, AddExtensionErrors, AddExtensionRequest, AddExtensionResponse, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponse, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponse, AgentRemoveExtensionResponses, Annotations, Author, AuthorRequest, BackupConfigData, BackupConfigErrors, BackupConfigResponse, BackupConfigResponses, CallToolData, CallToolErrors, CallToolRequest, CallToolResponse, CallToolResponse2, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, ChatRequest, CheckProviderData, CheckProviderRequest, ClientOptions, CommandType, ConfigKey, ConfigKeyQuery, ConfigResponse, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionRequest, ConfirmToolActionResponses, Content, Conversation, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponse, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeRequest, CreateRecipeResponse, CreateRecipeResponse2, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleRequest, CreateScheduleResponse, CreateScheduleResponses, CspMetadata, DeclarativeProviderConfig, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeRequest, DecodeRecipeResponse, DecodeRecipeResponse2, DecodeRecipeResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeRequest, DeleteRecipeResponse, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponse, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderRequest, DetectProviderResponse, DetectProviderResponse2, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponse, DiagnosticsResponses, DictationProvider, DictationProviderStatus, DownloadModelData, DownloadModelErrors, DownloadModelResponses, DownloadProgress, DownloadStatus, EmbeddedResource, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeRequest, EncodeRecipeResponse, EncodeRecipeResponse2, EncodeRecipeResponses, Envs, ErrorResponse, ExportAppData, ExportAppError, ExportAppErrors, ExportAppResponse, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponse, ExportSessionResponses, ExtensionConfig, ExtensionData, ExtensionEntry, ExtensionLoadResult, ExtensionQuery, ExtensionResponse, ForkRequest, ForkResponse, ForkSessionData, ForkSessionErrors, ForkSessionResponse, ForkSessionResponses, FrontendToolRequest, GetCanonicalModelInfoData, GetCanonicalModelInfoResponse, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponse, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponse, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponse, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponse, GetExtensionsResponses, GetPromptData, GetPromptErrors, GetPromptResponse, GetPromptResponses, GetPromptsData, GetPromptsResponse, GetPromptsResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponse, GetProviderModelsResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponse, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponse, GetSessionInsightsResponses, GetSessionResponse, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponse, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsQuery, GetToolsResponse, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponse, GetTunnelStatusResponses, GooseApp, Icon, ImageContent, ImportAppData, ImportAppError, ImportAppErrors, ImportAppRequest, ImportAppResponse, ImportAppResponse2, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionRequest, ImportSessionResponse, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponse, InitConfigResponses, InspectJobResponse, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponse, InspectRunningJobResponses, JsonObject, KillJobResponse, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsError, ListAppsErrors, ListAppsRequest, ListAppsResponse, ListAppsResponse2, ListAppsResponses, ListModelsData, ListModelsResponse, ListModelsResponses, ListRecipeResponse, ListRecipesData, ListRecipesErrors, ListRecipesResponse, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponse, ListSchedulesResponse2, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponse, ListSessionsResponses, LoadedProvider, McpAppResource, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, Message, MessageContent, MessageEvent, MessageMetadata, ModelConfig, ModelInfo, ModelInfoData, ModelInfoQuery, ModelInfoResponse, ParseRecipeData, ParseRecipeError, ParseRecipeErrors, ParseRecipeRequest, ParseRecipeResponse, ParseRecipeResponse2, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponse, PauseScheduleResponses, Permission, PermissionLevel, PermissionsMetadata, PrincipalType, PromptContentResponse, PromptsListResponse, ProviderDetails, ProviderEngine, ProviderMetadata, ProvidersData, ProvidersResponse, ProvidersResponse2, ProvidersResponses, ProviderType, RawAudioContent, RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ReadAllConfigData, ReadAllConfigResponse, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceRequest, ReadResourceResponse, ReadResourceResponse2, ReadResourceResponses, ReasoningContent, Recipe, RecipeManifest, RecipeParameter, RecipeParameterInputType, RecipeParameterRequirement, RecipeToYamlData, RecipeToYamlError, RecipeToYamlErrors, RecipeToYamlRequest, RecipeToYamlResponse, RecipeToYamlResponse2, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponse, RecoverConfigResponses, RedactedThinkingContent, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponse, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponse, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionRequest, RemoveExtensionResponse, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponse, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponse, ResetPromptResponses, ResourceContents, ResourceMetadata, Response, RestartAgentData, RestartAgentErrors, RestartAgentRequest, RestartAgentResponse, RestartAgentResponse2, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentRequest, ResumeAgentResponse, ResumeAgentResponse2, ResumeAgentResponses, RetryConfig, Role, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponse, RunNowHandlerResponses, RunNowResponse, SavePromptData, SavePromptErrors, SavePromptRequest, SavePromptResponse, SavePromptResponses, SaveRecipeData, SaveRecipeError, SaveRecipeErrors, SaveRecipeRequest, SaveRecipeResponse, SaveRecipeResponse2, SaveRecipeResponses, ScanRecipeData, ScanRecipeRequest, ScanRecipeResponse, ScanRecipeResponse2, ScanRecipeResponses, ScheduledJob, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeRequest, ScheduleRecipeResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponse, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, Session, SessionDisplayInfo, SessionExtensionsResponse, SessionInsights, SessionListResponse, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponse, SessionsHandlerResponses, SessionsQuery, SessionType, SetConfigProviderData, SetProviderRequest, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, SetSlashCommandRequest, Settings, SetupResponse, SlashCommand, SlashCommandsResponse, StartAgentData, StartAgentError, StartAgentErrors, StartAgentRequest, StartAgentResponse, StartAgentResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponse, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponse, StartTetrateSetupResponses, StartTunnelData, StartTunnelError, StartTunnelErrors, StartTunnelResponse, StartTunnelResponses, StatusData, StatusResponse, StatusResponses, StopAgentData, StopAgentErrors, StopAgentRequest, StopAgentResponse, StopAgentResponses, StopTunnelData, StopTunnelError, StopTunnelErrors, StopTunnelResponses, SubRecipe, SuccessCheck, SystemInfo, SystemInfoData, SystemInfoResponse, SystemInfoResponses, SystemNotificationContent, SystemNotificationType, TaskSupport, TelemetryEventRequest, Template, TextContent, ThinkingContent, TokenState, Tool, ToolAnnotations, ToolConfirmationRequest, ToolExecution, ToolInfo, ToolPermission, ToolRequest, ToolResponse, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponse, TranscribeDictationResponses, TranscribeRequest, TranscribeResponse, TunnelInfo, TunnelState, UiMetadata, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponse, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderRequest, UpdateCustomProviderResponse, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionRequest, UpdateFromSessionResponses, UpdateProviderRequest, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleRequest, UpdateScheduleResponse, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameRequest, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesError, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesRequest, UpdateSessionUserRecipeValuesResponse, UpdateSessionUserRecipeValuesResponse2, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirRequest, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigQuery, UpsertConfigResponse, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsQuery, UpsertPermissionsResponse, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponse, ValidateConfigResponses, WhisperModelResponse, WindowProps } from './types.gen'; +export type { ActionRequired, ActionRequiredData, AddExtensionData, AddExtensionErrors, AddExtensionRequest, AddExtensionResponse, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponse, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponse, AgentRemoveExtensionResponses, Annotations, Author, AuthorRequest, BackupConfigData, BackupConfigErrors, BackupConfigResponse, BackupConfigResponses, CallToolData, CallToolErrors, CallToolRequest, CallToolResponse, CallToolResponse2, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, ChatRequest, CheckProviderData, CheckProviderRequest, ClientOptions, CommandType, ConfigKey, ConfigKeyQuery, ConfigResponse, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionRequest, ConfirmToolActionResponses, Content, Conversation, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponse, CreateCustomProviderResponse2, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeRequest, CreateRecipeResponse, CreateRecipeResponse2, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleRequest, CreateScheduleResponse, CreateScheduleResponses, CspMetadata, DeclarativeProviderConfig, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeRequest, DecodeRecipeResponse, DecodeRecipeResponse2, DecodeRecipeResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeRequest, DeleteRecipeResponse, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponse, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderRequest, DetectProviderResponse, DetectProviderResponse2, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponse, DiagnosticsResponses, DictationProvider, DictationProviderStatus, DownloadModelData, DownloadModelErrors, DownloadModelResponses, DownloadProgress, DownloadStatus, EmbeddedResource, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeRequest, EncodeRecipeResponse, EncodeRecipeResponse2, EncodeRecipeResponses, Envs, ErrorResponse, ExportAppData, ExportAppError, ExportAppErrors, ExportAppResponse, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponse, ExportSessionResponses, ExtensionConfig, ExtensionData, ExtensionEntry, ExtensionLoadResult, ExtensionQuery, ExtensionResponse, ForkRequest, ForkResponse, ForkSessionData, ForkSessionErrors, ForkSessionResponse, ForkSessionResponses, FrontendToolRequest, GetCanonicalModelInfoData, GetCanonicalModelInfoResponse, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponse, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponse, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponse, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponse, GetExtensionsResponses, GetPromptData, GetPromptErrors, GetPromptResponse, GetPromptResponses, GetPromptsData, GetPromptsResponse, GetPromptsResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponse, GetProviderModelsResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponse, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponse, GetSessionInsightsResponses, GetSessionResponse, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponse, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsQuery, GetToolsResponse, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponse, GetTunnelStatusResponses, GooseApp, Icon, ImageContent, ImportAppData, ImportAppError, ImportAppErrors, ImportAppRequest, ImportAppResponse, ImportAppResponse2, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionRequest, ImportSessionResponse, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponse, InitConfigResponses, InspectJobResponse, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponse, InspectRunningJobResponses, JsonObject, KillJobResponse, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsError, ListAppsErrors, ListAppsRequest, ListAppsResponse, ListAppsResponse2, ListAppsResponses, ListModelsData, ListModelsResponse, ListModelsResponses, ListRecipeResponse, ListRecipesData, ListRecipesErrors, ListRecipesResponse, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponse, ListSchedulesResponse2, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponse, ListSessionsResponses, LoadedProvider, McpAppResource, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, Message, MessageContent, MessageEvent, MessageMetadata, ModelConfig, ModelInfo, ModelInfoData, ModelInfoQuery, ModelInfoResponse, ParseRecipeData, ParseRecipeError, ParseRecipeErrors, ParseRecipeRequest, ParseRecipeResponse, ParseRecipeResponse2, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponse, PauseScheduleResponses, Permission, PermissionLevel, PermissionsMetadata, PrincipalType, PromptContentResponse, PromptsListResponse, ProviderDetails, ProviderEngine, ProviderMetadata, ProvidersData, ProvidersResponse, ProvidersResponse2, ProvidersResponses, ProviderType, RawAudioContent, RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ReadAllConfigData, ReadAllConfigResponse, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceRequest, ReadResourceResponse, ReadResourceResponse2, ReadResourceResponses, ReasoningContent, Recipe, RecipeManifest, RecipeParameter, RecipeParameterInputType, RecipeParameterRequirement, RecipeToYamlData, RecipeToYamlError, RecipeToYamlErrors, RecipeToYamlRequest, RecipeToYamlResponse, RecipeToYamlResponse2, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponse, RecoverConfigResponses, RedactedThinkingContent, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponse, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponse, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionRequest, RemoveExtensionResponse, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponse, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponse, ResetPromptResponses, ResourceContents, ResourceMetadata, Response, RestartAgentData, RestartAgentErrors, RestartAgentRequest, RestartAgentResponse, RestartAgentResponse2, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentRequest, ResumeAgentResponse, ResumeAgentResponse2, ResumeAgentResponses, RetryConfig, Role, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponse, RunNowHandlerResponses, RunNowResponse, SavePromptData, SavePromptErrors, SavePromptRequest, SavePromptResponse, SavePromptResponses, SaveRecipeData, SaveRecipeError, SaveRecipeErrors, SaveRecipeRequest, SaveRecipeResponse, SaveRecipeResponse2, SaveRecipeResponses, ScanRecipeData, ScanRecipeRequest, ScanRecipeResponse, ScanRecipeResponse2, ScanRecipeResponses, ScheduledJob, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeRequest, ScheduleRecipeResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponse, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, Session, SessionDisplayInfo, SessionExtensionsResponse, SessionInsights, SessionListResponse, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponse, SessionsHandlerResponses, SessionsQuery, SessionType, SetConfigProviderData, SetProviderRequest, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, SetSlashCommandRequest, Settings, SetupResponse, SlashCommand, SlashCommandsResponse, StartAgentData, StartAgentError, StartAgentErrors, StartAgentRequest, StartAgentResponse, StartAgentResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponse, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponse, StartTetrateSetupResponses, StartTunnelData, StartTunnelError, StartTunnelErrors, StartTunnelResponse, StartTunnelResponses, StatusData, StatusResponse, StatusResponses, StopAgentData, StopAgentErrors, StopAgentRequest, StopAgentResponse, StopAgentResponses, StopTunnelData, StopTunnelError, StopTunnelErrors, StopTunnelResponses, SubRecipe, SuccessCheck, SystemInfo, SystemInfoData, SystemInfoResponse, SystemInfoResponses, SystemNotificationContent, SystemNotificationType, TaskSupport, TelemetryEventRequest, Template, TextContent, ThinkingContent, TokenState, Tool, ToolAnnotations, ToolConfirmationRequest, ToolExecution, ToolInfo, ToolPermission, ToolRequest, ToolResponse, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponse, TranscribeDictationResponses, TranscribeRequest, TranscribeResponse, TunnelInfo, TunnelState, UiMetadata, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponse, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderRequest, UpdateCustomProviderResponse, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionRequest, UpdateFromSessionResponses, UpdateProviderRequest, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleRequest, UpdateScheduleResponse, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameRequest, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesError, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesRequest, UpdateSessionUserRecipeValuesResponse, UpdateSessionUserRecipeValuesResponse2, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirRequest, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigQuery, UpsertConfigResponse, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsQuery, UpsertPermissionsResponse, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponse, ValidateConfigResponses, WhisperModelResponse, WindowProps } from './types.gen'; diff --git a/ui/desktop/src/api/types.gen.ts b/ui/desktop/src/api/types.gen.ts index 6450f7fd4f61..684527b25d40 100644 --- a/ui/desktop/src/api/types.gen.ts +++ b/ui/desktop/src/api/types.gen.ts @@ -127,6 +127,10 @@ export type Content = RawTextContent | RawImageContent | RawEmbeddedResource | R export type Conversation = Array; +export type CreateCustomProviderResponse = { + provider_name: string; +}; + export type CreateRecipeRequest = { author?: AuthorRequest | null; session_id: string; @@ -2028,10 +2032,10 @@ export type CreateCustomProviderResponses = { /** * Custom provider created successfully */ - 200: string; + 200: CreateCustomProviderResponse; }; -export type CreateCustomProviderResponse = CreateCustomProviderResponses[keyof CreateCustomProviderResponses]; +export type CreateCustomProviderResponse2 = CreateCustomProviderResponses[keyof CreateCustomProviderResponses]; export type RemoveCustomProviderData = { body?: never; diff --git a/ui/desktop/src/components/onboarding/ProviderSelector.tsx b/ui/desktop/src/components/onboarding/ProviderSelector.tsx index 769a060b9857..75ef085704ab 100644 --- a/ui/desktop/src/components/onboarding/ProviderSelector.tsx +++ b/ui/desktop/src/components/onboarding/ProviderSelector.tsx @@ -89,11 +89,8 @@ export default function ProviderSelector({ const handleCreateCustomProvider = async (data: UpdateCustomProviderRequest) => { const result = await createCustomProvider({ body: data, throwOnError: true }); setShowCustomModal(false); - // API returns "Custom provider added - ID: ", extract the ID - const message = result.data as string; - const providerId = message.split('ID: ').pop() || ''; - if (providerId) { - onConfigured(providerId); + if (result.data?.provider_name) { + onConfigured(result.data.provider_name); } }; From 46fa106aa9c9c26b55e5ea3146b7e0489efc0301 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Thu, 19 Feb 2026 15:59:32 +1100 Subject: [PATCH 15/41] enable nanogpt device login flow --- crates/goose-server/src/openapi.rs | 1 + crates/goose-server/src/routes/setup.rs | 33 +++++ crates/goose/src/config/mod.rs | 2 + crates/goose/src/config/signup_nanogpt/mod.rs | 124 ++++++++++++++++++ ui/desktop/openapi.json | 20 +++ ui/desktop/src/api/index.ts | 4 +- ui/desktop/src/api/sdk.gen.ts | 4 +- ui/desktop/src/api/types.gen.ts | 13 ++ .../components/onboarding/FreeCreditCards.tsx | 32 ++++- ui/desktop/src/utils/nanogptSetup.ts | 12 ++ 10 files changed, 238 insertions(+), 7 deletions(-) create mode 100644 crates/goose/src/config/signup_nanogpt/mod.rs create mode 100644 ui/desktop/src/utils/nanogptSetup.ts diff --git a/crates/goose-server/src/openapi.rs b/crates/goose-server/src/openapi.rs index fa9a0fa131a0..cc3de74b032b 100644 --- a/crates/goose-server/src/openapi.rs +++ b/crates/goose-server/src/openapi.rs @@ -413,6 +413,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, diff --git a/crates/goose-server/src/routes/setup.rs b/crates/goose-server/src/routes/setup.rs index fbf9ef01e79e..165a20e2e77b 100644 --- a/crates/goose-server/src/routes/setup.rs +++ b/crates/goose-server/src/routes/setup.rs @@ -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) -> 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) } @@ -88,3 +90,34 @@ async fn start_tetrate_setup() -> Result, ErrorResponse> { })), } } + +#[utoipa::path( + post, + path = "/handle_nanogpt", + responses( + (status = 200, body=SetupResponse) + ), +)] +async fn start_nanogpt_setup() -> Result, 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: format!("Setup failed: {}", e), + })), + } +} diff --git a/crates/goose/src/config/mod.rs b/crates/goose/src/config/mod.rs index e73349745d21..8fca0d134e73 100644 --- a/crates/goose/src/config/mod.rs +++ b/crates/goose/src/config/mod.rs @@ -7,6 +7,7 @@ mod migrations; pub mod paths; pub mod permission; pub mod search_path; +pub mod signup_nanogpt; pub mod signup_openrouter; pub mod signup_tetrate; @@ -21,6 +22,7 @@ pub use extensions::{ }; pub use goose_mode::GooseMode; pub use permission::PermissionManager; +pub use signup_nanogpt::configure_nanogpt; pub use signup_openrouter::configure_openrouter; pub use signup_tetrate::configure_tetrate; diff --git a/crates/goose/src/config/signup_nanogpt/mod.rs b/crates/goose/src/config/signup_nanogpt/mod.rs new file mode 100644 index 000000000000..e5d954cc9e79 --- /dev/null +++ b/crates/goose/src/config/signup_nanogpt/mod.rs @@ -0,0 +1,124 @@ +use anyhow::{anyhow, Result}; +use reqwest::Client; +use serde::{Deserialize, Serialize}; +use std::time::Duration; +use tokio::time::{sleep, timeout}; + +use crate::config::Config; + +/// Default model for NanoGPT configuration +pub const NANOGPT_DEFAULT_MODEL: &str = "openai/gpt-4.1-nano"; + +const NANOGPT_START_URL: &str = "https://nano-gpt.com/api/cli-login/start"; +const NANOGPT_POLL_URL: &str = "https://nano-gpt.com/api/cli-login/poll"; +const AUTH_TIMEOUT: Duration = Duration::from_secs(600); // 10 minutes +const POLL_INTERVAL: Duration = Duration::from_secs(2); + +#[derive(Debug, Serialize)] +struct StartRequest { + client_name: String, +} + +#[derive(Debug, Deserialize)] +struct StartResponse { + device_code: String, + verification_uri_complete: String, +} + +#[derive(Debug, Serialize)] +struct PollRequest { + device_code: String, +} + +#[derive(Debug, Deserialize)] +struct PollResponse { + key: String, +} + +async fn poll_for_token(device_code: &str) -> Result { + let client = Client::new(); + + loop { + sleep(POLL_INTERVAL).await; + + let body = PollRequest { + device_code: device_code.to_string(), + }; + + let response = client.post(NANOGPT_POLL_URL).json(&body).send().await?; + + match response.status().as_u16() { + 200 => { + let poll_resp: PollResponse = response.json().await?; + return Ok(poll_resp.key); + } + 202 => { + // Authorization pending, continue polling + continue; + } + 410 => { + return Err(anyhow!("Device code has expired - please try again")); + } + 409 => { + return Err(anyhow!("Device code has already been consumed")); + } + 404 => { + return Err(anyhow!("Invalid device code")); + } + other => { + let error_text = response.text().await.unwrap_or_default(); + return Err(anyhow!( + "Unexpected poll response: {} - {}", + other, + error_text + )); + } + } + } +} + +pub async fn complete_nanogpt_auth() -> Result { + let client = Client::new(); + let body = StartRequest { + client_name: "goose".to_string(), + }; + + let response = client.post(NANOGPT_START_URL).json(&body).send().await?; + + if !response.status().is_success() { + let status = response.status(); + let error_text = response.text().await.unwrap_or_default(); + return Err(anyhow!( + "Failed to start NanoGPT device flow: {} - {}", + status, + error_text + )); + } + + let start_resp: StartResponse = response.json().await?; + + println!("Opening browser for NanoGPT authentication..."); + + if let Err(e) = webbrowser::open(&start_resp.verification_uri_complete) { + eprintln!("Failed to open browser automatically: {}", e); + println!( + "Please open this URL manually: {}", + start_resp.verification_uri_complete + ); + } + + println!("Waiting for NanoGPT authorization..."); + + match timeout(AUTH_TIMEOUT, poll_for_token(&start_resp.device_code)).await { + Ok(Ok(api_key)) => Ok(api_key), + Ok(Err(e)) => Err(e), + Err(_) => Err(anyhow!("Authentication timed out - please try again")), + } +} + +pub fn configure_nanogpt(config: &Config, api_key: String) -> Result<()> { + config.set_secret("NANOGPT_API_KEY", &api_key)?; + config.set_goose_provider("nanogpt")?; + config.set_goose_model(NANOGPT_DEFAULT_MODEL)?; + Ok(()) +} diff --git a/ui/desktop/openapi.json b/ui/desktop/openapi.json index 466140ae4028..e152ca8bc6d8 100644 --- a/ui/desktop/openapi.json +++ b/ui/desktop/openapi.json @@ -1787,6 +1787,26 @@ } } }, + "/handle_nanogpt": { + "post": { + "tags": [ + "super::routes::setup" + ], + "operationId": "start_nanogpt_setup", + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SetupResponse" + } + } + } + } + } + } + }, "/handle_openrouter": { "post": { "tags": [ diff --git a/ui/desktop/src/api/index.ts b/ui/desktop/src/api/index.ts index 4602e1f05a8a..a8467b5aa63a 100644 --- a/ui/desktop/src/api/index.ts +++ b/ui/desktop/src/api/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { addExtension, agentAddExtension, agentRemoveExtension, backupConfig, callTool, cancelDownload, checkProvider, configureProviderOauth, confirmToolAction, createCustomProvider, createRecipe, createSchedule, decodeRecipe, deleteModel, deleteRecipe, deleteSchedule, deleteSession, detectProvider, diagnostics, downloadModel, encodeRecipe, exportApp, exportSession, forkSession, getCanonicalModelInfo, getCustomProvider, getDictationConfig, getDownloadProgress, getExtensions, getPrompt, getPrompts, getProviderModels, getSession, getSessionExtensions, getSessionInsights, getSlashCommands, getTools, getTunnelStatus, importApp, importSession, initConfig, inspectRunningJob, killRunningJob, listApps, listModels, listRecipes, listSchedules, listSessions, mcpUiProxy, type Options, parseRecipe, pauseSchedule, providers, readAllConfig, readConfig, readResource, recipeToYaml, recoverConfig, removeConfig, removeCustomProvider, removeExtension, reply, resetPrompt, restartAgent, resumeAgent, runNowHandler, savePrompt, saveRecipe, scanRecipe, scheduleRecipe, searchSessions, sendTelemetryEvent, sessionsHandler, setConfigProvider, setRecipeSlashCommand, startAgent, startOpenrouterSetup, startTetrateSetup, startTunnel, status, stopAgent, stopTunnel, systemInfo, transcribeDictation, unpauseSchedule, updateAgentProvider, updateCustomProvider, updateFromSession, updateSchedule, updateSessionName, updateSessionUserRecipeValues, updateWorkingDir, upsertConfig, upsertPermissions, validateConfig } from './sdk.gen'; -export type { ActionRequired, ActionRequiredData, AddExtensionData, AddExtensionErrors, AddExtensionRequest, AddExtensionResponse, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponse, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponse, AgentRemoveExtensionResponses, Annotations, Author, AuthorRequest, BackupConfigData, BackupConfigErrors, BackupConfigResponse, BackupConfigResponses, CallToolData, CallToolErrors, CallToolRequest, CallToolResponse, CallToolResponse2, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, ChatRequest, CheckProviderData, CheckProviderRequest, ClientOptions, CommandType, ConfigKey, ConfigKeyQuery, ConfigResponse, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionRequest, ConfirmToolActionResponses, Content, Conversation, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponse, CreateCustomProviderResponse2, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeRequest, CreateRecipeResponse, CreateRecipeResponse2, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleRequest, CreateScheduleResponse, CreateScheduleResponses, CspMetadata, DeclarativeProviderConfig, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeRequest, DecodeRecipeResponse, DecodeRecipeResponse2, DecodeRecipeResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeRequest, DeleteRecipeResponse, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponse, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderRequest, DetectProviderResponse, DetectProviderResponse2, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponse, DiagnosticsResponses, DictationProvider, DictationProviderStatus, DownloadModelData, DownloadModelErrors, DownloadModelResponses, DownloadProgress, DownloadStatus, EmbeddedResource, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeRequest, EncodeRecipeResponse, EncodeRecipeResponse2, EncodeRecipeResponses, Envs, ErrorResponse, ExportAppData, ExportAppError, ExportAppErrors, ExportAppResponse, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponse, ExportSessionResponses, ExtensionConfig, ExtensionData, ExtensionEntry, ExtensionLoadResult, ExtensionQuery, ExtensionResponse, ForkRequest, ForkResponse, ForkSessionData, ForkSessionErrors, ForkSessionResponse, ForkSessionResponses, FrontendToolRequest, GetCanonicalModelInfoData, GetCanonicalModelInfoResponse, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponse, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponse, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponse, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponse, GetExtensionsResponses, GetPromptData, GetPromptErrors, GetPromptResponse, GetPromptResponses, GetPromptsData, GetPromptsResponse, GetPromptsResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponse, GetProviderModelsResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponse, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponse, GetSessionInsightsResponses, GetSessionResponse, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponse, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsQuery, GetToolsResponse, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponse, GetTunnelStatusResponses, GooseApp, Icon, ImageContent, ImportAppData, ImportAppError, ImportAppErrors, ImportAppRequest, ImportAppResponse, ImportAppResponse2, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionRequest, ImportSessionResponse, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponse, InitConfigResponses, InspectJobResponse, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponse, InspectRunningJobResponses, JsonObject, KillJobResponse, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsError, ListAppsErrors, ListAppsRequest, ListAppsResponse, ListAppsResponse2, ListAppsResponses, ListModelsData, ListModelsResponse, ListModelsResponses, ListRecipeResponse, ListRecipesData, ListRecipesErrors, ListRecipesResponse, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponse, ListSchedulesResponse2, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponse, ListSessionsResponses, LoadedProvider, McpAppResource, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, Message, MessageContent, MessageEvent, MessageMetadata, ModelConfig, ModelInfo, ModelInfoData, ModelInfoQuery, ModelInfoResponse, ParseRecipeData, ParseRecipeError, ParseRecipeErrors, ParseRecipeRequest, ParseRecipeResponse, ParseRecipeResponse2, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponse, PauseScheduleResponses, Permission, PermissionLevel, PermissionsMetadata, PrincipalType, PromptContentResponse, PromptsListResponse, ProviderDetails, ProviderEngine, ProviderMetadata, ProvidersData, ProvidersResponse, ProvidersResponse2, ProvidersResponses, ProviderType, RawAudioContent, RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ReadAllConfigData, ReadAllConfigResponse, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceRequest, ReadResourceResponse, ReadResourceResponse2, ReadResourceResponses, ReasoningContent, Recipe, RecipeManifest, RecipeParameter, RecipeParameterInputType, RecipeParameterRequirement, RecipeToYamlData, RecipeToYamlError, RecipeToYamlErrors, RecipeToYamlRequest, RecipeToYamlResponse, RecipeToYamlResponse2, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponse, RecoverConfigResponses, RedactedThinkingContent, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponse, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponse, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionRequest, RemoveExtensionResponse, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponse, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponse, ResetPromptResponses, ResourceContents, ResourceMetadata, Response, RestartAgentData, RestartAgentErrors, RestartAgentRequest, RestartAgentResponse, RestartAgentResponse2, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentRequest, ResumeAgentResponse, ResumeAgentResponse2, ResumeAgentResponses, RetryConfig, Role, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponse, RunNowHandlerResponses, RunNowResponse, SavePromptData, SavePromptErrors, SavePromptRequest, SavePromptResponse, SavePromptResponses, SaveRecipeData, SaveRecipeError, SaveRecipeErrors, SaveRecipeRequest, SaveRecipeResponse, SaveRecipeResponse2, SaveRecipeResponses, ScanRecipeData, ScanRecipeRequest, ScanRecipeResponse, ScanRecipeResponse2, ScanRecipeResponses, ScheduledJob, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeRequest, ScheduleRecipeResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponse, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, Session, SessionDisplayInfo, SessionExtensionsResponse, SessionInsights, SessionListResponse, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponse, SessionsHandlerResponses, SessionsQuery, SessionType, SetConfigProviderData, SetProviderRequest, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, SetSlashCommandRequest, Settings, SetupResponse, SlashCommand, SlashCommandsResponse, StartAgentData, StartAgentError, StartAgentErrors, StartAgentRequest, StartAgentResponse, StartAgentResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponse, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponse, StartTetrateSetupResponses, StartTunnelData, StartTunnelError, StartTunnelErrors, StartTunnelResponse, StartTunnelResponses, StatusData, StatusResponse, StatusResponses, StopAgentData, StopAgentErrors, StopAgentRequest, StopAgentResponse, StopAgentResponses, StopTunnelData, StopTunnelError, StopTunnelErrors, StopTunnelResponses, SubRecipe, SuccessCheck, SystemInfo, SystemInfoData, SystemInfoResponse, SystemInfoResponses, SystemNotificationContent, SystemNotificationType, TaskSupport, TelemetryEventRequest, Template, TextContent, ThinkingContent, TokenState, Tool, ToolAnnotations, ToolConfirmationRequest, ToolExecution, ToolInfo, ToolPermission, ToolRequest, ToolResponse, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponse, TranscribeDictationResponses, TranscribeRequest, TranscribeResponse, TunnelInfo, TunnelState, UiMetadata, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponse, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderRequest, UpdateCustomProviderResponse, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionRequest, UpdateFromSessionResponses, UpdateProviderRequest, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleRequest, UpdateScheduleResponse, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameRequest, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesError, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesRequest, UpdateSessionUserRecipeValuesResponse, UpdateSessionUserRecipeValuesResponse2, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirRequest, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigQuery, UpsertConfigResponse, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsQuery, UpsertPermissionsResponse, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponse, ValidateConfigResponses, WhisperModelResponse, WindowProps } from './types.gen'; +export { addExtension, agentAddExtension, agentRemoveExtension, backupConfig, callTool, cancelDownload, checkProvider, configureProviderOauth, confirmToolAction, createCustomProvider, createRecipe, createSchedule, decodeRecipe, deleteModel, deleteRecipe, deleteSchedule, deleteSession, detectProvider, diagnostics, downloadModel, encodeRecipe, exportApp, exportSession, forkSession, getCanonicalModelInfo, getCustomProvider, getDictationConfig, getDownloadProgress, getExtensions, getPrompt, getPrompts, getProviderModels, getSession, getSessionExtensions, getSessionInsights, getSlashCommands, getTools, getTunnelStatus, importApp, importSession, initConfig, inspectRunningJob, killRunningJob, listApps, listModels, listRecipes, listSchedules, listSessions, mcpUiProxy, type Options, parseRecipe, pauseSchedule, providers, readAllConfig, readConfig, readResource, recipeToYaml, recoverConfig, removeConfig, removeCustomProvider, removeExtension, reply, resetPrompt, restartAgent, resumeAgent, runNowHandler, savePrompt, saveRecipe, scanRecipe, scheduleRecipe, searchSessions, sendTelemetryEvent, sessionsHandler, setConfigProvider, setRecipeSlashCommand, startAgent, startNanogptSetup, startOpenrouterSetup, startTetrateSetup, startTunnel, status, stopAgent, stopTunnel, systemInfo, transcribeDictation, unpauseSchedule, updateAgentProvider, updateCustomProvider, updateFromSession, updateSchedule, updateSessionName, updateSessionUserRecipeValues, updateWorkingDir, upsertConfig, upsertPermissions, validateConfig } from './sdk.gen'; +export type { ActionRequired, ActionRequiredData, AddExtensionData, AddExtensionErrors, AddExtensionRequest, AddExtensionResponse, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponse, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponse, AgentRemoveExtensionResponses, Annotations, Author, AuthorRequest, BackupConfigData, BackupConfigErrors, BackupConfigResponse, BackupConfigResponses, CallToolData, CallToolErrors, CallToolRequest, CallToolResponse, CallToolResponse2, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, ChatRequest, CheckProviderData, CheckProviderRequest, ClientOptions, CommandType, ConfigKey, ConfigKeyQuery, ConfigResponse, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionRequest, ConfirmToolActionResponses, Content, Conversation, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponse, CreateCustomProviderResponse2, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeRequest, CreateRecipeResponse, CreateRecipeResponse2, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleRequest, CreateScheduleResponse, CreateScheduleResponses, CspMetadata, DeclarativeProviderConfig, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeRequest, DecodeRecipeResponse, DecodeRecipeResponse2, DecodeRecipeResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeRequest, DeleteRecipeResponse, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponse, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderRequest, DetectProviderResponse, DetectProviderResponse2, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponse, DiagnosticsResponses, DictationProvider, DictationProviderStatus, DownloadModelData, DownloadModelErrors, DownloadModelResponses, DownloadProgress, DownloadStatus, EmbeddedResource, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeRequest, EncodeRecipeResponse, EncodeRecipeResponse2, EncodeRecipeResponses, Envs, ErrorResponse, ExportAppData, ExportAppError, ExportAppErrors, ExportAppResponse, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponse, ExportSessionResponses, ExtensionConfig, ExtensionData, ExtensionEntry, ExtensionLoadResult, ExtensionQuery, ExtensionResponse, ForkRequest, ForkResponse, ForkSessionData, ForkSessionErrors, ForkSessionResponse, ForkSessionResponses, FrontendToolRequest, GetCanonicalModelInfoData, GetCanonicalModelInfoResponse, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponse, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponse, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponse, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponse, GetExtensionsResponses, GetPromptData, GetPromptErrors, GetPromptResponse, GetPromptResponses, GetPromptsData, GetPromptsResponse, GetPromptsResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponse, GetProviderModelsResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponse, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponse, GetSessionInsightsResponses, GetSessionResponse, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponse, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsQuery, GetToolsResponse, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponse, GetTunnelStatusResponses, GooseApp, Icon, ImageContent, ImportAppData, ImportAppError, ImportAppErrors, ImportAppRequest, ImportAppResponse, ImportAppResponse2, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionRequest, ImportSessionResponse, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponse, InitConfigResponses, InspectJobResponse, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponse, InspectRunningJobResponses, JsonObject, KillJobResponse, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsError, ListAppsErrors, ListAppsRequest, ListAppsResponse, ListAppsResponse2, ListAppsResponses, ListModelsData, ListModelsResponse, ListModelsResponses, ListRecipeResponse, ListRecipesData, ListRecipesErrors, ListRecipesResponse, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponse, ListSchedulesResponse2, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponse, ListSessionsResponses, LoadedProvider, McpAppResource, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, Message, MessageContent, MessageEvent, MessageMetadata, ModelConfig, ModelInfo, ModelInfoData, ModelInfoQuery, ModelInfoResponse, ParseRecipeData, ParseRecipeError, ParseRecipeErrors, ParseRecipeRequest, ParseRecipeResponse, ParseRecipeResponse2, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponse, PauseScheduleResponses, Permission, PermissionLevel, PermissionsMetadata, PrincipalType, PromptContentResponse, PromptsListResponse, ProviderDetails, ProviderEngine, ProviderMetadata, ProvidersData, ProvidersResponse, ProvidersResponse2, ProvidersResponses, ProviderType, RawAudioContent, RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ReadAllConfigData, ReadAllConfigResponse, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceRequest, ReadResourceResponse, ReadResourceResponse2, ReadResourceResponses, ReasoningContent, Recipe, RecipeManifest, RecipeParameter, RecipeParameterInputType, RecipeParameterRequirement, RecipeToYamlData, RecipeToYamlError, RecipeToYamlErrors, RecipeToYamlRequest, RecipeToYamlResponse, RecipeToYamlResponse2, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponse, RecoverConfigResponses, RedactedThinkingContent, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponse, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponse, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionRequest, RemoveExtensionResponse, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponse, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponse, ResetPromptResponses, ResourceContents, ResourceMetadata, Response, RestartAgentData, RestartAgentErrors, RestartAgentRequest, RestartAgentResponse, RestartAgentResponse2, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentRequest, ResumeAgentResponse, ResumeAgentResponse2, ResumeAgentResponses, RetryConfig, Role, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponse, RunNowHandlerResponses, RunNowResponse, SavePromptData, SavePromptErrors, SavePromptRequest, SavePromptResponse, SavePromptResponses, SaveRecipeData, SaveRecipeError, SaveRecipeErrors, SaveRecipeRequest, SaveRecipeResponse, SaveRecipeResponse2, SaveRecipeResponses, ScanRecipeData, ScanRecipeRequest, ScanRecipeResponse, ScanRecipeResponse2, ScanRecipeResponses, ScheduledJob, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeRequest, ScheduleRecipeResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponse, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, Session, SessionDisplayInfo, SessionExtensionsResponse, SessionInsights, SessionListResponse, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponse, SessionsHandlerResponses, SessionsQuery, SessionType, SetConfigProviderData, SetProviderRequest, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, SetSlashCommandRequest, Settings, SetupResponse, SlashCommand, SlashCommandsResponse, StartAgentData, StartAgentError, StartAgentErrors, StartAgentRequest, StartAgentResponse, StartAgentResponses, StartNanogptSetupData, StartNanogptSetupResponse, StartNanogptSetupResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponse, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponse, StartTetrateSetupResponses, StartTunnelData, StartTunnelError, StartTunnelErrors, StartTunnelResponse, StartTunnelResponses, StatusData, StatusResponse, StatusResponses, StopAgentData, StopAgentErrors, StopAgentRequest, StopAgentResponse, StopAgentResponses, StopTunnelData, StopTunnelError, StopTunnelErrors, StopTunnelResponses, SubRecipe, SuccessCheck, SystemInfo, SystemInfoData, SystemInfoResponse, SystemInfoResponses, SystemNotificationContent, SystemNotificationType, TaskSupport, TelemetryEventRequest, Template, TextContent, ThinkingContent, TokenState, Tool, ToolAnnotations, ToolConfirmationRequest, ToolExecution, ToolInfo, ToolPermission, ToolRequest, ToolResponse, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponse, TranscribeDictationResponses, TranscribeRequest, TranscribeResponse, TunnelInfo, TunnelState, UiMetadata, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponse, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderRequest, UpdateCustomProviderResponse, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionRequest, UpdateFromSessionResponses, UpdateProviderRequest, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleRequest, UpdateScheduleResponse, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameRequest, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesError, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesRequest, UpdateSessionUserRecipeValuesResponse, UpdateSessionUserRecipeValuesResponse2, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirRequest, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigQuery, UpsertConfigResponse, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsQuery, UpsertPermissionsResponse, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponse, ValidateConfigResponses, WhisperModelResponse, WindowProps } from './types.gen'; diff --git a/ui/desktop/src/api/sdk.gen.ts b/ui/desktop/src/api/sdk.gen.ts index 012124b3b4f3..269bb0d99d8e 100644 --- a/ui/desktop/src/api/sdk.gen.ts +++ b/ui/desktop/src/api/sdk.gen.ts @@ -2,7 +2,7 @@ import type { Client, Options as Options2, TDataShape } from './client'; import { client } from './client.gen'; -import type { AddExtensionData, AddExtensionErrors, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponses, BackupConfigData, BackupConfigErrors, BackupConfigResponses, CallToolData, CallToolErrors, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CheckProviderData, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionResponses, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleResponses, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponses, DownloadModelData, DownloadModelErrors, DownloadModelResponses, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeResponses, ExportAppData, ExportAppErrors, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponses, ForkSessionData, ForkSessionErrors, ForkSessionResponses, GetCanonicalModelInfoData, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponses, GetPromptData, GetPromptErrors, GetPromptResponses, GetPromptsData, GetPromptsResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponses, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponses, ImportAppData, ImportAppErrors, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponses, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponses, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsErrors, ListAppsResponses, ListModelsData, ListModelsResponses, ListRecipesData, ListRecipesErrors, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponses, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, ParseRecipeData, ParseRecipeErrors, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponses, ProvidersData, ProvidersResponses, ReadAllConfigData, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceResponses, RecipeToYamlData, RecipeToYamlErrors, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponses, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponses, RestartAgentData, RestartAgentErrors, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentResponses, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponses, SavePromptData, SavePromptErrors, SavePromptResponses, SaveRecipeData, SaveRecipeErrors, SaveRecipeResponses, ScanRecipeData, ScanRecipeResponses, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponses, SetConfigProviderData, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, StartAgentData, StartAgentErrors, StartAgentResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, StartTunnelData, StartTunnelErrors, StartTunnelResponses, StatusData, StatusResponses, StopAgentData, StopAgentErrors, StopAgentResponses, StopTunnelData, StopTunnelErrors, StopTunnelResponses, SystemInfoData, SystemInfoResponses, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponses, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionResponses, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponses } from './types.gen'; +import type { AddExtensionData, AddExtensionErrors, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponses, BackupConfigData, BackupConfigErrors, BackupConfigResponses, CallToolData, CallToolErrors, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CheckProviderData, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionResponses, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleResponses, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponses, DownloadModelData, DownloadModelErrors, DownloadModelResponses, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeResponses, ExportAppData, ExportAppErrors, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponses, ForkSessionData, ForkSessionErrors, ForkSessionResponses, GetCanonicalModelInfoData, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponses, GetPromptData, GetPromptErrors, GetPromptResponses, GetPromptsData, GetPromptsResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponses, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponses, ImportAppData, ImportAppErrors, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponses, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponses, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsErrors, ListAppsResponses, ListModelsData, ListModelsResponses, ListRecipesData, ListRecipesErrors, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponses, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, ParseRecipeData, ParseRecipeErrors, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponses, ProvidersData, ProvidersResponses, ReadAllConfigData, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceResponses, RecipeToYamlData, RecipeToYamlErrors, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponses, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponses, RestartAgentData, RestartAgentErrors, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentResponses, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponses, SavePromptData, SavePromptErrors, SavePromptResponses, SaveRecipeData, SaveRecipeErrors, SaveRecipeResponses, ScanRecipeData, ScanRecipeResponses, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponses, SetConfigProviderData, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, StartAgentData, StartAgentErrors, StartAgentResponses, StartNanogptSetupData, StartNanogptSetupResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, StartTunnelData, StartTunnelErrors, StartTunnelResponses, StatusData, StatusResponses, StopAgentData, StopAgentErrors, StopAgentResponses, StopTunnelData, StopTunnelErrors, StopTunnelResponses, SystemInfoData, SystemInfoResponses, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponses, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionResponses, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponses } from './types.gen'; export type Options = Options2 & { /** @@ -304,6 +304,8 @@ export const transcribeDictation = (option } }); +export const startNanogptSetup = (options?: Options) => (options?.client ?? client).post({ url: '/handle_nanogpt', ...options }); + export const startOpenrouterSetup = (options?: Options) => (options?.client ?? client).post({ url: '/handle_openrouter', ...options }); export const startTetrateSetup = (options?: Options) => (options?.client ?? client).post({ url: '/handle_tetrate', ...options }); diff --git a/ui/desktop/src/api/types.gen.ts b/ui/desktop/src/api/types.gen.ts index 684527b25d40..759414e69da9 100644 --- a/ui/desktop/src/api/types.gen.ts +++ b/ui/desktop/src/api/types.gen.ts @@ -2818,6 +2818,19 @@ export type TranscribeDictationResponses = { export type TranscribeDictationResponse = TranscribeDictationResponses[keyof TranscribeDictationResponses]; +export type StartNanogptSetupData = { + body?: never; + path?: never; + query?: never; + url: '/handle_nanogpt'; +}; + +export type StartNanogptSetupResponses = { + 200: SetupResponse; +}; + +export type StartNanogptSetupResponse = StartNanogptSetupResponses[keyof StartNanogptSetupResponses]; + export type StartOpenrouterSetupData = { body?: never; path?: never; diff --git a/ui/desktop/src/components/onboarding/FreeCreditCards.tsx b/ui/desktop/src/components/onboarding/FreeCreditCards.tsx index a847442246fc..83d4d0bfd140 100644 --- a/ui/desktop/src/components/onboarding/FreeCreditCards.tsx +++ b/ui/desktop/src/components/onboarding/FreeCreditCards.tsx @@ -1,5 +1,6 @@ import { useState } from 'react'; import { startOpenRouterSetup } from '../../utils/openRouterSetup'; +import { startNanogptSetup } from '../../utils/nanogptSetup'; import { startTetrateSetup } from '../../utils/tetrateSetup'; import { OpenRouter, Tetrate } from '../icons'; import { SetupModal } from '../SetupModal'; @@ -75,9 +76,30 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) } }; - const handleNanogptSetup = () => { - // TODO: implement NanoGPT setup flow - console.log('NanoGPT setup not yet implemented'); + const handleNanogptSetup = async () => { + try { + const result = await startNanogptSetup(); + if (result.success) { + onConfigured('nanogpt'); + } else { + setSetupState({ + show: true, + title: 'Setup Failed', + message: result.message, + showRetry: true, + type: 'nanogpt', + }); + } + } catch (error) { + console.error('NanoGPT setup error:', error); + setSetupState({ + show: true, + title: 'Setup Error', + message: 'An unexpected error occurred during setup.', + showRetry: true, + type: 'nanogpt', + }); + } }; const handleRetry = () => { @@ -156,7 +178,9 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps)
-

Simple, affordable AI access. Coming soon.

+

+ Simple, affordable AI access. Sign up to get started. +

diff --git a/ui/desktop/src/utils/nanogptSetup.ts b/ui/desktop/src/utils/nanogptSetup.ts new file mode 100644 index 000000000000..85ac0d2400fe --- /dev/null +++ b/ui/desktop/src/utils/nanogptSetup.ts @@ -0,0 +1,12 @@ +import { startNanogptSetup as startNanogptSetupApi } from '../api'; + +export async function startNanogptSetup(): Promise<{ success: boolean; message: string }> { + try { + return (await startNanogptSetupApi({ throwOnError: true })).data; + } catch (e) { + return { + success: false, + message: `Failed to start NanoGPT setup ['${e}]`, + }; + } +} From 535b6b57d16ec70f8e07cb5c094f122dc53f0bf3 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Thu, 19 Feb 2026 18:10:15 +1100 Subject: [PATCH 16/41] added nanogpt provider --- crates/goose/src/providers/init.rs | 2 + crates/goose/src/providers/mod.rs | 1 + crates/goose/src/providers/nanogpt.rs | 215 ++++++++++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 crates/goose/src/providers/nanogpt.rs diff --git a/crates/goose/src/providers/init.rs b/crates/goose/src/providers/init.rs index c1f69e61d6b9..e51bec56adb5 100644 --- a/crates/goose/src/providers/init.rs +++ b/crates/goose/src/providers/init.rs @@ -16,6 +16,7 @@ use super::{ google::GoogleProvider, lead_worker::LeadWorkerProvider, litellm::LiteLLMProvider, + nanogpt::NanoGptProvider, ollama::OllamaProvider, openai::OpenAiProvider, openrouter::OpenRouterProvider, @@ -57,6 +58,7 @@ async fn init_registry() -> RwLock { registry.register::(false); registry.register::(true); registry.register::(false); + registry.register::(true); registry.register::(true); registry.register::(true); registry.register::(true); diff --git a/crates/goose/src/providers/mod.rs b/crates/goose/src/providers/mod.rs index 6e4862f0df17..7f19e9668df5 100644 --- a/crates/goose/src/providers/mod.rs +++ b/crates/goose/src/providers/mod.rs @@ -23,6 +23,7 @@ pub mod google; mod init; pub mod lead_worker; pub mod litellm; +pub mod nanogpt; pub mod oauth; pub mod ollama; pub mod openai; diff --git a/crates/goose/src/providers/nanogpt.rs b/crates/goose/src/providers/nanogpt.rs new file mode 100644 index 000000000000..f20e77169240 --- /dev/null +++ b/crates/goose/src/providers/nanogpt.rs @@ -0,0 +1,215 @@ +use super::api_client::{ApiClient, AuthMethod}; +use super::base::{ConfigKey, MessageStream, Provider, ProviderDef, ProviderMetadata}; +use super::errors::ProviderError; +use super::openai_compatible::{handle_status_openai_compat, stream_openai_compat}; +use super::retry::ProviderRetry; +use super::utils::{ImageFormat, RequestLog}; +use crate::conversation::message::Message; +use crate::model::ModelConfig; +use crate::providers::formats::openai::create_request; +use anyhow::Result; +use async_trait::async_trait; +use futures::future::BoxFuture; +use rmcp::model::Tool; + +const NANOGPT_PROVIDER_NAME: &str = "nanogpt"; +pub const NANOGPT_API_HOST: &str = "https://nano-gpt.com/api/v1"; +pub const NANOGPT_SUBSCRIPTION_HOST: &str = "https://nano-gpt.com/api/subscription/v1"; +pub const NANOGPT_DEFAULT_MODEL: &str = "openai/gpt-4.1-nano"; +pub const NANOGPT_DOC_URL: &str = "https://docs.nano-gpt.com/"; +const NANOGPT_API_KEY: &str = "NANOGPT_API_KEY"; + +#[derive(serde::Serialize)] +pub struct NanoGptProvider { + #[serde(skip)] + api_client: ApiClient, + model: ModelConfig, + #[serde(skip)] + name: String, +} + +impl NanoGptProvider { + async fn check_subscription(api_key: &str) -> bool { + let client = match ApiClient::new( + NANOGPT_SUBSCRIPTION_HOST.to_string(), + AuthMethod::BearerToken(api_key.to_string()), + ) { + Ok(c) => c, + Err(_) => return false, + }; + + match client.response_get(None, "usage").await { + Ok(resp) => resp + .json::() + .await + .ok() + .and_then(|json| json.get("active")?.as_bool()) + .unwrap_or(false), + Err(_) => false, + } + } + + pub async fn from_env(model: ModelConfig) -> Result { + let config = crate::config::Config::global(); + let api_key: String = config.get_secret(NANOGPT_API_KEY)?; + + let is_subscription = Self::check_subscription(&api_key).await; + let host = if is_subscription { + tracing::info!("NanoGPT subscription active, using subscription endpoint"); + NANOGPT_SUBSCRIPTION_HOST.to_string() + } else { + tracing::info!("NanoGPT using pay-as-you-go endpoint"); + NANOGPT_API_HOST.to_string() + }; + + let api_client = ApiClient::new(host, AuthMethod::BearerToken(api_key))?; + + Ok(Self { + api_client, + model, + name: NANOGPT_PROVIDER_NAME.to_string(), + }) + } +} + +impl ProviderDef for NanoGptProvider { + type Provider = Self; + + fn metadata() -> ProviderMetadata { + ProviderMetadata::new( + NANOGPT_PROVIDER_NAME, + "NanoGPT", + "Access multiple AI models through NanoGPT's unified API", + NANOGPT_DEFAULT_MODEL, + vec![NANOGPT_DEFAULT_MODEL], + NANOGPT_DOC_URL, + vec![ConfigKey::new(NANOGPT_API_KEY, true, true, None, true)], + ) + .with_unlisted_models() + } + + fn from_env( + model: ModelConfig, + _extensions: Vec, + ) -> BoxFuture<'static, Result> { + Box::pin(Self::from_env(model)) + } +} + +#[async_trait] +impl Provider for NanoGptProvider { + fn get_name(&self) -> &str { + &self.name + } + + fn get_model_config(&self) -> ModelConfig { + self.model.clone() + } + + async fn fetch_supported_models(&self) -> Result, ProviderError> { + let response = self + .api_client + .request(None, "models?detailed=true") + .response_get() + .await + .map_err(|e| { + ProviderError::RequestFailed(format!( + "Failed to fetch models from NanoGPT API: {}", + e + )) + })?; + + let json: serde_json::Value = response.json().await.map_err(|e| { + ProviderError::RequestFailed(format!( + "Failed to parse NanoGPT models API response as JSON: {}", + e + )) + })?; + + if let Some(err_obj) = json.get("error") { + let msg = err_obj + .get("message") + .and_then(|v| v.as_str()) + .unwrap_or("unknown error"); + return Err(ProviderError::RequestFailed(format!( + "NanoGPT API returned an error: {}", + msg + ))); + } + + let data = json.get("data").and_then(|v| v.as_array()).ok_or_else(|| { + ProviderError::RequestFailed("Missing 'data' field in JSON response".into()) + })?; + + let mut models: Vec = data + .iter() + .filter_map(|model| { + let id = model.get("id").and_then(|v| v.as_str())?; + let supports_tool_calling = model + .get("capabilities") + .and_then(|c| c.get("tool_calling")) + .and_then(|v| v.as_bool()) + .unwrap_or(false); + if supports_tool_calling { + Some(id.to_string()) + } else { + None + } + }) + .collect(); + + models.sort(); + Ok(models) + } + + async fn stream( + &self, + model_config: &ModelConfig, + session_id: &str, + system: &str, + messages: &[Message], + tools: &[Tool], + ) -> Result { + let payload = create_request( + model_config, + system, + messages, + tools, + &ImageFormat::OpenAi, + true, + )?; + + let mut log = RequestLog::start(model_config, &payload)?; + + let response = self + .with_retry(|| async { + let resp = self + .api_client + .response_post(Some(session_id), "chat/completions", &payload) + .await?; + handle_status_openai_compat(resp).await + }) + .await + .inspect_err(|e| { + let _ = log.error(e); + })?; + + stream_openai_compat(response, log) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_metadata() { + let metadata = NanoGptProvider::metadata(); + assert_eq!(metadata.name, "nanogpt"); + assert_eq!(metadata.default_model, "openai/gpt-4.1-nano"); + assert_eq!(metadata.config_keys[0].name, NANOGPT_API_KEY); + assert!(metadata.config_keys[0].required); + assert!(metadata.config_keys[0].secret); + assert!(metadata.allows_unlisted_models); + } +} From 301d4f3c2a9e660e2231b6f23c076b29cb13e8bd Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Thu, 19 Feb 2026 19:12:41 +1100 Subject: [PATCH 17/41] text change --- .../components/onboarding/FreeCreditCards.tsx | 60 ++----------------- .../onboarding/ProviderSelector.tsx | 2 +- 2 files changed, 5 insertions(+), 57 deletions(-) diff --git a/ui/desktop/src/components/onboarding/FreeCreditCards.tsx b/ui/desktop/src/components/onboarding/FreeCreditCards.tsx index 83d4d0bfd140..d341e2a9130e 100644 --- a/ui/desktop/src/components/onboarding/FreeCreditCards.tsx +++ b/ui/desktop/src/components/onboarding/FreeCreditCards.tsx @@ -1,8 +1,7 @@ import { useState } from 'react'; -import { startOpenRouterSetup } from '../../utils/openRouterSetup'; import { startNanogptSetup } from '../../utils/nanogptSetup'; import { startTetrateSetup } from '../../utils/tetrateSetup'; -import { OpenRouter, Tetrate } from '../icons'; +import { Tetrate } from '../icons'; import { SetupModal } from '../SetupModal'; interface FreeCreditCardsProps { @@ -21,7 +20,7 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) title: string; message: string; showRetry: boolean; - type: 'tetrate' | 'openrouter' | 'nanogpt'; + type: 'tetrate' | 'nanogpt'; } | null>(null); const handleTetrateSetup = async () => { @@ -50,32 +49,6 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) } }; - const handleOpenRouterSetup = async () => { - try { - const result = await startOpenRouterSetup(); - if (result.success) { - onConfigured('openrouter'); - } else { - setSetupState({ - show: true, - title: 'Setup Failed', - message: result.message, - showRetry: true, - type: 'openrouter', - }); - } - } catch (error) { - console.error('OpenRouter setup error:', error); - setSetupState({ - show: true, - title: 'Setup Error', - message: 'An unexpected error occurred during setup.', - showRetry: true, - type: 'openrouter', - }); - } - }; - const handleNanogptSetup = async () => { try { const result = await startNanogptSetup(); @@ -107,19 +80,13 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) const type = setupState.type; setSetupState(null); if (type === 'tetrate') handleTetrateSetup(); - else if (type === 'openrouter') handleOpenRouterSetup(); else handleNanogptSetup(); }; return (
-

- Get Started with Free Credits -

-

- Sign up with a provider to get free credits for Goose. -

+

Choose a provider to get started.

{/* Tetrate */} @@ -143,25 +110,6 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps)

- {/* OpenRouter */} -
-
-
- - OpenRouter -
-
- -
-
-

- Access 200+ models with one API key. Pay-per-use pricing. -

-
- {/* NanoGPT */}

- Simple, affordable AI access. Sign up to get started. + Sign up to receive 60M free tokens for 7 days.

diff --git a/ui/desktop/src/components/onboarding/ProviderSelector.tsx b/ui/desktop/src/components/onboarding/ProviderSelector.tsx index 75ef085704ab..0cfc6824bf34 100644 --- a/ui/desktop/src/components/onboarding/ProviderSelector.tsx +++ b/ui/desktop/src/components/onboarding/ProviderSelector.tsx @@ -112,7 +112,7 @@ export default function ProviderSelector({ Free Credits

- Sign up with an AI provider and get free credits + Get free credits from a provider to try Goose

From 2e85a7973c2f79ce5a291ae25f6dddb074d6c6d1 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Thu, 19 Feb 2026 19:32:03 +1100 Subject: [PATCH 18/41] change font size --- .../src/components/onboarding/FreeCreditCards.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ui/desktop/src/components/onboarding/FreeCreditCards.tsx b/ui/desktop/src/components/onboarding/FreeCreditCards.tsx index d341e2a9130e..d8b629d1b30e 100644 --- a/ui/desktop/src/components/onboarding/FreeCreditCards.tsx +++ b/ui/desktop/src/components/onboarding/FreeCreditCards.tsx @@ -86,7 +86,7 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) return (
-

Choose a provider to get started.

+

Choose a provider to get started.

{/* Tetrate */} @@ -97,7 +97,7 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps)
- + Agent Router by Tetrate
@@ -105,7 +105,7 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps)
-

+

Access multiple AI models with automatic setup. Sign up to receive $10 credit.

@@ -120,13 +120,13 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) N - NanoGPT + NanoGPT
-

+

Sign up to receive 60M free tokens for 7 days.

From 6f03f6faf44613809a24ff2ffb12c7929f1c0315 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Thu, 19 Feb 2026 19:33:45 +1100 Subject: [PATCH 19/41] extract to constant --- .../onboarding/ProviderSelector.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/ui/desktop/src/components/onboarding/ProviderSelector.tsx b/ui/desktop/src/components/onboarding/ProviderSelector.tsx index 0cfc6824bf34..5ae903747506 100644 --- a/ui/desktop/src/components/onboarding/ProviderSelector.tsx +++ b/ui/desktop/src/components/onboarding/ProviderSelector.tsx @@ -12,6 +12,9 @@ import CustomProviderForm from '../settings/providers/modal/subcomponents/forms/ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog'; import { Gift, Key, Plus } from 'lucide-react'; +const FREE_CREDITS = 'free-credits'; +const OWN_PROVIDER = 'own-provider'; + type SelectedPath = 'free-credits' | 'own-provider' | null; interface ProviderOption { @@ -72,13 +75,13 @@ export default function ProviderSelector({ }; const handleFreeCreditClick = () => { - setSelectedPath('free-credits'); + setSelectedPath(FREE_CREDITS); setSelectedOption(null); onFirstSelection?.(); }; const handleOwnProviderClick = () => { - setSelectedPath('own-provider'); + setSelectedPath(OWN_PROVIDER); }; const handleProviderSelect = (option: ProviderOption | null) => { @@ -102,9 +105,9 @@ export default function ProviderSelector({
- {selectedPath === 'free-credits' && ( + {selectedPath === FREE_CREDITS && (
)} - {selectedPath === 'own-provider' && ( + {selectedPath === OWN_PROVIDER && (
setTelemetryOptIn(e.target.checked)} + className="rounded" + /> + Share anonymous usage data + +
+ + +
+ + + + setShowPrivacyInfo(false)} /> + + ); +} diff --git a/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx b/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx new file mode 100644 index 000000000000..585ab7817f42 --- /dev/null +++ b/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx @@ -0,0 +1,53 @@ +import { Card } from '../ui/card'; + +interface PrivacyInfoModalProps { + isOpen: boolean; + onClose: () => void; +} + +export default function PrivacyInfoModal({ isOpen, onClose }: PrivacyInfoModalProps) { + if (!isOpen) return null; + + return ( +
+ e.stopPropagation()} + > + + +

Privacy details

+

+ Anonymous usage data helps us understand how goose is used and identify areas for + improvement. +

+

What we collect:

+
    +
  • Operating system, version, and architecture
  • +
  • Goose version and install method
  • +
  • Provider and model used
  • +
  • Extensions and tool usage counts (names only)
  • +
  • Session metrics (duration, interaction count, token usage)
  • +
  • Error types (e.g., "rate_limit", "auth" - no details)
  • +
+

+ We never collect your conversations, code, tool arguments, error messages, or any personal + data. You can change this setting anytime in Settings. +

+
+
+ ); +} From c504e2a9a5f9611c9aa699290ec7b57efe118bc9 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Fri, 20 Feb 2026 19:19:28 +1100 Subject: [PATCH 22/41] added tracking events --- .../components/onboarding/OnboardingGuard.tsx | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx index ac2b3a81bfd8..25c25c41525a 100644 --- a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx +++ b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx @@ -23,11 +23,12 @@ export default function OnboardingGuard({ children }: OnboardingGuardProps) { const { read, upsert, getProviders } = useConfig(); const { refreshCurrentModelAndProvider } = useModelAndProvider(); - const [isChecking, setIsChecking] = useState(true); + const [isCheckingProvider, setIsCheckingProvider] = useState(true); const [hasProvider, setHasProvider] = useState(false); const [hasSelection, setHasSelection] = useState(false); const [configuredProvider, setConfiguredProvider] = useState(null); - const onboardingTracked = useRef(false); + const [configuredModel, setConfiguredModel] = useState(null); + const hasTrackedOnboardingStart = useRef(false); useEffect(() => { const checkProvider = async () => { @@ -38,28 +39,31 @@ export default function OnboardingGuard({ children }: OnboardingGuardProps) { console.error('Error checking provider:', error); setHasProvider(false); } finally { - setIsChecking(false); + setIsCheckingProvider(false); } }; checkProvider(); }, [read]); useEffect(() => { - if (!isChecking && !hasProvider && !onboardingTracked.current) { + if (!isCheckingProvider && !hasProvider && !hasTrackedOnboardingStart.current) { trackOnboardingStarted(); - onboardingTracked.current = true; + hasTrackedOnboardingStart.current = true; } - }, [isChecking, hasProvider]); + }, [isCheckingProvider, hasProvider]); const handleConfigured = async (providerName: string) => { const providers = await getProviders(true); - const match = providers.find((p) => p.name === providerName); + const matchedProvider = providers.find((p) => p.name === providerName); await upsert('GOOSE_PROVIDER', providerName, false); - if (match) { - await upsert('GOOSE_MODEL', match.metadata.default_model, false); + if (matchedProvider) { + await upsert('GOOSE_MODEL', matchedProvider.metadata.default_model, false); } await refreshCurrentModelAndProvider(); setConfiguredProvider(providerName); + if (matchedProvider) { + setConfiguredModel(matchedProvider.metadata.default_model); + } }; const finishOnboarding = async (telemetryEnabled: boolean) => { @@ -68,19 +72,18 @@ export default function OnboardingGuard({ children }: OnboardingGuardProps) { } catch (error) { console.error('Failed to save telemetry preference:', error); } - if (telemetryEnabled) { - trackTelemetryPreference(true, 'onboarding'); - if (configuredProvider) { - trackOnboardingCompleted(configuredProvider); - } - } else { + trackTelemetryPreference(telemetryEnabled, 'onboarding'); + if (configuredProvider) { + trackOnboardingCompleted(configuredProvider, configuredModel ?? undefined); + } + if (!telemetryEnabled) { setAnalyticsTelemetryEnabled(false); } navigate('/', { replace: true }); setHasProvider(true); }; - if (isChecking) { + if (isCheckingProvider) { return null; } From affff89734c6bf9b8fa8c79e243542705d8b13a6 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Mon, 23 Feb 2026 12:16:20 +1100 Subject: [PATCH 23/41] updated the instructions --- crates/goose/src/providers/anthropic.rs | 4 ++-- crates/goose/src/providers/google.rs | 4 ++-- crates/goose/src/providers/openai.rs | 2 +- crates/goose/src/providers/openrouter.rs | 5 ++--- .../onboarding/ProviderConfigForm.tsx | 22 ++++++++++++++++++- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/crates/goose/src/providers/anthropic.rs b/crates/goose/src/providers/anthropic.rs index 95415410fb4d..f1efd94f9215 100644 --- a/crates/goose/src/providers/anthropic.rs +++ b/crates/goose/src/providers/anthropic.rs @@ -164,8 +164,8 @@ impl ProviderDef for AnthropicProvider { ], ) .with_setup_steps(vec![ - "Go to console.anthropic.com and sign up or log in", - "Navigate to Settings > API Keys", + "Go to https://console.anthropic.com and sign up or log in", + "Click 'API Keys' in the left sidebar", "Click 'Create Key'", "Copy the key and paste it above", ]) diff --git a/crates/goose/src/providers/google.rs b/crates/goose/src/providers/google.rs index 052885334806..d521d9a376eb 100644 --- a/crates/goose/src/providers/google.rs +++ b/crates/goose/src/providers/google.rs @@ -122,8 +122,8 @@ impl ProviderDef for GoogleProvider { ], ) .with_setup_steps(vec![ - "Go to aistudio.google.com and sign in with your Google account", - "Click 'Get API key' in the top navigation", + "Go to https://aistudio.google.com and sign in with your Google account", + "Click 'Get API key' on the left sidebar", "Create a new API key or select an existing one", "Copy the key and paste it above", ]) diff --git a/crates/goose/src/providers/openai.rs b/crates/goose/src/providers/openai.rs index e048a66deb4b..6a30b2ec11d9 100644 --- a/crates/goose/src/providers/openai.rs +++ b/crates/goose/src/providers/openai.rs @@ -307,7 +307,7 @@ impl ProviderDef for OpenAiProvider { ], ) .with_setup_steps(vec![ - "Go to platform.openai.com and sign up or log in", + "Go to https://platform.openai.com and sign up or log in", "Navigate to API Keys in the left sidebar", "Click 'Create new secret key'", "Copy the key and paste it above", diff --git a/crates/goose/src/providers/openrouter.rs b/crates/goose/src/providers/openrouter.rs index 8baae41cd337..f272420bdd60 100644 --- a/crates/goose/src/providers/openrouter.rs +++ b/crates/goose/src/providers/openrouter.rs @@ -170,9 +170,8 @@ impl ProviderDef for OpenRouterProvider { ) .with_unlisted_models() .with_setup_steps(vec![ - "Go to openrouter.ai and sign up or log in", - "Navigate to Keys in the menu", - "Click 'Create Key'", + "Go to https://openrouter.ai/settings/keys", + "Click 'Create' or use an existing API key", "Copy the key and paste it above", ]) } diff --git a/ui/desktop/src/components/onboarding/ProviderConfigForm.tsx b/ui/desktop/src/components/onboarding/ProviderConfigForm.tsx index 484c520800b2..b01b382d3519 100644 --- a/ui/desktop/src/components/onboarding/ProviderConfigForm.tsx +++ b/ui/desktop/src/components/onboarding/ProviderConfigForm.tsx @@ -10,6 +10,26 @@ import { SecureStorageNotice } from '../settings/providers/modal/subcomponents/S import { Button } from '../ui/button'; import { LogIn, ChevronRight } from 'lucide-react'; +function parseLinks(text: string) { + return text.split(/(https?:\/\/[^\s]+)/g).map((part, i) => + /^https?:\/\//.test(part) ? ( + { + e.preventDefault(); + window.electron.openExternal(part); + }} + className="underline hover:text-text-default cursor-pointer" + > + {part} + + ) : ( + part + ) + ); +} + function OAuthForm({ provider, onConfigured, @@ -140,7 +160,7 @@ function ApiKeyForm({ {showSetupHelp && (
    {setupSteps.map((step, i) => ( -
  1. {step}
  2. +
  3. {parseLinks(step)}
  4. ))}
)} From d183cf02f93f25243558735b05cf70f69846ff74 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Mon, 23 Feb 2026 15:24:58 +1100 Subject: [PATCH 24/41] error handling --- crates/goose-server/src/routes/setup.rs | 6 +- crates/goose/src/config/signup_nanogpt/mod.rs | 8 +- ui/desktop/src/App.tsx | 2 - .../components/onboarding/FreeCreditCards.tsx | 99 ++++------- .../onboarding/GettingStartedPage.tsx | 165 ------------------ 5 files changed, 40 insertions(+), 240 deletions(-) delete mode 100644 ui/desktop/src/components/onboarding/GettingStartedPage.tsx diff --git a/crates/goose-server/src/routes/setup.rs b/crates/goose-server/src/routes/setup.rs index 165a20e2e77b..55a357db3dbd 100644 --- a/crates/goose-server/src/routes/setup.rs +++ b/crates/goose-server/src/routes/setup.rs @@ -52,7 +52,7 @@ async fn start_openrouter_setup() -> Result, ErrorResponse> } Err(e) => Ok(Json(SetupResponse { success: false, - message: format!("Setup failed: {}", e), + message: e.to_string(), })), } } @@ -86,7 +86,7 @@ async fn start_tetrate_setup() -> Result, ErrorResponse> { } Err(e) => Ok(Json(SetupResponse { success: false, - message: format!("Setup failed: {}", e), + message: e.to_string(), })), } } @@ -117,7 +117,7 @@ async fn start_nanogpt_setup() -> Result, ErrorResponse> { } Err(e) => Ok(Json(SetupResponse { success: false, - message: format!("Setup failed: {}", e), + message: e.to_string(), })), } } diff --git a/crates/goose/src/config/signup_nanogpt/mod.rs b/crates/goose/src/config/signup_nanogpt/mod.rs index e5d954cc9e79..40e3d58bf0c9 100644 --- a/crates/goose/src/config/signup_nanogpt/mod.rs +++ b/crates/goose/src/config/signup_nanogpt/mod.rs @@ -11,7 +11,7 @@ pub const NANOGPT_DEFAULT_MODEL: &str = "openai/gpt-4.1-nano"; const NANOGPT_START_URL: &str = "https://nano-gpt.com/api/cli-login/start"; const NANOGPT_POLL_URL: &str = "https://nano-gpt.com/api/cli-login/poll"; -const AUTH_TIMEOUT: Duration = Duration::from_secs(600); // 10 minutes +const AUTH_TIMEOUT: Duration = Duration::from_secs(180); // 3 minutes const POLL_INTERVAL: Duration = Duration::from_secs(2); #[derive(Debug, Serialize)] @@ -46,14 +46,13 @@ async fn poll_for_token(device_code: &str) -> Result { }; let response = client.post(NANOGPT_POLL_URL).json(&body).send().await?; - + // https://docs.nano-gpt.com/integrations/cli-login#response-codes match response.status().as_u16() { 200 => { let poll_resp: PollResponse = response.json().await?; return Ok(poll_resp.key); } 202 => { - // Authorization pending, continue polling continue; } 410 => { @@ -65,6 +64,9 @@ async fn poll_for_token(device_code: &str) -> Result { 404 => { return Err(anyhow!("Invalid device code")); } + 429 => { + return Err(anyhow!("Too many requests to NanoGPT. Please wait a moment and try again.")); + } other => { let error_text = response.text().await.unwrap_or_default(); return Err(anyhow!( diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index a1abdb5f427b..ab8a21676cc7 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -18,7 +18,6 @@ import TelemetryOptOutModal from './components/TelemetryOptOutModal'; import ProviderGuard from './components/ProviderGuard'; import OnboardingGuard from './components/onboarding/OnboardingGuard'; import { USE_NEW_ONBOARDING } from './featureFlags'; -import GettingStartedPage from './components/onboarding/GettingStartedPage'; import { createSession } from './sessions'; import { ChatType } from './types/chat'; @@ -636,7 +635,6 @@ export function AppInner() { element={ setDidSelectProvider(true)} />} /> } /> - } /> } /> void; @@ -15,72 +18,34 @@ const ChevronRight = () => ( ); export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) { - const [setupState, setSetupState] = useState<{ - show: boolean; - title: string; + const [error, setError] = useState<{ message: string; - showRetry: boolean; - type: 'tetrate' | 'nanogpt'; + type: FreeCreditProvider; } | null>(null); - const handleTetrateSetup = async () => { + const handleSetup = async (type: FreeCreditProvider) => { + setError(null); try { - const result = await startTetrateSetup(); + const result = type === TETRATE ? await startTetrateSetup() : await startNanogptSetup(); if (result.success) { - onConfigured('tetrate'); + onConfigured(type); } else { - setSetupState({ - show: true, - title: 'Setup Failed', - message: result.message, - showRetry: true, - type: 'tetrate', - }); + setError({ message: result.message, type }); } - } catch (error) { - console.error('Tetrate setup error:', error); - setSetupState({ - show: true, - title: 'Setup Error', - message: 'An unexpected error occurred during setup.', - showRetry: true, - type: 'tetrate', - }); + } catch { + setError({ message: 'An unexpected error occurred during setup.', type }); } }; - const handleNanogptSetup = async () => { - try { - const result = await startNanogptSetup(); - if (result.success) { - onConfigured('nanogpt'); - } else { - setSetupState({ - show: true, - title: 'Setup Failed', - message: result.message, - showRetry: true, - type: 'nanogpt', - }); - } - } catch (error) { - console.error('NanoGPT setup error:', error); - setSetupState({ - show: true, - title: 'Setup Error', - message: 'An unexpected error occurred during setup.', - showRetry: true, - type: 'nanogpt', - }); - } - }; + const handleTetrateSetup = () => handleSetup(TETRATE); + const handleNanogptSetup = () => handleSetup(NANOGPT); const handleRetry = () => { - if (!setupState) return; - const type = setupState.type; - setSetupState(null); - if (type === 'tetrate') handleTetrateSetup(); - else handleNanogptSetup(); + if (!error) return; + if (error.type === TETRATE) { + handleTetrateSetup(); + } + handleNanogptSetup(); }; return ( @@ -89,7 +54,6 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps)

Choose a provider to get started.

- {/* Tetrate */}
- {/* NanoGPT */}
+ {error && ( +
+

{error.message}

+ +
+ )} +

You can switch providers anytime.

- - {setupState?.show && ( - setSetupState(null)} - /> - )} ); } diff --git a/ui/desktop/src/components/onboarding/GettingStartedPage.tsx b/ui/desktop/src/components/onboarding/GettingStartedPage.tsx deleted file mode 100644 index c3d23e2351f7..000000000000 --- a/ui/desktop/src/components/onboarding/GettingStartedPage.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; -import { startOpenRouterSetup } from '../../utils/openRouterSetup'; -import { startTetrateSetup } from '../../utils/tetrateSetup'; -import { SetupModal } from '../SetupModal'; -import { Goose, OpenRouter, Tetrate } from '../icons'; - -export default function GettingStartedPage() { - const navigate = useNavigate(); - - const [setupState, setSetupState] = useState<{ - show: boolean; - title: string; - message: string; - showRetry: boolean; - type: 'openrouter' | 'tetrate'; - } | null>(null); - - const handleTetrateSetup = async () => { - try { - const result = await startTetrateSetup(); - if (result.success) { - navigate('/', { replace: true }); - } else { - setSetupState({ - show: true, - title: 'Setup Failed', - message: result.message, - showRetry: true, - type: 'tetrate', - }); - } - } catch (error) { - console.error('Tetrate setup error:', error); - setSetupState({ - show: true, - title: 'Setup Error', - message: 'An unexpected error occurred during setup.', - showRetry: true, - type: 'tetrate', - }); - } - }; - - const handleOpenRouterSetup = async () => { - try { - const result = await startOpenRouterSetup(); - if (result.success) { - navigate('/', { replace: true }); - } else { - setSetupState({ - show: true, - title: 'Setup Failed', - message: result.message, - showRetry: true, - type: 'openrouter', - }); - } - } catch (error) { - console.error('OpenRouter setup error:', error); - setSetupState({ - show: true, - title: 'Setup Error', - message: 'An unexpected error occurred during setup.', - showRetry: true, - type: 'openrouter', - }); - } - }; - - const handleRetry = () => { - if (!setupState) return; - const type = setupState.type; - setSetupState(null); - if (type === 'tetrate') handleTetrateSetup(); - else handleOpenRouterSetup(); - }; - - return ( -
-
-
-
- {/* Header */} -
-
- -
-

Get Started

-

- Sign up for an AI provider to start using Goose. -

-
- - {/* Tetrate card */} -
-
-
- - - Agent Router by Tetrate - -
-
- - - -
-
-

- Access multiple AI models with automatic setup. Sign up to receive $10 credit. -

-
- - {/* OpenRouter card */} -
-
-
- - - OpenRouter - -
-
- - - -
-
-

- Access 200+ models with one API. Pay-per-use pricing. -

-
- - {/* Back link */} -
- -
-
-
-
- - {setupState?.show && ( - setSetupState(null)} - /> - )} -
- ); -} From c1062da0534a733df54bdf6dd1755c2badb3a3aa Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Mon, 23 Feb 2026 16:08:16 +1100 Subject: [PATCH 25/41] feature toggle off by default --- ui/desktop/src/featureFlags.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/desktop/src/featureFlags.ts b/ui/desktop/src/featureFlags.ts index 663954c73f5b..b3a0b9ec9562 100644 --- a/ui/desktop/src/featureFlags.ts +++ b/ui/desktop/src/featureFlags.ts @@ -1 +1 @@ -export const USE_NEW_ONBOARDING = true; +export const USE_NEW_ONBOARDING = false; From bec2abfc37e70e02bee93138425dbfb3facbca43 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Mon, 23 Feb 2026 17:31:15 +1100 Subject: [PATCH 26/41] added local model selection --- crates/goose/src/providers/base.rs | 6 - crates/goose/src/providers/nanogpt.rs | 1 - ui/desktop/src/api/index.ts | 4 +- ui/desktop/src/api/sdk.gen.ts | 2 +- ui/desktop/src/components/LocalModelSetup.tsx | 367 +---------------- ...reeCreditCards.tsx => FreeOptionCards.tsx} | 66 ++- .../onboarding/LocalModelPicker.tsx | 376 ++++++++++++++++++ .../components/onboarding/OnboardingGuard.tsx | 19 +- .../onboarding/OnboardingSuccess.tsx | 6 +- .../onboarding/ProviderSelector.tsx | 10 +- ui/desktop/src/featureFlags.ts | 2 +- 11 files changed, 455 insertions(+), 404 deletions(-) rename ui/desktop/src/components/onboarding/{FreeCreditCards.tsx => FreeOptionCards.tsx} (58%) create mode 100644 ui/desktop/src/components/onboarding/LocalModelPicker.tsx diff --git a/crates/goose/src/providers/base.rs b/crates/goose/src/providers/base.rs index 3c6f0b57930e..68a401fdf969 100644 --- a/crates/goose/src/providers/base.rs +++ b/crates/goose/src/providers/base.rs @@ -248,12 +248,6 @@ impl ProviderMetadata { } } - /// Set allows_unlisted_models flag (builder pattern) - pub fn with_unlisted_models(mut self) -> Self { - self.allows_unlisted_models = true; - self - } - pub fn with_setup_steps(mut self, steps: Vec<&str>) -> Self { self.setup_steps = steps.into_iter().map(|s| s.to_string()).collect(); self diff --git a/crates/goose/src/providers/nanogpt.rs b/crates/goose/src/providers/nanogpt.rs index f20e77169240..75dea3151c25 100644 --- a/crates/goose/src/providers/nanogpt.rs +++ b/crates/goose/src/providers/nanogpt.rs @@ -85,7 +85,6 @@ impl ProviderDef for NanoGptProvider { NANOGPT_DOC_URL, vec![ConfigKey::new(NANOGPT_API_KEY, true, true, None, true)], ) - .with_unlisted_models() } fn from_env( diff --git a/ui/desktop/src/api/index.ts b/ui/desktop/src/api/index.ts index 2e65e54472c0..0432a17ef688 100644 --- a/ui/desktop/src/api/index.ts +++ b/ui/desktop/src/api/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { addExtension, agentAddExtension, agentRemoveExtension, backupConfig, callTool, cancelDownload, cancelLocalModelDownload, checkProvider, configureProviderOauth, confirmToolAction, createCustomProvider, createRecipe, createSchedule, decodeRecipe, deleteLocalModel, deleteModel, deleteRecipe, deleteSchedule, deleteSession, detectProvider, diagnostics, downloadHfModel, downloadModel, encodeRecipe, exportApp, exportSession, forkSession, getCanonicalModelInfo, getCustomProvider, getDictationConfig, getDownloadProgress, getExtensions, getLocalModelDownloadProgress, getModelSettings, getPrompt, getPrompts, getProviderModels, getRepoFiles, getSession, getSessionExtensions, getSessionInsights, getSlashCommands, getTools, getTunnelStatus, importApp, importSession, initConfig, inspectRunningJob, killRunningJob, listApps, listLocalModels, listModels, listRecipes, listSchedules, listSessions, mcpUiProxy, type Options, parseRecipe, pauseSchedule, providers, readAllConfig, readConfig, readResource, recipeToYaml, recoverConfig, removeConfig, removeCustomProvider, removeExtension, reply, resetPrompt, restartAgent, resumeAgent, runNowHandler, savePrompt, saveRecipe, scanRecipe, scheduleRecipe, searchHfModels, searchSessions, sendTelemetryEvent, sessionsHandler, setConfigProvider, setRecipeSlashCommand, startAgent, startOpenrouterSetup, startTetrateSetup, startTunnel, status, stopAgent, stopTunnel, systemInfo, transcribeDictation, unpauseSchedule, updateAgentProvider, updateCustomProvider, updateFromSession, updateModelSettings, updateSchedule, updateSessionName, updateSessionUserRecipeValues, updateWorkingDir, upsertConfig, upsertPermissions, validateConfig } from './sdk.gen'; -export type { ActionRequired, ActionRequiredData, AddExtensionData, AddExtensionErrors, AddExtensionRequest, AddExtensionResponse, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponse, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponse, AgentRemoveExtensionResponses, Annotations, Author, AuthorRequest, BackupConfigData, BackupConfigErrors, BackupConfigResponse, BackupConfigResponses, CallToolData, CallToolErrors, CallToolRequest, CallToolResponse, CallToolResponse2, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, ChatRequest, CheckProviderData, CheckProviderRequest, ClientOptions, CommandType, ConfigKey, ConfigKeyQuery, ConfigResponse, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionRequest, ConfirmToolActionResponses, Content, Conversation, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponse, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeRequest, CreateRecipeResponse, CreateRecipeResponse2, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleRequest, CreateScheduleResponse, CreateScheduleResponses, CspMetadata, DeclarativeProviderConfig, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeRequest, DecodeRecipeResponse, DecodeRecipeResponse2, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeRequest, DeleteRecipeResponse, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponse, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderRequest, DetectProviderResponse, DetectProviderResponse2, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponse, DiagnosticsResponses, DictationProvider, DictationProviderStatus, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponse, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelRequest, DownloadModelResponses, DownloadProgress, DownloadStatus, EmbeddedResource, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeRequest, EncodeRecipeResponse, EncodeRecipeResponse2, EncodeRecipeResponses, Envs, ErrorResponse, ExportAppData, ExportAppError, ExportAppErrors, ExportAppResponse, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponse, ExportSessionResponses, ExtensionConfig, ExtensionData, ExtensionEntry, ExtensionLoadResult, ExtensionQuery, ExtensionResponse, ForkRequest, ForkResponse, ForkSessionData, ForkSessionErrors, ForkSessionResponse, ForkSessionResponses, FrontendToolRequest, GetCanonicalModelInfoData, GetCanonicalModelInfoResponse, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponse, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponse, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponse, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponse, GetExtensionsResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponse, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponse, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponse, GetPromptResponses, GetPromptsData, GetPromptsResponse, GetPromptsResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponse, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponse, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponse, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponse, GetSessionInsightsResponses, GetSessionResponse, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponse, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsQuery, GetToolsResponse, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponse, GetTunnelStatusResponses, GooseApp, HfGgufFile, HfModelInfo, HfQuantVariant, Icon, ImageContent, ImportAppData, ImportAppError, ImportAppErrors, ImportAppRequest, ImportAppResponse, ImportAppResponse2, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionRequest, ImportSessionResponse, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponse, InitConfigResponses, InspectJobResponse, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponse, InspectRunningJobResponses, JsonObject, KillJobResponse, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsError, ListAppsErrors, ListAppsRequest, ListAppsResponse, ListAppsResponse2, ListAppsResponses, ListLocalModelsData, ListLocalModelsResponse, ListLocalModelsResponses, ListModelsData, ListModelsResponse, ListModelsResponses, ListRecipeResponse, ListRecipesData, ListRecipesErrors, ListRecipesResponse, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponse, ListSchedulesResponse2, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponse, ListSessionsResponses, LoadedProvider, LocalModelResponse, McpAppResource, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, Message, MessageContent, MessageEvent, MessageMetadata, ModelConfig, ModelDownloadStatus, ModelInfo, ModelInfoData, ModelInfoQuery, ModelInfoResponse, ModelSettings, ParseRecipeData, ParseRecipeError, ParseRecipeErrors, ParseRecipeRequest, ParseRecipeResponse, ParseRecipeResponse2, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponse, PauseScheduleResponses, Permission, PermissionLevel, PermissionsMetadata, PrincipalType, PromptContentResponse, PromptsListResponse, ProviderDetails, ProviderEngine, ProviderMetadata, ProvidersData, ProvidersResponse, ProvidersResponse2, ProvidersResponses, ProviderType, RawAudioContent, RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ReadAllConfigData, ReadAllConfigResponse, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceRequest, ReadResourceResponse, ReadResourceResponse2, ReadResourceResponses, ReasoningContent, Recipe, RecipeManifest, RecipeParameter, RecipeParameterInputType, RecipeParameterRequirement, RecipeToYamlData, RecipeToYamlError, RecipeToYamlErrors, RecipeToYamlRequest, RecipeToYamlResponse, RecipeToYamlResponse2, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponse, RecoverConfigResponses, RedactedThinkingContent, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponse, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponse, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionRequest, RemoveExtensionResponse, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponse, ReplyResponses, RepoVariantsResponse, ResetPromptData, ResetPromptErrors, ResetPromptResponse, ResetPromptResponses, ResourceContents, ResourceMetadata, Response, RestartAgentData, RestartAgentErrors, RestartAgentRequest, RestartAgentResponse, RestartAgentResponse2, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentRequest, ResumeAgentResponse, ResumeAgentResponse2, ResumeAgentResponses, RetryConfig, Role, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponse, RunNowHandlerResponses, RunNowResponse, SamplingConfig, SavePromptData, SavePromptErrors, SavePromptRequest, SavePromptResponse, SavePromptResponses, SaveRecipeData, SaveRecipeError, SaveRecipeErrors, SaveRecipeRequest, SaveRecipeResponse, SaveRecipeResponse2, SaveRecipeResponses, ScanRecipeData, ScanRecipeRequest, ScanRecipeResponse, ScanRecipeResponse2, ScanRecipeResponses, ScheduledJob, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeRequest, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponse, SearchHfModelsResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponse, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, Session, SessionDisplayInfo, SessionExtensionsResponse, SessionInsights, SessionListResponse, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponse, SessionsHandlerResponses, SessionsQuery, SessionType, SetConfigProviderData, SetProviderRequest, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, SetSlashCommandRequest, Settings, SetupResponse, SlashCommand, SlashCommandsResponse, StartAgentData, StartAgentError, StartAgentErrors, StartAgentRequest, StartAgentResponse, StartAgentResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponse, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponse, StartTetrateSetupResponses, StartTunnelData, StartTunnelError, StartTunnelErrors, StartTunnelResponse, StartTunnelResponses, StatusData, StatusResponse, StatusResponses, StopAgentData, StopAgentErrors, StopAgentRequest, StopAgentResponse, StopAgentResponses, StopTunnelData, StopTunnelError, StopTunnelErrors, StopTunnelResponses, SubRecipe, SuccessCheck, SystemInfo, SystemInfoData, SystemInfoResponse, SystemInfoResponses, SystemNotificationContent, SystemNotificationType, TaskSupport, TelemetryEventRequest, Template, TextContent, ThinkingContent, TokenState, Tool, ToolAnnotations, ToolConfirmationRequest, ToolExecution, ToolInfo, ToolPermission, ToolRequest, ToolResponse, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponse, TranscribeDictationResponses, TranscribeRequest, TranscribeResponse, TunnelInfo, TunnelState, UiMetadata, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponse, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderRequest, UpdateCustomProviderResponse, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionRequest, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponse, UpdateModelSettingsResponses, UpdateProviderRequest, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleRequest, UpdateScheduleResponse, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameRequest, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesError, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesRequest, UpdateSessionUserRecipeValuesResponse, UpdateSessionUserRecipeValuesResponse2, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirRequest, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigQuery, UpsertConfigResponse, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsQuery, UpsertPermissionsResponse, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponse, ValidateConfigResponses, WhisperModelResponse, WindowProps } from './types.gen'; +export { addExtension, agentAddExtension, agentRemoveExtension, backupConfig, callTool, cancelDownload, cancelLocalModelDownload, checkProvider, configureProviderOauth, confirmToolAction, createCustomProvider, createRecipe, createSchedule, decodeRecipe, deleteLocalModel, deleteModel, deleteRecipe, deleteSchedule, deleteSession, detectProvider, diagnostics, downloadHfModel, downloadModel, encodeRecipe, exportApp, exportSession, forkSession, getCanonicalModelInfo, getCustomProvider, getDictationConfig, getDownloadProgress, getExtensions, getLocalModelDownloadProgress, getModelSettings, getPrompt, getPrompts, getProviderModels, getRepoFiles, getSession, getSessionExtensions, getSessionInsights, getSlashCommands, getTools, getTunnelStatus, importApp, importSession, initConfig, inspectRunningJob, killRunningJob, listApps, listLocalModels, listModels, listRecipes, listSchedules, listSessions, mcpUiProxy, type Options, parseRecipe, pauseSchedule, providers, readAllConfig, readConfig, readResource, recipeToYaml, recoverConfig, removeConfig, removeCustomProvider, removeExtension, reply, resetPrompt, restartAgent, resumeAgent, runNowHandler, savePrompt, saveRecipe, scanRecipe, scheduleRecipe, searchHfModels, searchSessions, sendTelemetryEvent, sessionsHandler, setConfigProvider, setRecipeSlashCommand, startAgent, startNanogptSetup, startOpenrouterSetup, startTetrateSetup, startTunnel, status, stopAgent, stopTunnel, systemInfo, transcribeDictation, unpauseSchedule, updateAgentProvider, updateCustomProvider, updateFromSession, updateModelSettings, updateSchedule, updateSessionName, updateSessionUserRecipeValues, updateWorkingDir, upsertConfig, upsertPermissions, validateConfig } from './sdk.gen'; +export type { ActionRequired, ActionRequiredData, AddExtensionData, AddExtensionErrors, AddExtensionRequest, AddExtensionResponse, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponse, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponse, AgentRemoveExtensionResponses, Annotations, Author, AuthorRequest, BackupConfigData, BackupConfigErrors, BackupConfigResponse, BackupConfigResponses, CallToolData, CallToolErrors, CallToolRequest, CallToolResponse, CallToolResponse2, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, ChatRequest, CheckProviderData, CheckProviderRequest, ClientOptions, CommandType, ConfigKey, ConfigKeyQuery, ConfigResponse, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionRequest, ConfirmToolActionResponses, Content, Conversation, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponse, CreateCustomProviderResponse2, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeRequest, CreateRecipeResponse, CreateRecipeResponse2, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleRequest, CreateScheduleResponse, CreateScheduleResponses, CspMetadata, DeclarativeProviderConfig, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeRequest, DecodeRecipeResponse, DecodeRecipeResponse2, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeRequest, DeleteRecipeResponse, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponse, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderRequest, DetectProviderResponse, DetectProviderResponse2, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponse, DiagnosticsResponses, DictationProvider, DictationProviderStatus, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponse, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelRequest, DownloadModelResponses, DownloadProgress, DownloadStatus, EmbeddedResource, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeRequest, EncodeRecipeResponse, EncodeRecipeResponse2, EncodeRecipeResponses, Envs, ErrorResponse, ExportAppData, ExportAppError, ExportAppErrors, ExportAppResponse, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponse, ExportSessionResponses, ExtensionConfig, ExtensionData, ExtensionEntry, ExtensionLoadResult, ExtensionQuery, ExtensionResponse, ForkRequest, ForkResponse, ForkSessionData, ForkSessionErrors, ForkSessionResponse, ForkSessionResponses, FrontendToolRequest, GetCanonicalModelInfoData, GetCanonicalModelInfoResponse, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponse, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponse, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponse, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponse, GetExtensionsResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponse, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponse, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponse, GetPromptResponses, GetPromptsData, GetPromptsResponse, GetPromptsResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponse, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponse, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponse, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponse, GetSessionInsightsResponses, GetSessionResponse, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponse, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsQuery, GetToolsResponse, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponse, GetTunnelStatusResponses, GooseApp, HfGgufFile, HfModelInfo, HfQuantVariant, Icon, ImageContent, ImportAppData, ImportAppError, ImportAppErrors, ImportAppRequest, ImportAppResponse, ImportAppResponse2, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionRequest, ImportSessionResponse, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponse, InitConfigResponses, InspectJobResponse, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponse, InspectRunningJobResponses, JsonObject, KillJobResponse, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsError, ListAppsErrors, ListAppsRequest, ListAppsResponse, ListAppsResponse2, ListAppsResponses, ListLocalModelsData, ListLocalModelsResponse, ListLocalModelsResponses, ListModelsData, ListModelsResponse, ListModelsResponses, ListRecipeResponse, ListRecipesData, ListRecipesErrors, ListRecipesResponse, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponse, ListSchedulesResponse2, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponse, ListSessionsResponses, LoadedProvider, LocalModelResponse, McpAppResource, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, Message, MessageContent, MessageEvent, MessageMetadata, ModelConfig, ModelDownloadStatus, ModelInfo, ModelInfoData, ModelInfoQuery, ModelInfoResponse, ModelSettings, ParseRecipeData, ParseRecipeError, ParseRecipeErrors, ParseRecipeRequest, ParseRecipeResponse, ParseRecipeResponse2, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponse, PauseScheduleResponses, Permission, PermissionLevel, PermissionsMetadata, PrincipalType, PromptContentResponse, PromptsListResponse, ProviderDetails, ProviderEngine, ProviderMetadata, ProvidersData, ProvidersResponse, ProvidersResponse2, ProvidersResponses, ProviderType, RawAudioContent, RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ReadAllConfigData, ReadAllConfigResponse, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceRequest, ReadResourceResponse, ReadResourceResponse2, ReadResourceResponses, ReasoningContent, Recipe, RecipeManifest, RecipeParameter, RecipeParameterInputType, RecipeParameterRequirement, RecipeToYamlData, RecipeToYamlError, RecipeToYamlErrors, RecipeToYamlRequest, RecipeToYamlResponse, RecipeToYamlResponse2, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponse, RecoverConfigResponses, RedactedThinkingContent, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponse, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponse, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionRequest, RemoveExtensionResponse, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponse, ReplyResponses, RepoVariantsResponse, ResetPromptData, ResetPromptErrors, ResetPromptResponse, ResetPromptResponses, ResourceContents, ResourceMetadata, Response, RestartAgentData, RestartAgentErrors, RestartAgentRequest, RestartAgentResponse, RestartAgentResponse2, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentRequest, ResumeAgentResponse, ResumeAgentResponse2, ResumeAgentResponses, RetryConfig, Role, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponse, RunNowHandlerResponses, RunNowResponse, SamplingConfig, SavePromptData, SavePromptErrors, SavePromptRequest, SavePromptResponse, SavePromptResponses, SaveRecipeData, SaveRecipeError, SaveRecipeErrors, SaveRecipeRequest, SaveRecipeResponse, SaveRecipeResponse2, SaveRecipeResponses, ScanRecipeData, ScanRecipeRequest, ScanRecipeResponse, ScanRecipeResponse2, ScanRecipeResponses, ScheduledJob, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeRequest, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponse, SearchHfModelsResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponse, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, Session, SessionDisplayInfo, SessionExtensionsResponse, SessionInsights, SessionListResponse, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponse, SessionsHandlerResponses, SessionsQuery, SessionType, SetConfigProviderData, SetProviderRequest, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, SetSlashCommandRequest, Settings, SetupResponse, SlashCommand, SlashCommandsResponse, StartAgentData, StartAgentError, StartAgentErrors, StartAgentRequest, StartAgentResponse, StartAgentResponses, StartNanogptSetupData, StartNanogptSetupResponse, StartNanogptSetupResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponse, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponse, StartTetrateSetupResponses, StartTunnelData, StartTunnelError, StartTunnelErrors, StartTunnelResponse, StartTunnelResponses, StatusData, StatusResponse, StatusResponses, StopAgentData, StopAgentErrors, StopAgentRequest, StopAgentResponse, StopAgentResponses, StopTunnelData, StopTunnelError, StopTunnelErrors, StopTunnelResponses, SubRecipe, SuccessCheck, SystemInfo, SystemInfoData, SystemInfoResponse, SystemInfoResponses, SystemNotificationContent, SystemNotificationType, TaskSupport, TelemetryEventRequest, Template, TextContent, ThinkingContent, TokenState, Tool, ToolAnnotations, ToolConfirmationRequest, ToolExecution, ToolInfo, ToolPermission, ToolRequest, ToolResponse, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponse, TranscribeDictationResponses, TranscribeRequest, TranscribeResponse, TunnelInfo, TunnelState, UiMetadata, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponse, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderRequest, UpdateCustomProviderResponse, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionRequest, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponse, UpdateModelSettingsResponses, UpdateProviderRequest, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleRequest, UpdateScheduleResponse, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameRequest, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesError, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesRequest, UpdateSessionUserRecipeValuesResponse, UpdateSessionUserRecipeValuesResponse2, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirRequest, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigQuery, UpsertConfigResponse, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsQuery, UpsertPermissionsResponse, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponse, ValidateConfigResponses, WhisperModelResponse, WindowProps } from './types.gen'; diff --git a/ui/desktop/src/api/sdk.gen.ts b/ui/desktop/src/api/sdk.gen.ts index f548c1e54f61..65822fa67ba2 100644 --- a/ui/desktop/src/api/sdk.gen.ts +++ b/ui/desktop/src/api/sdk.gen.ts @@ -2,7 +2,7 @@ import type { Client, Options as Options2, TDataShape } from './client'; import { client } from './client.gen'; -import type { AddExtensionData, AddExtensionErrors, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponses, BackupConfigData, BackupConfigErrors, BackupConfigResponses, CallToolData, CallToolErrors, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, CheckProviderData, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionResponses, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleResponses, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponses, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelResponses, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeResponses, ExportAppData, ExportAppErrors, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponses, ForkSessionData, ForkSessionErrors, ForkSessionResponses, GetCanonicalModelInfoData, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponses, GetPromptsData, GetPromptsResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponses, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponses, ImportAppData, ImportAppErrors, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponses, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponses, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsErrors, ListAppsResponses, ListLocalModelsData, ListLocalModelsResponses, ListModelsData, ListModelsResponses, ListRecipesData, ListRecipesErrors, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponses, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, ParseRecipeData, ParseRecipeErrors, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponses, ProvidersData, ProvidersResponses, ReadAllConfigData, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceResponses, RecipeToYamlData, RecipeToYamlErrors, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponses, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponses, RestartAgentData, RestartAgentErrors, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentResponses, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponses, SavePromptData, SavePromptErrors, SavePromptResponses, SaveRecipeData, SaveRecipeErrors, SaveRecipeResponses, ScanRecipeData, ScanRecipeResponses, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponses, SetConfigProviderData, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, StartAgentData, StartAgentErrors, StartAgentResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, StartTunnelData, StartTunnelErrors, StartTunnelResponses, StatusData, StatusResponses, StopAgentData, StopAgentErrors, StopAgentResponses, StopTunnelData, StopTunnelErrors, StopTunnelResponses, SystemInfoData, SystemInfoResponses, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponses, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponses, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponses } from './types.gen'; +import type { AddExtensionData, AddExtensionErrors, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponses, BackupConfigData, BackupConfigErrors, BackupConfigResponses, CallToolData, CallToolErrors, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, CheckProviderData, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionResponses, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleResponses, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponses, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelResponses, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeResponses, ExportAppData, ExportAppErrors, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponses, ForkSessionData, ForkSessionErrors, ForkSessionResponses, GetCanonicalModelInfoData, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponses, GetPromptsData, GetPromptsResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponses, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponses, ImportAppData, ImportAppErrors, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponses, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponses, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsErrors, ListAppsResponses, ListLocalModelsData, ListLocalModelsResponses, ListModelsData, ListModelsResponses, ListRecipesData, ListRecipesErrors, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponses, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, ParseRecipeData, ParseRecipeErrors, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponses, ProvidersData, ProvidersResponses, ReadAllConfigData, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceResponses, RecipeToYamlData, RecipeToYamlErrors, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponses, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponses, RestartAgentData, RestartAgentErrors, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentResponses, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponses, SavePromptData, SavePromptErrors, SavePromptResponses, SaveRecipeData, SaveRecipeErrors, SaveRecipeResponses, ScanRecipeData, ScanRecipeResponses, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponses, SetConfigProviderData, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, StartAgentData, StartAgentErrors, StartAgentResponses, StartNanogptSetupData, StartNanogptSetupResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, StartTunnelData, StartTunnelErrors, StartTunnelResponses, StatusData, StatusResponses, StopAgentData, StopAgentErrors, StopAgentResponses, StopTunnelData, StopTunnelErrors, StopTunnelResponses, SystemInfoData, SystemInfoResponses, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponses, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponses, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponses } from './types.gen'; export type Options = Options2 & { /** diff --git a/ui/desktop/src/components/LocalModelSetup.tsx b/ui/desktop/src/components/LocalModelSetup.tsx index e26b514563cb..3a77c26718bf 100644 --- a/ui/desktop/src/components/LocalModelSetup.tsx +++ b/ui/desktop/src/components/LocalModelSetup.tsx @@ -1,82 +1,17 @@ -import { useState, useEffect, useCallback, useRef } from 'react'; import { useConfig } from './ConfigContext'; -import { - listLocalModels, - downloadHfModel, - getLocalModelDownloadProgress, - cancelLocalModelDownload, - type DownloadProgress, - type LocalModelResponse, -} from '../api'; import { toastService } from '../toasts'; -import { trackOnboardingSetupFailed } from '../utils/analytics'; import { Goose } from './icons'; +import LocalModelPicker from './onboarding/LocalModelPicker'; interface LocalModelSetupProps { onSuccess: () => void; onCancel: () => void; } -const formatBytes = (bytes: number): string => { - if (bytes < 1024) return `${bytes}B`; - if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)}KB`; - if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(0)}MB`; - return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}GB`; -}; - -const formatSize = (bytes: number): string => { - const mb = bytes / (1024 * 1024); - return mb >= 1024 ? `${(mb / 1024).toFixed(1)}GB` : `${mb.toFixed(0)}MB`; -}; - -type SetupPhase = 'loading' | 'select' | 'downloading' | 'error'; - export function LocalModelSetup({ onSuccess, onCancel }: LocalModelSetupProps) { const { upsert } = useConfig(); - const [phase, setPhase] = useState('loading'); - const [models, setModels] = useState([]); - const [selectedModelId, setSelectedModelId] = useState(null); - const [downloadProgress, setDownloadProgress] = useState(null); - const [errorMessage, setErrorMessage] = useState(null); - const [showAllModels, setShowAllModels] = useState(false); - const pollRef = useRef | null>(null); - - const cleanup = useCallback(() => { - if (pollRef.current) { - clearInterval(pollRef.current); - pollRef.current = null; - } - }, []); - useEffect(() => cleanup, [cleanup]); - - useEffect(() => { - const load = async () => { - try { - const response = await listLocalModels(); - if (response.data) { - setModels(response.data); - - const alreadyDownloaded = response.data.find((m) => m.status.state === 'Downloaded'); - if (alreadyDownloaded) { - setSelectedModelId(alreadyDownloaded.id); - } else { - const recommended = response.data.find((m: LocalModelResponse) => m.recommended); - if (recommended) setSelectedModelId(recommended.id); - } - } - } catch (error) { - console.error('Failed to load local models:', error); - setErrorMessage('Failed to load available models. Please try again.'); - setPhase('error'); - return; - } - setPhase('select'); - }; - load(); - }, []); - - const finishSetup = async (modelId: string) => { + const handleConfigured = async (_providerName: string, modelId: string) => { await upsert('GOOSE_PROVIDER', 'local', false); await upsert('GOOSE_MODEL', modelId, false); toastService.success({ @@ -86,312 +21,20 @@ export function LocalModelSetup({ onSuccess, onCancel }: LocalModelSetupProps) { onSuccess(); }; - const startDownload = async (modelId: string) => { - setPhase('downloading'); - setDownloadProgress(null); - setErrorMessage(null); - - const model = models.find((m) => m.id === modelId); - if (!model) { - setErrorMessage('Model not found'); - setPhase('error'); - return; - } - - try { - await downloadHfModel({ body: { spec: model.id } }); - } catch (error) { - console.error('Failed to start download:', error); - setErrorMessage('Failed to start download. Please try again.'); - trackOnboardingSetupFailed('local', 'download_start_failed'); - setPhase('error'); - return; - } - - pollRef.current = setInterval(async () => { - try { - const response = await getLocalModelDownloadProgress({ path: { model_id: modelId } }); - if (response.data) { - setDownloadProgress(response.data); - if (response.data.status === 'completed') { - cleanup(); - await finishSetup(modelId); - } else if (response.data.status === 'failed') { - cleanup(); - setErrorMessage(response.data.error || 'Download failed.'); - trackOnboardingSetupFailed('local', response.data.error || 'download_failed'); - setPhase('error'); - } else if (response.data.status === 'cancelled') { - cleanup(); - setPhase('select'); - } - } - } catch { - cleanup(); - setErrorMessage('Lost connection to download. Please try again.'); - trackOnboardingSetupFailed('local', 'progress_poll_failed'); - setPhase('error'); - } - }, 500); - }; - - const handleCancel = async () => { - if (phase === 'downloading' && selectedModelId) { - cleanup(); - try { - await cancelLocalModelDownload({ path: { model_id: selectedModelId } }); - } catch { - // best-effort - } - setDownloadProgress(null); - setPhase('select'); - } else { - onCancel(); - } - }; - - const handlePrimaryAction = async () => { - if (!selectedModelId) return; - const model = models.find((m) => m.id === selectedModelId); - if (!model) return; - if (model.status.state === 'Downloaded') { - await finishSetup(model.id); - } else { - await startDownload(model.id); - } - }; - - const recommended = models.find((m) => m.recommended); - const otherModels = models.filter((m) => m.id !== recommended?.id); - const selectedModel = models.find((m) => m.id === selectedModelId); - - if (phase === 'loading') { - return ( -
-
-

Checking available models...

-
- ); - } - return (
- {/* Header */}

Run Locally

- Download a model to run Goose entirely on your machine — no API keys, no accounts, completely free and private. + Download a model to run Goose entirely on your machine — no API keys, no accounts, + completely free and private.

- {/* Error state */} - {phase === 'error' && ( -
-
-

{errorMessage}

-
- - -
- )} - - {/* Model selection */} - {phase === 'select' && ( -
- {/* Recommended model card */} - {recommended && ( -
setSelectedModelId(recommended.id)} - className={`relative w-full p-4 sm:p-6 border rounded-xl cursor-pointer transition-all duration-200 group ${ - selectedModelId === recommended.id - ? 'border-blue-500 bg-blue-500/5' - : 'border-border-subtle hover:border-border-default' - }`} - > -
- - Best for your machine - -
-
- setSelectedModelId(recommended.id)} - className="cursor-pointer flex-shrink-0 mt-1" - /> -
-
- - {recommended.id} - - {recommended.status.state === 'Downloaded' && ( - - Ready - - )} -
-

- {formatSize(recommended.size_bytes)} -

-
-
-
- )} - - {/* Expandable other models */} - {otherModels.length > 0 && ( -
- - - {showAllModels && ( -
- {otherModels.map((model) => ( -
setSelectedModelId(model.id)} - className={`w-full p-4 border rounded-xl cursor-pointer transition-all duration-200 ${ - selectedModelId === model.id - ? 'border-blue-500 bg-blue-500/5' - : 'border-border-subtle hover:border-border-default' - }`} - > -
- setSelectedModelId(model.id)} - className="cursor-pointer flex-shrink-0 mt-0.5" - /> -
-
- {model.id} - {formatSize(model.size_bytes)} - {model.status.state === 'Downloaded' && ( - - Ready - - )} -
-
-
-
- ))} -
- )} -
- )} - - {/* Primary action */} - - - -
- )} - - {/* Downloading state */} - {phase === 'downloading' && selectedModel && ( -
-
-

- Downloading {selectedModel.id} -

- - {downloadProgress ? ( -
- {/* Progress bar */} -
-
-
- - {/* Stats row */} -
- - {formatBytes(downloadProgress.bytes_downloaded)} of{' '} - {formatBytes(downloadProgress.total_bytes)} - - {downloadProgress.progress_percent.toFixed(0)}% -
- -
- {downloadProgress.speed_bps ? ( - {formatBytes(downloadProgress.speed_bps)}/s - ) : ( - - )} - {downloadProgress.eta_seconds != null && downloadProgress.eta_seconds > 0 && ( - - ~{downloadProgress.eta_seconds < 60 - ? `${Math.round(downloadProgress.eta_seconds)}s` - : `${Math.round(downloadProgress.eta_seconds / 60)}m`}{' '} - remaining - - )} -
-
- ) : ( -
-
- Starting download... -
- )} -
- - -
- )} +
); } diff --git a/ui/desktop/src/components/onboarding/FreeCreditCards.tsx b/ui/desktop/src/components/onboarding/FreeOptionCards.tsx similarity index 58% rename from ui/desktop/src/components/onboarding/FreeCreditCards.tsx rename to ui/desktop/src/components/onboarding/FreeOptionCards.tsx index 65931d343aed..1b89415bee78 100644 --- a/ui/desktop/src/components/onboarding/FreeCreditCards.tsx +++ b/ui/desktop/src/components/onboarding/FreeOptionCards.tsx @@ -2,13 +2,17 @@ import { useState } from 'react'; import { startNanogptSetup } from '../../utils/nanogptSetup'; import { startTetrateSetup } from '../../utils/tetrateSetup'; import { Tetrate } from '../icons'; +import LocalModelPicker from './LocalModelPicker'; +import { trackOnboardingProviderSelected } from '../../utils/analytics'; +import { HardDrive } from 'lucide-react'; const TETRATE = 'tetrate' as const; const NANOGPT = 'nanogpt' as const; -type FreeCreditProvider = typeof TETRATE | typeof NANOGPT; +const LOCAL_PROVIDER = 'local' as const; +type FreeOption = typeof TETRATE | typeof NANOGPT | typeof LOCAL_PROVIDER; -interface FreeCreditCardsProps { - onConfigured: (providerName: string) => void; +interface FreeOptionCardsProps { + onConfigured: (providerName: string, modelId?: string) => void; } const ChevronRight = () => ( @@ -17,14 +21,21 @@ const ChevronRight = () => ( ); -export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) { +const cardClass = (isSelected: boolean) => + `w-full p-4 bg-transparent border rounded-lg transition-all duration-200 cursor-pointer group ${ + isSelected ? 'border-blue-400' : 'hover:border-blue-400' + }`; + +export default function FreeOptionCards({ onConfigured }: FreeOptionCardsProps) { const [error, setError] = useState<{ message: string; - type: FreeCreditProvider; + type: typeof TETRATE | typeof NANOGPT; } | null>(null); + const [selectedProvider, setSelectedProvider] = useState(null); - const handleSetup = async (type: FreeCreditProvider) => { + const handleSetup = async (type: typeof TETRATE | typeof NANOGPT) => { setError(null); + setSelectedProvider(type); try { const result = type === TETRATE ? await startTetrateSetup() : await startNanogptSetup(); if (result.success) { @@ -40,6 +51,11 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) const handleTetrateSetup = () => handleSetup(TETRATE); const handleNanogptSetup = () => handleSetup(NANOGPT); + const handleRunLocallyClick = () => { + trackOnboardingProviderSelected(LOCAL_PROVIDER); + setSelectedProvider(LOCAL_PROVIDER); + }; + const handleRetry = () => { if (!error) return; if (error.type === TETRATE) { @@ -48,16 +64,19 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) handleNanogptSetup(); }; + if (selectedProvider === LOCAL_PROVIDER) { + return ( + setSelectedProvider(null)} /> + ); + } + return (
-

Choose a provider to get started.

+

Choose an option to get started.

-
+
@@ -74,10 +93,7 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps)

-
+
@@ -93,6 +109,24 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps) Sign up to receive 60M free tokens for 7 days.

+ +
+
+
+ + Use a Local Model + + Free & Private + +
+
+ +
+
+

+ Download a model and run entirely on your machine. No API keys, no accounts. +

+
{error && ( @@ -106,8 +140,6 @@ export default function FreeCreditCards({ onConfigured }: FreeCreditCardsProps)
)} - -

You can switch providers anytime.

); diff --git a/ui/desktop/src/components/onboarding/LocalModelPicker.tsx b/ui/desktop/src/components/onboarding/LocalModelPicker.tsx new file mode 100644 index 000000000000..cb3b8050e7ac --- /dev/null +++ b/ui/desktop/src/components/onboarding/LocalModelPicker.tsx @@ -0,0 +1,376 @@ +import { useState, useEffect, useCallback, useRef } from 'react'; +import { + listLocalModels, + downloadHfModel, + getLocalModelDownloadProgress, + cancelLocalModelDownload, + type DownloadProgress, + type LocalModelResponse, +} from '../../api'; +import { trackOnboardingSetupFailed } from '../../utils/analytics'; + +interface LocalModelPickerProps { + onConfigured: (providerName: string, modelId: string) => void; + onBack?: () => void; +} + +const formatBytes = (bytes: number): string => { + if (bytes < 1024) return `${bytes}B`; + if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)}KB`; + if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(0)}MB`; + return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)}GB`; +}; + +const formatSize = (bytes: number): string => { + const mb = bytes / (1024 * 1024); + return mb >= 1024 ? `${(mb / 1024).toFixed(1)}GB` : `${mb.toFixed(0)}MB`; +}; + +const LOCAL_PROVIDER = 'local'; + +type Phase = 'loading' | 'select' | 'downloading' | 'error'; + +export default function LocalModelPicker({ onConfigured, onBack }: LocalModelPickerProps) { + const [phase, setPhase] = useState('loading'); + const [models, setModels] = useState([]); + const [selectedModelId, setSelectedModelId] = useState(null); + const [downloadProgress, setDownloadProgress] = useState(null); + const [errorMessage, setErrorMessage] = useState(null); + const [showAllModels, setShowAllModels] = useState(false); + const pollRef = useRef | null>(null); + + const cleanup = useCallback(() => { + if (pollRef.current) { + clearInterval(pollRef.current); + pollRef.current = null; + } + }, []); + + useEffect(() => cleanup, [cleanup]); + + useEffect(() => { + const load = async () => { + try { + const response = await listLocalModels(); + if (response.data) { + setModels(response.data); + + const alreadyDownloaded = response.data.find((m) => m.status.state === 'Downloaded'); + if (alreadyDownloaded) { + setSelectedModelId(alreadyDownloaded.id); + } else { + const recommended = response.data.find((m: LocalModelResponse) => m.recommended); + if (recommended) setSelectedModelId(recommended.id); + } + } + } catch (error) { + console.error('Failed to load local models:', error); + setErrorMessage('Failed to load available models. Please try again.'); + setPhase('error'); + return; + } + setPhase('select'); + }; + load(); + }, []); + + const finishSetup = (modelId: string) => { + onConfigured(LOCAL_PROVIDER, modelId); + }; + + const startDownload = async (modelId: string) => { + setPhase('downloading'); + setDownloadProgress(null); + setErrorMessage(null); + + const model = models.find((m) => m.id === modelId); + if (!model) { + setErrorMessage('Model not found'); + setPhase('error'); + return; + } + + try { + await downloadHfModel({ body: { spec: model.id } }); + } catch (error) { + console.error('Failed to start download:', error); + setErrorMessage('Failed to start download. Please try again.'); + trackOnboardingSetupFailed(LOCAL_PROVIDER, 'download_start_failed'); + setPhase('error'); + return; + } + + pollRef.current = setInterval(async () => { + try { + const response = await getLocalModelDownloadProgress({ path: { model_id: modelId } }); + if (response.data) { + setDownloadProgress(response.data); + if (response.data.status === 'completed') { + cleanup(); + finishSetup(modelId); + } else if (response.data.status === 'failed') { + cleanup(); + setErrorMessage(response.data.error || 'Download failed.'); + trackOnboardingSetupFailed(LOCAL_PROVIDER, response.data.error || 'download_failed'); + setPhase('error'); + } else if (response.data.status === 'cancelled') { + cleanup(); + setPhase('select'); + } + } + } catch { + cleanup(); + setErrorMessage('Lost connection to download. Please try again.'); + trackOnboardingSetupFailed(LOCAL_PROVIDER, 'progress_poll_failed'); + setPhase('error'); + } + }, 500); + }; + + const handleCancelDownload = async () => { + if (phase === 'downloading' && selectedModelId) { + cleanup(); + try { + await cancelLocalModelDownload({ path: { model_id: selectedModelId } }); + } catch { + // best-effort + } + setDownloadProgress(null); + setPhase('select'); + } + }; + + const handlePrimaryAction = async () => { + if (!selectedModelId) return; + const model = models.find((m) => m.id === selectedModelId); + if (!model) return; + if (model.status.state === 'Downloaded') { + finishSetup(model.id); + } else { + await startDownload(model.id); + } + }; + + const recommended = models.find((m) => m.recommended); + const otherModels = models.filter((m) => m.id !== recommended?.id); + const selectedModel = models.find((m) => m.id === selectedModelId); + + if (phase === 'loading') { + return ( +
+
+

Checking available models...

+
+ ); + } + + return ( +
+

+ Choose a model to download and run on your machine. +

+ + {phase === 'error' && ( +
+
+

{errorMessage}

+
+ +
+ )} + + {phase === 'select' && ( +
+ {recommended && ( +
setSelectedModelId(recommended.id)} + className={`relative w-full p-4 border rounded-lg cursor-pointer transition-all duration-200 ${ + selectedModelId === recommended.id + ? 'border-blue-500 bg-blue-500/5' + : 'border-border-subtle hover:border-border-default' + }`} + > +
+ + Best for your machine + +
+
+ setSelectedModelId(recommended.id)} + className="cursor-pointer flex-shrink-0 mt-1" + /> +
+
+ {recommended.id} + {recommended.status.state === 'Downloaded' && ( + + Ready + + )} +
+

+ {formatSize(recommended.size_bytes)} +

+
+
+
+ )} + + {otherModels.length > 0 && ( +
+ + + {showAllModels && ( +
+ {otherModels.map((model) => ( +
setSelectedModelId(model.id)} + className={`w-full p-4 border rounded-lg cursor-pointer transition-all duration-200 ${ + selectedModelId === model.id + ? 'border-blue-500 bg-blue-500/5' + : 'border-border-subtle hover:border-border-default' + }`} + > +
+ setSelectedModelId(model.id)} + className="cursor-pointer flex-shrink-0 mt-0.5" + /> +
+
+ + {model.id} + + + {formatSize(model.size_bytes)} + + {model.status.state === 'Downloaded' && ( + + Ready + + )} +
+
+
+
+ ))} +
+ )} +
+ )} + + + + {onBack && ( + + )} +
+ )} + + {phase === 'downloading' && selectedModel && ( +
+
+

+ Downloading {selectedModel.id} +

+ + {downloadProgress ? ( +
+
+
+
+ +
+ + {formatBytes(downloadProgress.bytes_downloaded)} of{' '} + {formatBytes(downloadProgress.total_bytes)} + + {downloadProgress.progress_percent.toFixed(0)}% +
+ +
+ {downloadProgress.speed_bps ? ( + {formatBytes(downloadProgress.speed_bps)}/s + ) : ( + + )} + {downloadProgress.eta_seconds != null && downloadProgress.eta_seconds > 0 && ( + + ~ + {downloadProgress.eta_seconds < 60 + ? `${Math.round(downloadProgress.eta_seconds)}s` + : `${Math.round(downloadProgress.eta_seconds / 60)}m`}{' '} + remaining + + )} +
+
+ ) : ( +
+
+ Starting download... +
+ )} +
+ + +
+ )} +
+ ); +} diff --git a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx index 25c25c41525a..c5430d9815a3 100644 --- a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx +++ b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx @@ -52,18 +52,21 @@ export default function OnboardingGuard({ children }: OnboardingGuardProps) { } }, [isCheckingProvider, hasProvider]); - const handleConfigured = async (providerName: string) => { - const providers = await getProviders(true); - const matchedProvider = providers.find((p) => p.name === providerName); + const handleConfigured = async (providerName: string, modelId?: string) => { await upsert('GOOSE_PROVIDER', providerName, false); - if (matchedProvider) { - await upsert('GOOSE_MODEL', matchedProvider.metadata.default_model, false); + if (modelId) { + await upsert('GOOSE_MODEL', modelId, false); + setConfiguredModel(modelId); + } else { + const providers = await getProviders(true); + const matchedProvider = providers.find((p) => p.name === providerName); + if (matchedProvider) { + await upsert('GOOSE_MODEL', matchedProvider.metadata.default_model, false); + setConfiguredModel(matchedProvider.metadata.default_model); + } } await refreshCurrentModelAndProvider(); setConfiguredProvider(providerName); - if (matchedProvider) { - setConfiguredModel(matchedProvider.metadata.default_model); - } }; const finishOnboarding = async (telemetryEnabled: boolean) => { diff --git a/ui/desktop/src/components/onboarding/OnboardingSuccess.tsx b/ui/desktop/src/components/onboarding/OnboardingSuccess.tsx index b4c300641e37..f3380b2648ee 100644 --- a/ui/desktop/src/components/onboarding/OnboardingSuccess.tsx +++ b/ui/desktop/src/components/onboarding/OnboardingSuccess.tsx @@ -2,6 +2,8 @@ import { useState } from 'react'; import { Button } from '../ui/button'; import PrivacyInfoModal from './PrivacyInfoModal'; +const LOCAL_PROVIDER = 'local'; + interface OnboardingSuccessProps { providerName: string; onFinish: (telemetryEnabled: boolean) => void; @@ -33,7 +35,9 @@ export default function OnboardingSuccess({ providerName, onFinish }: Onboarding

- Connected to {providerName} + {providerName === LOCAL_PROVIDER + ? 'Local model ready' + : `Connected to ${providerName}`}

You're all set to start using Goose.

diff --git a/ui/desktop/src/components/onboarding/ProviderSelector.tsx b/ui/desktop/src/components/onboarding/ProviderSelector.tsx index e74bf6a6e54f..18bde4914dcf 100644 --- a/ui/desktop/src/components/onboarding/ProviderSelector.tsx +++ b/ui/desktop/src/components/onboarding/ProviderSelector.tsx @@ -7,7 +7,7 @@ import { } from '../../api'; import { Select } from '../ui/Select'; import ProviderConfigForm from './ProviderConfigForm'; -import FreeCreditCards from './FreeCreditCards'; +import FreeOptionCards from './FreeOptionCards'; import CustomProviderForm from '../settings/providers/modal/subcomponents/forms/CustomProviderForm'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog'; import { Gift, Key, Plus } from 'lucide-react'; @@ -24,7 +24,7 @@ interface ProviderOption { } interface ProviderSelectorProps { - onConfigured: (providerName: string) => void; + onConfigured: (providerName: string, modelId?: string) => void; onFirstSelection?: () => void; } @@ -114,9 +114,9 @@ export default function ProviderSelector({ }`} > - Free Credits + Try for Free

- Get free credits from a provider to try Goose + Free credits or run locally on your machine

@@ -139,7 +139,7 @@ export default function ProviderSelector({ {selectedPath === FREE_CREDITS && (
- +
)} diff --git a/ui/desktop/src/featureFlags.ts b/ui/desktop/src/featureFlags.ts index b3a0b9ec9562..663954c73f5b 100644 --- a/ui/desktop/src/featureFlags.ts +++ b/ui/desktop/src/featureFlags.ts @@ -1 +1 @@ -export const USE_NEW_ONBOARDING = false; +export const USE_NEW_ONBOARDING = true; From 898310f510d286a15aef15280ecaeaac675f9301 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Mon, 23 Feb 2026 17:48:09 +1100 Subject: [PATCH 27/41] fix test --- crates/goose/src/providers/nanogpt.rs | 1 - ui/desktop/package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/goose/src/providers/nanogpt.rs b/crates/goose/src/providers/nanogpt.rs index 75dea3151c25..408dde0a04ff 100644 --- a/crates/goose/src/providers/nanogpt.rs +++ b/crates/goose/src/providers/nanogpt.rs @@ -209,6 +209,5 @@ mod tests { assert_eq!(metadata.config_keys[0].name, NANOGPT_API_KEY); assert!(metadata.config_keys[0].required); assert!(metadata.config_keys[0].secret); - assert!(metadata.allows_unlisted_models); } } diff --git a/ui/desktop/package.json b/ui/desktop/package.json index 25e40d6d01a1..321a73b5d9ec 100644 --- a/ui/desktop/package.json +++ b/ui/desktop/package.json @@ -11,7 +11,7 @@ "scripts": { "typecheck": "tsc --noEmit", "generate-api": "openapi-ts", - "start-gui": "npm run generate-api && electron-forge start", + "start-gui": "npm run generate-api && GOOSE_PATH_ROOT=/tmp/lifei-test electron-forge start", "start-gui-debug": "npm run generate-api && electron-forge start -- --inspect=9229", "start": "cd ../.. && just run-ui", "start:test-error": "GOOSE_TEST_ERROR=true electron-forge start", From 3398621c8105749b29904dd946da8790f55d771a Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Mon, 23 Feb 2026 18:00:20 +1100 Subject: [PATCH 28/41] revert testing code --- ui/desktop/package.json | 2 +- ui/desktop/src/featureFlags.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/desktop/package.json b/ui/desktop/package.json index 321a73b5d9ec..25e40d6d01a1 100644 --- a/ui/desktop/package.json +++ b/ui/desktop/package.json @@ -11,7 +11,7 @@ "scripts": { "typecheck": "tsc --noEmit", "generate-api": "openapi-ts", - "start-gui": "npm run generate-api && GOOSE_PATH_ROOT=/tmp/lifei-test electron-forge start", + "start-gui": "npm run generate-api && electron-forge start", "start-gui-debug": "npm run generate-api && electron-forge start -- --inspect=9229", "start": "cd ../.. && just run-ui", "start:test-error": "GOOSE_TEST_ERROR=true electron-forge start", diff --git a/ui/desktop/src/featureFlags.ts b/ui/desktop/src/featureFlags.ts index 663954c73f5b..b3a0b9ec9562 100644 --- a/ui/desktop/src/featureFlags.ts +++ b/ui/desktop/src/featureFlags.ts @@ -1 +1 @@ -export const USE_NEW_ONBOARDING = true; +export const USE_NEW_ONBOARDING = false; From 07443dd501a096e38e12211e2d0edbf620d1cd5f Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Mon, 23 Feb 2026 18:59:46 +1100 Subject: [PATCH 29/41] fix test compilation --- crates/goose/src/config/signup_nanogpt/mod.rs | 4 +++- crates/goose/src/providers/init.rs | 2 +- crates/goose/src/providers/mod.rs | 2 +- crates/goose/tests/agent.rs | 1 + crates/goose/tests/compaction.rs | 1 + 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/crates/goose/src/config/signup_nanogpt/mod.rs b/crates/goose/src/config/signup_nanogpt/mod.rs index 40e3d58bf0c9..a106443deb01 100644 --- a/crates/goose/src/config/signup_nanogpt/mod.rs +++ b/crates/goose/src/config/signup_nanogpt/mod.rs @@ -65,7 +65,9 @@ async fn poll_for_token(device_code: &str) -> Result { return Err(anyhow!("Invalid device code")); } 429 => { - return Err(anyhow!("Too many requests to NanoGPT. Please wait a moment and try again.")); + return Err(anyhow!( + "Too many requests to NanoGPT. Please wait a moment and try again." + )); } other => { let error_text = response.text().await.unwrap_or_default(); diff --git a/crates/goose/src/providers/init.rs b/crates/goose/src/providers/init.rs index cdeda4bd77af..5fac8421c12e 100644 --- a/crates/goose/src/providers/init.rs +++ b/crates/goose/src/providers/init.rs @@ -16,8 +16,8 @@ use super::{ google::GoogleProvider, lead_worker::LeadWorkerProvider, litellm::LiteLLMProvider, - nanogpt::NanoGptProvider, local_inference::LocalInferenceProvider, + nanogpt::NanoGptProvider, ollama::OllamaProvider, openai::OpenAiProvider, openrouter::OpenRouterProvider, diff --git a/crates/goose/src/providers/mod.rs b/crates/goose/src/providers/mod.rs index ce231d36bf0f..7d37d3135430 100644 --- a/crates/goose/src/providers/mod.rs +++ b/crates/goose/src/providers/mod.rs @@ -23,8 +23,8 @@ pub mod google; mod init; pub mod lead_worker; pub mod litellm; -pub mod nanogpt; pub mod local_inference; +pub mod nanogpt; pub mod oauth; pub mod ollama; pub mod openai; diff --git a/crates/goose/tests/agent.rs b/crates/goose/tests/agent.rs index f00fb000ad7c..b6f1d026df93 100644 --- a/crates/goose/tests/agent.rs +++ b/crates/goose/tests/agent.rs @@ -372,6 +372,7 @@ mod tests { known_models: vec![], model_doc_link: "".to_string(), config_keys: vec![], + setup_steps: vec![], } } diff --git a/crates/goose/tests/compaction.rs b/crates/goose/tests/compaction.rs index 43ac2a655916..824cfbc73282 100644 --- a/crates/goose/tests/compaction.rs +++ b/crates/goose/tests/compaction.rs @@ -190,6 +190,7 @@ impl ProviderDef for MockCompactionProvider { known_models: vec![], model_doc_link: "".to_string(), config_keys: vec![], + setup_steps: vec![], } } From 0fef53208ec26be2e42aa20260a80d3404d90e7e Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Tue, 24 Feb 2026 13:10:08 +1100 Subject: [PATCH 30/41] adddres copilot review comments --- ui/desktop/src/components/LocalModelSetup.tsx | 2 +- ui/desktop/src/components/onboarding/FreeOptionCards.tsx | 3 ++- ui/desktop/src/components/onboarding/OnboardingGuard.tsx | 2 +- ui/desktop/src/components/onboarding/OnboardingSuccess.tsx | 2 +- ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx | 2 +- ui/desktop/src/components/onboarding/ProviderSelector.tsx | 2 +- ui/desktop/src/utils/nanogptSetup.ts | 2 +- 7 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ui/desktop/src/components/LocalModelSetup.tsx b/ui/desktop/src/components/LocalModelSetup.tsx index 3a77c26718bf..bb96a22c8412 100644 --- a/ui/desktop/src/components/LocalModelSetup.tsx +++ b/ui/desktop/src/components/LocalModelSetup.tsx @@ -29,7 +29,7 @@ export function LocalModelSetup({ onSuccess, onCancel }: LocalModelSetupProps) {

Run Locally

- Download a model to run Goose entirely on your machine — no API keys, no accounts, + Download a model to run goose entirely on your machine — no API keys, no accounts, completely free and private.

diff --git a/ui/desktop/src/components/onboarding/FreeOptionCards.tsx b/ui/desktop/src/components/onboarding/FreeOptionCards.tsx index 1b89415bee78..3cb10b829167 100644 --- a/ui/desktop/src/components/onboarding/FreeOptionCards.tsx +++ b/ui/desktop/src/components/onboarding/FreeOptionCards.tsx @@ -60,8 +60,9 @@ export default function FreeOptionCards({ onConfigured }: FreeOptionCardsProps) if (!error) return; if (error.type === TETRATE) { handleTetrateSetup(); + } else { + handleNanogptSetup(); } - handleNanogptSetup(); }; if (selectedProvider === LOCAL_PROVIDER) { diff --git a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx index c5430d9815a3..897819706481 100644 --- a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx +++ b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx @@ -111,7 +111,7 @@ export default function OnboardingGuard({ children }: OnboardingGuardProps) {
-

Welcome to Goose

+

Welcome to goose

Your local AI agent. Connect an AI model provider to get started.

diff --git a/ui/desktop/src/components/onboarding/OnboardingSuccess.tsx b/ui/desktop/src/components/onboarding/OnboardingSuccess.tsx index f3380b2648ee..6ba09891d78e 100644 --- a/ui/desktop/src/components/onboarding/OnboardingSuccess.tsx +++ b/ui/desktop/src/components/onboarding/OnboardingSuccess.tsx @@ -39,7 +39,7 @@ export default function OnboardingSuccess({ providerName, onFinish }: Onboarding ? 'Local model ready' : `Connected to ${providerName}`} -

You're all set to start using Goose.

+

You're all set to start using goose.

diff --git a/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx b/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx index 585ab7817f42..22bfc75afa2a 100644 --- a/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx +++ b/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx @@ -37,7 +37,7 @@ export default function PrivacyInfoModal({ isOpen, onClose }: PrivacyInfoModalPr

What we collect:

  • Operating system, version, and architecture
  • -
  • Goose version and install method
  • +
  • goose version and install method
  • Provider and model used
  • Extensions and tool usage counts (names only)
  • Session metrics (duration, interaction count, token usage)
  • diff --git a/ui/desktop/src/components/onboarding/ProviderSelector.tsx b/ui/desktop/src/components/onboarding/ProviderSelector.tsx index 18bde4914dcf..ffa7f541e6a6 100644 --- a/ui/desktop/src/components/onboarding/ProviderSelector.tsx +++ b/ui/desktop/src/components/onboarding/ProviderSelector.tsx @@ -85,6 +85,7 @@ export default function ProviderSelector({ const handleOwnProviderClick = () => { setSelectedPath(OWN_PROVIDER); + onFirstSelection?.(); }; const handleProviderSelect = (option: ProviderOption | null) => { @@ -120,7 +121,6 @@ export default function ProviderSelector({

- {/* Own Provider card */}
Date: Tue, 24 Feb 2026 14:37:22 +1100 Subject: [PATCH 31/41] resolve merge conflicts --- ui/desktop/src/api/index.ts | 4 ++-- ui/desktop/src/api/sdk.gen.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/desktop/src/api/index.ts b/ui/desktop/src/api/index.ts index 8af4598d0ec4..a6dbae19929f 100644 --- a/ui/desktop/src/api/index.ts +++ b/ui/desktop/src/api/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { addExtension, agentAddExtension, agentRemoveExtension, backupConfig, callTool, cancelDownload, cancelLocalModelDownload, checkProvider, configureProviderOauth, confirmToolAction, createCustomProvider, createRecipe, createSchedule, decodeRecipe, deleteLocalModel, deleteModel, deleteRecipe, deleteSchedule, deleteSession, detectProvider, diagnostics, downloadHfModel, downloadModel, encodeRecipe, exportApp, exportSession, forkSession, getCanonicalModelInfo, getCustomProvider, getDictationConfig, getDownloadProgress, getExtensions, getLocalModelDownloadProgress, getModelSettings, getPrompt, getPrompts, getProviderCatalog, getProviderCatalogTemplate, getProviderModels, getRepoFiles, getSession, getSessionExtensions, getSessionInsights, getSlashCommands, getTools, getTunnelStatus, importApp, importSession, initConfig, inspectRunningJob, killRunningJob, listApps, listLocalModels, listModels, listRecipes, listSchedules, listSessions, mcpUiProxy, type Options, parseRecipe, pauseSchedule, providers, readAllConfig, readConfig, readResource, recipeToYaml, recoverConfig, removeConfig, removeCustomProvider, removeExtension, reply, resetPrompt, restartAgent, resumeAgent, runNowHandler, savePrompt, saveRecipe, scanRecipe, scheduleRecipe, searchHfModels, searchSessions, sendTelemetryEvent, sessionsHandler, setConfigProvider, setRecipeSlashCommand, startAgent, startOpenrouterSetup, startTetrateSetup, startTunnel, status, stopAgent, stopTunnel, systemInfo, transcribeDictation, unpauseSchedule, updateAgentProvider, updateCustomProvider, updateFromSession, updateModelSettings, updateSchedule, updateSessionName, updateSessionUserRecipeValues, updateWorkingDir, upsertConfig, upsertPermissions, validateConfig } from './sdk.gen'; -export type { ActionRequired, ActionRequiredData, AddExtensionData, AddExtensionErrors, AddExtensionRequest, AddExtensionResponse, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponse, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponse, AgentRemoveExtensionResponses, Annotations, Author, AuthorRequest, BackupConfigData, BackupConfigErrors, BackupConfigResponse, BackupConfigResponses, CallToolData, CallToolErrors, CallToolRequest, CallToolResponse, CallToolResponse2, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, ChatRequest, CheckProviderData, CheckProviderRequest, ClientOptions, CommandType, ConfigKey, ConfigKeyQuery, ConfigResponse, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionRequest, ConfirmToolActionResponses, Content, Conversation, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponse, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeRequest, CreateRecipeResponse, CreateRecipeResponse2, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleRequest, CreateScheduleResponse, CreateScheduleResponses, CspMetadata, DeclarativeProviderConfig, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeRequest, DecodeRecipeResponse, DecodeRecipeResponse2, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeRequest, DeleteRecipeResponse, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponse, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderRequest, DetectProviderResponse, DetectProviderResponse2, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponse, DiagnosticsResponses, DictationProvider, DictationProviderStatus, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponse, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelRequest, DownloadModelResponses, DownloadProgress, DownloadStatus, EmbeddedResource, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeRequest, EncodeRecipeResponse, EncodeRecipeResponse2, EncodeRecipeResponses, Envs, ErrorResponse, ExportAppData, ExportAppError, ExportAppErrors, ExportAppResponse, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponse, ExportSessionResponses, ExtensionConfig, ExtensionData, ExtensionEntry, ExtensionLoadResult, ExtensionQuery, ExtensionResponse, ForkRequest, ForkResponse, ForkSessionData, ForkSessionErrors, ForkSessionResponse, ForkSessionResponses, FrontendToolRequest, GetCanonicalModelInfoData, GetCanonicalModelInfoResponse, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponse, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponse, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponse, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponse, GetExtensionsResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponse, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponse, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponse, GetPromptResponses, GetPromptsData, GetPromptsResponse, GetPromptsResponses, GetProviderCatalogData, GetProviderCatalogErrors, GetProviderCatalogResponse, GetProviderCatalogResponses, GetProviderCatalogTemplateData, GetProviderCatalogTemplateErrors, GetProviderCatalogTemplateResponse, GetProviderCatalogTemplateResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponse, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponse, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponse, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponse, GetSessionInsightsResponses, GetSessionResponse, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponse, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsQuery, GetToolsResponse, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponse, GetTunnelStatusResponses, GooseApp, HfGgufFile, HfModelInfo, HfQuantVariant, Icon, ImageContent, ImportAppData, ImportAppError, ImportAppErrors, ImportAppRequest, ImportAppResponse, ImportAppResponse2, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionRequest, ImportSessionResponse, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponse, InitConfigResponses, InspectJobResponse, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponse, InspectRunningJobResponses, JsonObject, KillJobResponse, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsError, ListAppsErrors, ListAppsRequest, ListAppsResponse, ListAppsResponse2, ListAppsResponses, ListLocalModelsData, ListLocalModelsResponse, ListLocalModelsResponses, ListModelsData, ListModelsResponse, ListModelsResponses, ListRecipeResponse, ListRecipesData, ListRecipesErrors, ListRecipesResponse, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponse, ListSchedulesResponse2, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponse, ListSessionsResponses, LoadedProvider, LocalModelResponse, McpAppResource, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, Message, MessageContent, MessageEvent, MessageMetadata, ModelCapabilities, ModelConfig, ModelDownloadStatus, ModelInfo, ModelInfoData, ModelInfoQuery, ModelInfoResponse, ModelSettings, ModelTemplate, ParseRecipeData, ParseRecipeError, ParseRecipeErrors, ParseRecipeRequest, ParseRecipeResponse, ParseRecipeResponse2, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponse, PauseScheduleResponses, Permission, PermissionLevel, PermissionsMetadata, PrincipalType, PromptContentResponse, PromptsListResponse, ProviderCatalogEntry, ProviderDetails, ProviderEngine, ProviderMetadata, ProvidersData, ProvidersResponse, ProvidersResponse2, ProvidersResponses, ProviderTemplate, ProviderType, RawAudioContent, RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ReadAllConfigData, ReadAllConfigResponse, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceRequest, ReadResourceResponse, ReadResourceResponse2, ReadResourceResponses, ReasoningContent, Recipe, RecipeManifest, RecipeParameter, RecipeParameterInputType, RecipeParameterRequirement, RecipeToYamlData, RecipeToYamlError, RecipeToYamlErrors, RecipeToYamlRequest, RecipeToYamlResponse, RecipeToYamlResponse2, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponse, RecoverConfigResponses, RedactedThinkingContent, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponse, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponse, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionRequest, RemoveExtensionResponse, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponse, ReplyResponses, RepoVariantsResponse, ResetPromptData, ResetPromptErrors, ResetPromptResponse, ResetPromptResponses, ResourceContents, ResourceMetadata, Response, RestartAgentData, RestartAgentErrors, RestartAgentRequest, RestartAgentResponse, RestartAgentResponse2, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentRequest, ResumeAgentResponse, ResumeAgentResponse2, ResumeAgentResponses, RetryConfig, Role, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponse, RunNowHandlerResponses, RunNowResponse, SamplingConfig, SavePromptData, SavePromptErrors, SavePromptRequest, SavePromptResponse, SavePromptResponses, SaveRecipeData, SaveRecipeError, SaveRecipeErrors, SaveRecipeRequest, SaveRecipeResponse, SaveRecipeResponse2, SaveRecipeResponses, ScanRecipeData, ScanRecipeRequest, ScanRecipeResponse, ScanRecipeResponse2, ScanRecipeResponses, ScheduledJob, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeRequest, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponse, SearchHfModelsResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponse, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, Session, SessionDisplayInfo, SessionExtensionsResponse, SessionInsights, SessionListResponse, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponse, SessionsHandlerResponses, SessionsQuery, SessionType, SetConfigProviderData, SetProviderRequest, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, SetSlashCommandRequest, Settings, SetupResponse, SlashCommand, SlashCommandsResponse, StartAgentData, StartAgentError, StartAgentErrors, StartAgentRequest, StartAgentResponse, StartAgentResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponse, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponse, StartTetrateSetupResponses, StartTunnelData, StartTunnelError, StartTunnelErrors, StartTunnelResponse, StartTunnelResponses, StatusData, StatusResponse, StatusResponses, StopAgentData, StopAgentErrors, StopAgentRequest, StopAgentResponse, StopAgentResponses, StopTunnelData, StopTunnelError, StopTunnelErrors, StopTunnelResponses, SubRecipe, SuccessCheck, SystemInfo, SystemInfoData, SystemInfoResponse, SystemInfoResponses, SystemNotificationContent, SystemNotificationType, TaskSupport, TelemetryEventRequest, Template, TextContent, ThinkingContent, TokenState, Tool, ToolAnnotations, ToolConfirmationRequest, ToolExecution, ToolInfo, ToolPermission, ToolRequest, ToolResponse, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponse, TranscribeDictationResponses, TranscribeRequest, TranscribeResponse, TunnelInfo, TunnelState, UiMetadata, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponse, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderRequest, UpdateCustomProviderResponse, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionRequest, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponse, UpdateModelSettingsResponses, UpdateProviderRequest, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleRequest, UpdateScheduleResponse, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameRequest, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesError, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesRequest, UpdateSessionUserRecipeValuesResponse, UpdateSessionUserRecipeValuesResponse2, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirRequest, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigQuery, UpsertConfigResponse, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsQuery, UpsertPermissionsResponse, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponse, ValidateConfigResponses, WhisperModelResponse, WindowProps } from './types.gen'; +export { addExtension, agentAddExtension, agentRemoveExtension, backupConfig, callTool, cancelDownload, cancelLocalModelDownload, checkProvider, configureProviderOauth, confirmToolAction, createCustomProvider, createRecipe, createSchedule, decodeRecipe, deleteLocalModel, deleteModel, deleteRecipe, deleteSchedule, deleteSession, detectProvider, diagnostics, downloadHfModel, downloadModel, encodeRecipe, exportApp, exportSession, forkSession, getCanonicalModelInfo, getCustomProvider, getDictationConfig, getDownloadProgress, getExtensions, getLocalModelDownloadProgress, getModelSettings, getPrompt, getPrompts, getProviderCatalog, getProviderCatalogTemplate, getProviderModels, getRepoFiles, getSession, getSessionExtensions, getSessionInsights, getSlashCommands, getTools, getTunnelStatus, importApp, importSession, initConfig, inspectRunningJob, killRunningJob, listApps, listLocalModels, listModels, listRecipes, listSchedules, listSessions, mcpUiProxy, type Options, parseRecipe, pauseSchedule, providers, readAllConfig, readConfig, readResource, recipeToYaml, recoverConfig, removeConfig, removeCustomProvider, removeExtension, reply, resetPrompt, restartAgent, resumeAgent, runNowHandler, savePrompt, saveRecipe, scanRecipe, scheduleRecipe, searchHfModels, searchSessions, sendTelemetryEvent, sessionsHandler, setConfigProvider, setRecipeSlashCommand, startAgent, startNanogptSetup, startOpenrouterSetup, startTetrateSetup, startTunnel, status, stopAgent, stopTunnel, systemInfo, transcribeDictation, unpauseSchedule, updateAgentProvider, updateCustomProvider, updateFromSession, updateModelSettings, updateSchedule, updateSessionName, updateSessionUserRecipeValues, updateWorkingDir, upsertConfig, upsertPermissions, validateConfig } from './sdk.gen'; +export type { ActionRequired, ActionRequiredData, AddExtensionData, AddExtensionErrors, AddExtensionRequest, AddExtensionResponse, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponse, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponse, AgentRemoveExtensionResponses, Annotations, Author, AuthorRequest, BackupConfigData, BackupConfigErrors, BackupConfigResponse, BackupConfigResponses, CallToolData, CallToolErrors, CallToolRequest, CallToolResponse, CallToolResponse2, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, ChatRequest, CheckProviderData, CheckProviderRequest, ClientOptions, CommandType, ConfigKey, ConfigKeyQuery, ConfigResponse, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionRequest, ConfirmToolActionResponses, Content, Conversation, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponse, CreateCustomProviderResponse2, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeRequest, CreateRecipeResponse, CreateRecipeResponse2, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleRequest, CreateScheduleResponse, CreateScheduleResponses, CspMetadata, DeclarativeProviderConfig, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeRequest, DecodeRecipeResponse, DecodeRecipeResponse2, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeRequest, DeleteRecipeResponse, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponse, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderRequest, DetectProviderResponse, DetectProviderResponse2, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponse, DiagnosticsResponses, DictationProvider, DictationProviderStatus, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponse, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelRequest, DownloadModelResponses, DownloadProgress, DownloadStatus, EmbeddedResource, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeRequest, EncodeRecipeResponse, EncodeRecipeResponse2, EncodeRecipeResponses, Envs, ErrorResponse, ExportAppData, ExportAppError, ExportAppErrors, ExportAppResponse, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponse, ExportSessionResponses, ExtensionConfig, ExtensionData, ExtensionEntry, ExtensionLoadResult, ExtensionQuery, ExtensionResponse, ForkRequest, ForkResponse, ForkSessionData, ForkSessionErrors, ForkSessionResponse, ForkSessionResponses, FrontendToolRequest, GetCanonicalModelInfoData, GetCanonicalModelInfoResponse, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponse, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponse, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponse, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponse, GetExtensionsResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponse, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponse, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponse, GetPromptResponses, GetPromptsData, GetPromptsResponse, GetPromptsResponses, GetProviderCatalogData, GetProviderCatalogErrors, GetProviderCatalogResponse, GetProviderCatalogResponses, GetProviderCatalogTemplateData, GetProviderCatalogTemplateErrors, GetProviderCatalogTemplateResponse, GetProviderCatalogTemplateResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponse, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponse, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponse, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponse, GetSessionInsightsResponses, GetSessionResponse, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponse, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsQuery, GetToolsResponse, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponse, GetTunnelStatusResponses, GooseApp, HfGgufFile, HfModelInfo, HfQuantVariant, Icon, ImageContent, ImportAppData, ImportAppError, ImportAppErrors, ImportAppRequest, ImportAppResponse, ImportAppResponse2, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionRequest, ImportSessionResponse, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponse, InitConfigResponses, InspectJobResponse, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponse, InspectRunningJobResponses, JsonObject, KillJobResponse, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsError, ListAppsErrors, ListAppsRequest, ListAppsResponse, ListAppsResponse2, ListAppsResponses, ListLocalModelsData, ListLocalModelsResponse, ListLocalModelsResponses, ListModelsData, ListModelsResponse, ListModelsResponses, ListRecipeResponse, ListRecipesData, ListRecipesErrors, ListRecipesResponse, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponse, ListSchedulesResponse2, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponse, ListSessionsResponses, LoadedProvider, LocalModelResponse, McpAppResource, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, Message, MessageContent, MessageEvent, MessageMetadata, ModelCapabilities, ModelConfig, ModelDownloadStatus, ModelInfo, ModelInfoData, ModelInfoQuery, ModelInfoResponse, ModelSettings, ModelTemplate, ParseRecipeData, ParseRecipeError, ParseRecipeErrors, ParseRecipeRequest, ParseRecipeResponse, ParseRecipeResponse2, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponse, PauseScheduleResponses, Permission, PermissionLevel, PermissionsMetadata, PrincipalType, PromptContentResponse, PromptsListResponse, ProviderCatalogEntry, ProviderDetails, ProviderEngine, ProviderMetadata, ProvidersData, ProvidersResponse, ProvidersResponse2, ProvidersResponses, ProviderTemplate, ProviderType, RawAudioContent, RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ReadAllConfigData, ReadAllConfigResponse, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceRequest, ReadResourceResponse, ReadResourceResponse2, ReadResourceResponses, ReasoningContent, Recipe, RecipeManifest, RecipeParameter, RecipeParameterInputType, RecipeParameterRequirement, RecipeToYamlData, RecipeToYamlError, RecipeToYamlErrors, RecipeToYamlRequest, RecipeToYamlResponse, RecipeToYamlResponse2, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponse, RecoverConfigResponses, RedactedThinkingContent, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponse, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponse, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionRequest, RemoveExtensionResponse, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponse, ReplyResponses, RepoVariantsResponse, ResetPromptData, ResetPromptErrors, ResetPromptResponse, ResetPromptResponses, ResourceContents, ResourceMetadata, Response, RestartAgentData, RestartAgentErrors, RestartAgentRequest, RestartAgentResponse, RestartAgentResponse2, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentRequest, ResumeAgentResponse, ResumeAgentResponse2, ResumeAgentResponses, RetryConfig, Role, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponse, RunNowHandlerResponses, RunNowResponse, SamplingConfig, SavePromptData, SavePromptErrors, SavePromptRequest, SavePromptResponse, SavePromptResponses, SaveRecipeData, SaveRecipeError, SaveRecipeErrors, SaveRecipeRequest, SaveRecipeResponse, SaveRecipeResponse2, SaveRecipeResponses, ScanRecipeData, ScanRecipeRequest, ScanRecipeResponse, ScanRecipeResponse2, ScanRecipeResponses, ScheduledJob, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeRequest, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponse, SearchHfModelsResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponse, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, Session, SessionDisplayInfo, SessionExtensionsResponse, SessionInsights, SessionListResponse, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponse, SessionsHandlerResponses, SessionsQuery, SessionType, SetConfigProviderData, SetProviderRequest, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, SetSlashCommandRequest, Settings, SetupResponse, SlashCommand, SlashCommandsResponse, StartAgentData, StartAgentError, StartAgentErrors, StartAgentRequest, StartAgentResponse, StartAgentResponses, StartNanogptSetupData, StartNanogptSetupResponse, StartNanogptSetupResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponse, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponse, StartTetrateSetupResponses, StartTunnelData, StartTunnelError, StartTunnelErrors, StartTunnelResponse, StartTunnelResponses, StatusData, StatusResponse, StatusResponses, StopAgentData, StopAgentErrors, StopAgentRequest, StopAgentResponse, StopAgentResponses, StopTunnelData, StopTunnelError, StopTunnelErrors, StopTunnelResponses, SubRecipe, SuccessCheck, SystemInfo, SystemInfoData, SystemInfoResponse, SystemInfoResponses, SystemNotificationContent, SystemNotificationType, TaskSupport, TelemetryEventRequest, Template, TextContent, ThinkingContent, TokenState, Tool, ToolAnnotations, ToolConfirmationRequest, ToolExecution, ToolInfo, ToolPermission, ToolRequest, ToolResponse, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponse, TranscribeDictationResponses, TranscribeRequest, TranscribeResponse, TunnelInfo, TunnelState, UiMetadata, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponse, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderRequest, UpdateCustomProviderResponse, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionRequest, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponse, UpdateModelSettingsResponses, UpdateProviderRequest, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleRequest, UpdateScheduleResponse, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameRequest, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesError, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesRequest, UpdateSessionUserRecipeValuesResponse, UpdateSessionUserRecipeValuesResponse2, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirRequest, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigQuery, UpsertConfigResponse, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsQuery, UpsertPermissionsResponse, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponse, ValidateConfigResponses, WhisperModelResponse, WindowProps } from './types.gen'; diff --git a/ui/desktop/src/api/sdk.gen.ts b/ui/desktop/src/api/sdk.gen.ts index d863e017b60a..fe33b4c7aeeb 100644 --- a/ui/desktop/src/api/sdk.gen.ts +++ b/ui/desktop/src/api/sdk.gen.ts @@ -2,7 +2,7 @@ import type { Client, Options as Options2, TDataShape } from './client'; import { client } from './client.gen'; -import type { AddExtensionData, AddExtensionErrors, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponses, BackupConfigData, BackupConfigErrors, BackupConfigResponses, CallToolData, CallToolErrors, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, CheckProviderData, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionResponses, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleResponses, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponses, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelResponses, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeResponses, ExportAppData, ExportAppErrors, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponses, ForkSessionData, ForkSessionErrors, ForkSessionResponses, GetCanonicalModelInfoData, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponses, GetPromptsData, GetPromptsResponses, GetProviderCatalogData, GetProviderCatalogErrors, GetProviderCatalogResponses, GetProviderCatalogTemplateData, GetProviderCatalogTemplateErrors, GetProviderCatalogTemplateResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponses, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponses, ImportAppData, ImportAppErrors, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponses, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponses, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsErrors, ListAppsResponses, ListLocalModelsData, ListLocalModelsResponses, ListModelsData, ListModelsResponses, ListRecipesData, ListRecipesErrors, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponses, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, ParseRecipeData, ParseRecipeErrors, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponses, ProvidersData, ProvidersResponses, ReadAllConfigData, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceResponses, RecipeToYamlData, RecipeToYamlErrors, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponses, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponses, RestartAgentData, RestartAgentErrors, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentResponses, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponses, SavePromptData, SavePromptErrors, SavePromptResponses, SaveRecipeData, SaveRecipeErrors, SaveRecipeResponses, ScanRecipeData, ScanRecipeResponses, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponses, SetConfigProviderData, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, StartAgentData, StartAgentErrors, StartAgentResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, StartTunnelData, StartTunnelErrors, StartTunnelResponses, StatusData, StatusResponses, StopAgentData, StopAgentErrors, StopAgentResponses, StopTunnelData, StopTunnelErrors, StopTunnelResponses, SystemInfoData, SystemInfoResponses, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponses, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponses, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponses } from './types.gen'; +import type { AddExtensionData, AddExtensionErrors, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponses, BackupConfigData, BackupConfigErrors, BackupConfigResponses, CallToolData, CallToolErrors, CallToolResponses, CancelDownloadData, CancelDownloadErrors, CancelDownloadResponses, CancelLocalModelDownloadData, CancelLocalModelDownloadErrors, CancelLocalModelDownloadResponses, CheckProviderData, ConfigureProviderOauthData, ConfigureProviderOauthErrors, ConfigureProviderOauthResponses, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionResponses, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleResponses, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeResponses, DeleteLocalModelData, DeleteLocalModelErrors, DeleteLocalModelResponses, DeleteModelData, DeleteModelErrors, DeleteModelResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponses, DownloadHfModelData, DownloadHfModelErrors, DownloadHfModelResponses, DownloadModelData, DownloadModelErrors, DownloadModelResponses, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeResponses, ExportAppData, ExportAppErrors, ExportAppResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponses, ForkSessionData, ForkSessionErrors, ForkSessionResponses, GetCanonicalModelInfoData, GetCanonicalModelInfoResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponses, GetDictationConfigData, GetDictationConfigResponses, GetDownloadProgressData, GetDownloadProgressErrors, GetDownloadProgressResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponses, GetLocalModelDownloadProgressData, GetLocalModelDownloadProgressErrors, GetLocalModelDownloadProgressResponses, GetModelSettingsData, GetModelSettingsErrors, GetModelSettingsResponses, GetPromptData, GetPromptErrors, GetPromptResponses, GetPromptsData, GetPromptsResponses, GetProviderCatalogData, GetProviderCatalogErrors, GetProviderCatalogResponses, GetProviderCatalogTemplateData, GetProviderCatalogTemplateErrors, GetProviderCatalogTemplateResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponses, GetRepoFilesData, GetRepoFilesResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponses, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponses, ImportAppData, ImportAppErrors, ImportAppResponses, ImportSessionData, ImportSessionErrors, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponses, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponses, KillRunningJobData, KillRunningJobResponses, ListAppsData, ListAppsErrors, ListAppsResponses, ListLocalModelsData, ListLocalModelsResponses, ListModelsData, ListModelsResponses, ListRecipesData, ListRecipesErrors, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponses, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, ParseRecipeData, ParseRecipeErrors, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponses, ProvidersData, ProvidersResponses, ReadAllConfigData, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceResponses, RecipeToYamlData, RecipeToYamlErrors, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponses, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponses, ResetPromptData, ResetPromptErrors, ResetPromptResponses, RestartAgentData, RestartAgentErrors, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentResponses, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponses, SavePromptData, SavePromptErrors, SavePromptResponses, SaveRecipeData, SaveRecipeErrors, SaveRecipeResponses, ScanRecipeData, ScanRecipeResponses, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeResponses, SearchHfModelsData, SearchHfModelsErrors, SearchHfModelsResponses, SearchSessionsData, SearchSessionsErrors, SearchSessionsResponses, SendTelemetryEventData, SendTelemetryEventResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponses, SetConfigProviderData, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, StartAgentData, StartAgentErrors, StartAgentResponses, StartNanogptSetupData, StartNanogptSetupResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, StartTunnelData, StartTunnelErrors, StartTunnelResponses, StatusData, StatusResponses, StopAgentData, StopAgentErrors, StopAgentResponses, StopTunnelData, StopTunnelErrors, StopTunnelResponses, SystemInfoData, SystemInfoResponses, TranscribeDictationData, TranscribeDictationErrors, TranscribeDictationResponses, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionResponses, UpdateModelSettingsData, UpdateModelSettingsErrors, UpdateModelSettingsResponses, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponses } from './types.gen'; export type Options = Options2 & { /** From c708c26595da3a72d0bc2769a8abec4b796fd692 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Tue, 24 Feb 2026 15:01:09 +1100 Subject: [PATCH 32/41] text change --- .../components/onboarding/LocalModelPicker.tsx | 5 +++-- .../components/onboarding/ProviderSelector.tsx | 16 +++++++++------- ui/desktop/src/featureFlags.ts | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/ui/desktop/src/components/onboarding/LocalModelPicker.tsx b/ui/desktop/src/components/onboarding/LocalModelPicker.tsx index cb3b8050e7ac..561147bf1160 100644 --- a/ui/desktop/src/components/onboarding/LocalModelPicker.tsx +++ b/ui/desktop/src/components/onboarding/LocalModelPicker.tsx @@ -166,8 +166,9 @@ export default function LocalModelPicker({ onConfigured, onBack }: LocalModelPic return (
-

- Choose a model to download and run on your machine. +

+ ℹ️ Local models keep everything on your machine for full privacy. Performance and context + window size may vary compared to cloud providers depending on your hardware and model size.

{phase === 'error' && ( diff --git a/ui/desktop/src/components/onboarding/ProviderSelector.tsx b/ui/desktop/src/components/onboarding/ProviderSelector.tsx index ffa7f541e6a6..7a81ecb05bfc 100644 --- a/ui/desktop/src/components/onboarding/ProviderSelector.tsx +++ b/ui/desktop/src/components/onboarding/ProviderSelector.tsx @@ -12,10 +12,10 @@ import CustomProviderForm from '../settings/providers/modal/subcomponents/forms/ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog'; import { Gift, Key, Plus } from 'lucide-react'; -const FREE_CREDITS = 'free-credits'; -const OWN_PROVIDER = 'own-provider'; +const FREE_OPTIONS = 'free-options' as const; +const OWN_PROVIDER = 'own-provider' as const; -type SelectedPath = 'free-credits' | 'own-provider' | null; +type SelectedPath = typeof FREE_OPTIONS | typeof OWN_PROVIDER | null; interface ProviderOption { value: string; @@ -78,7 +78,7 @@ export default function ProviderSelector({ }; const handleFreeCreditClick = () => { - setSelectedPath(FREE_CREDITS); + setSelectedPath(FREE_OPTIONS); setSelectedOption(null); onFirstSelection?.(); }; @@ -109,13 +109,15 @@ export default function ProviderSelector({
- Try for Free + + Use Free/Local Providers +

Free credits or run locally on your machine

@@ -137,7 +139,7 @@ export default function ProviderSelector({
- {selectedPath === FREE_CREDITS && ( + {selectedPath === FREE_OPTIONS && (
diff --git a/ui/desktop/src/featureFlags.ts b/ui/desktop/src/featureFlags.ts index b3a0b9ec9562..663954c73f5b 100644 --- a/ui/desktop/src/featureFlags.ts +++ b/ui/desktop/src/featureFlags.ts @@ -1 +1 @@ -export const USE_NEW_ONBOARDING = false; +export const USE_NEW_ONBOARDING = true; From ae924c02c13d80bf3b7e2ff566052332a0538c72 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Tue, 24 Feb 2026 17:41:20 +1100 Subject: [PATCH 33/41] error message and error handling --- .../onboarding/LocalModelPicker.tsx | 9 ++- .../onboarding/PrivacyInfoModal.tsx | 69 ++++++++----------- .../forms/CustomProviderForm.tsx | 36 ++++++---- ui/desktop/src/components/ui/dialog.tsx | 2 +- 4 files changed, 57 insertions(+), 59 deletions(-) diff --git a/ui/desktop/src/components/onboarding/LocalModelPicker.tsx b/ui/desktop/src/components/onboarding/LocalModelPicker.tsx index 561147bf1160..215510a278e5 100644 --- a/ui/desktop/src/components/onboarding/LocalModelPicker.tsx +++ b/ui/desktop/src/components/onboarding/LocalModelPicker.tsx @@ -51,7 +51,7 @@ export default function LocalModelPicker({ onConfigured, onBack }: LocalModelPic useEffect(() => { const load = async () => { try { - const response = await listLocalModels(); + const response = await listLocalModels({ throwOnError: true }); if (response.data) { setModels(response.data); @@ -91,7 +91,7 @@ export default function LocalModelPicker({ onConfigured, onBack }: LocalModelPic } try { - await downloadHfModel({ body: { spec: model.id } }); + await downloadHfModel({ body: { spec: model.id }, throwOnError: true }); } catch (error) { console.error('Failed to start download:', error); setErrorMessage('Failed to start download. Please try again.'); @@ -102,7 +102,10 @@ export default function LocalModelPicker({ onConfigured, onBack }: LocalModelPic pollRef.current = setInterval(async () => { try { - const response = await getLocalModelDownloadProgress({ path: { model_id: modelId } }); + const response = await getLocalModelDownloadProgress({ + path: { model_id: modelId }, + throwOnError: true, + }); if (response.data) { setDownloadProgress(response.data); if (response.data.status === 'completed') { diff --git a/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx b/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx index 22bfc75afa2a..5dd3ee208a61 100644 --- a/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx +++ b/ui/desktop/src/components/onboarding/PrivacyInfoModal.tsx @@ -1,4 +1,4 @@ -import { Card } from '../ui/card'; +import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog'; interface PrivacyInfoModalProps { isOpen: boolean; @@ -6,48 +6,33 @@ interface PrivacyInfoModalProps { } export default function PrivacyInfoModal({ isOpen, onClose }: PrivacyInfoModalProps) { - if (!isOpen) return null; - return ( -
- e.stopPropagation()} - > - + !open && onClose()}> + + + Privacy details + -

Privacy details

-

- Anonymous usage data helps us understand how goose is used and identify areas for - improvement. -

-

What we collect:

-
    -
  • Operating system, version, and architecture
  • -
  • goose version and install method
  • -
  • Provider and model used
  • -
  • Extensions and tool usage counts (names only)
  • -
  • Session metrics (duration, interaction count, token usage)
  • -
  • Error types (e.g., "rate_limit", "auth" - no details)
  • -
-

- We never collect your conversations, code, tool arguments, error messages, or any personal - data. You can change this setting anytime in Settings. -

-
-
+
+

+ Anonymous usage data helps us understand how goose is used and identify areas for + improvement. +

+

What we collect:

+
    +
  • Operating system, version, and architecture
  • +
  • goose version and install method
  • +
  • Provider and model used
  • +
  • Extensions and tool usage counts (names only)
  • +
  • Session metrics (duration, interaction count, token usage)
  • +
  • Error types (e.g., "rate_limit", "auth" - no details)
  • +
+

+ We never collect your conversations, code, tool arguments, error messages, or any + personal data. You can change this setting anytime in Settings. +

+
+ + ); } diff --git a/ui/desktop/src/components/settings/providers/modal/subcomponents/forms/CustomProviderForm.tsx b/ui/desktop/src/components/settings/providers/modal/subcomponents/forms/CustomProviderForm.tsx index 7a9337654a40..3078433498bc 100644 --- a/ui/desktop/src/components/settings/providers/modal/subcomponents/forms/CustomProviderForm.tsx +++ b/ui/desktop/src/components/settings/providers/modal/subcomponents/forms/CustomProviderForm.tsx @@ -11,7 +11,7 @@ import ProviderCatalogPicker from '../ProviderCatalogPicker'; type Step = 'choice' | 'catalog' | 'form'; interface CustomProviderFormProps { - onSubmit: (data: UpdateCustomProviderRequest) => void; + onSubmit: (data: UpdateCustomProviderRequest) => void | Promise; onCancel: () => void; onDelete?: () => Promise; isActiveProvider?: boolean; @@ -43,6 +43,7 @@ export default function CustomProviderForm({ value: false, }); const [validationErrors, setValidationErrors] = useState>({}); + const [submitError, setSubmitError] = useState(null); const [showDeleteConfirmation, setShowDeleteConfirmation] = useState(false); // Template + step state @@ -181,8 +182,10 @@ export default function CustomProviderForm({ } }; - const handleSubmit = (e: React.FormEvent) => { + const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); + setSubmitError(null); + setValidationErrors({}); const errors: Record = {}; if (!displayName) errors.displayName = 'Display name is required'; @@ -223,17 +226,22 @@ export default function CustomProviderForm({ {} as Record ); - onSubmit({ - engine, - display_name: displayName, - api_url: apiUrl, - api_key: apiKey, - models: modelList, - supports_streaming: supportsStreaming, - requires_auth: requiresAuth, - headers: headersObject, - catalog_provider_id: selectedTemplate?.id ?? initialData?.catalog_provider_id ?? undefined, - }); + try { + await onSubmit({ + engine, + display_name: displayName, + api_url: apiUrl, + api_key: apiKey, + models: modelList, + supports_streaming: supportsStreaming, + requires_auth: requiresAuth, + headers: headersObject, + catalog_provider_id: selectedTemplate?.id ?? initialData?.catalog_provider_id ?? undefined, + }); + } catch (error) { + console.error('Failed to save custom provider:', error); + setSubmitError('Failed to save provider. Please check your configuration and try again.'); + } }; // Aggregate capability badges for template models @@ -643,6 +651,8 @@ export default function CustomProviderForm({ + {submitError &&

{submitError}

} + {showDeleteConfirmation ? (
{isActiveProvider ? ( diff --git a/ui/desktop/src/components/ui/dialog.tsx b/ui/desktop/src/components/ui/dialog.tsx index 6f7d4426d3d5..b65fd40c1144 100644 --- a/ui/desktop/src/components/ui/dialog.tsx +++ b/ui/desktop/src/components/ui/dialog.tsx @@ -55,7 +55,7 @@ function DialogContent({ {...props} > {children} - + Close From a1521001acfa4db69f9ddd25e856b1521ed54ca0 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Tue, 24 Feb 2026 17:55:20 +1100 Subject: [PATCH 34/41] track provider selected --- .../components/onboarding/FreeOptionCards.tsx | 2 -- .../components/onboarding/OnboardingGuard.tsx | 2 ++ ui/desktop/src/utils/analytics.ts | 18 ++---------------- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/ui/desktop/src/components/onboarding/FreeOptionCards.tsx b/ui/desktop/src/components/onboarding/FreeOptionCards.tsx index 3cb10b829167..d5343a9d8bf1 100644 --- a/ui/desktop/src/components/onboarding/FreeOptionCards.tsx +++ b/ui/desktop/src/components/onboarding/FreeOptionCards.tsx @@ -3,7 +3,6 @@ import { startNanogptSetup } from '../../utils/nanogptSetup'; import { startTetrateSetup } from '../../utils/tetrateSetup'; import { Tetrate } from '../icons'; import LocalModelPicker from './LocalModelPicker'; -import { trackOnboardingProviderSelected } from '../../utils/analytics'; import { HardDrive } from 'lucide-react'; const TETRATE = 'tetrate' as const; @@ -52,7 +51,6 @@ export default function FreeOptionCards({ onConfigured }: FreeOptionCardsProps) const handleNanogptSetup = () => handleSetup(NANOGPT); const handleRunLocallyClick = () => { - trackOnboardingProviderSelected(LOCAL_PROVIDER); setSelectedProvider(LOCAL_PROVIDER); }; diff --git a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx index 897819706481..2d0df8284d49 100644 --- a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx +++ b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx @@ -8,6 +8,7 @@ import OnboardingSuccess from './OnboardingSuccess'; import { trackOnboardingStarted, trackOnboardingCompleted, + trackOnboardingProviderSelected, trackTelemetryPreference, setTelemetryEnabled as setAnalyticsTelemetryEnabled, } from '../../utils/analytics'; @@ -53,6 +54,7 @@ export default function OnboardingGuard({ children }: OnboardingGuardProps) { }, [isCheckingProvider, hasProvider]); const handleConfigured = async (providerName: string, modelId?: string) => { + trackOnboardingProviderSelected(providerName); await upsert('GOOSE_PROVIDER', providerName, false); if (modelId) { await upsert('GOOSE_MODEL', modelId, false); diff --git a/ui/desktop/src/utils/analytics.ts b/ui/desktop/src/utils/analytics.ts index 4e85690291a1..ea4441e1936f 100644 --- a/ui/desktop/src/utils/analytics.ts +++ b/ui/desktop/src/utils/analytics.ts @@ -67,19 +67,7 @@ async function sendEvent( export type AnalyticsEvent = | { name: 'page_view'; properties: { page: string; referrer?: string } } | { name: 'onboarding_started'; properties: Record } - | { - name: 'onboarding_provider_selected'; - properties: { - method: - | 'api_key' - | 'openrouter' - | 'tetrate' - | 'chatgpt_codex' - | 'ollama' - | 'local' - | 'other'; - }; - } + | { name: 'onboarding_provider_selected'; properties: { method: string } } | { name: 'onboarding_completed'; properties: { provider: string; model?: string; duration_seconds?: number }; @@ -293,9 +281,7 @@ export function trackOnboardingStarted(): void { trackEvent({ name: 'onboarding_started', properties: {} }); } -export function trackOnboardingProviderSelected( - method: 'api_key' | 'openrouter' | 'tetrate' | 'chatgpt_codex' | 'ollama' | 'local' | 'other' -): void { +export function trackOnboardingProviderSelected(method: string): void { trackEvent({ name: 'onboarding_provider_selected', properties: { method }, From 4ec0e6f579cf9f4e27277e7d50da89810f7dde2e Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 25 Feb 2026 14:10:57 +1100 Subject: [PATCH 35/41] used nano-gpt to get canonical model data --- crates/goose/src/config/signup_nanogpt/mod.rs | 2 +- crates/goose/src/providers/nanogpt.rs | 6 +++--- ui/desktop/src/components/onboarding/FreeOptionCards.tsx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/goose/src/config/signup_nanogpt/mod.rs b/crates/goose/src/config/signup_nanogpt/mod.rs index a106443deb01..0c7a3f513ced 100644 --- a/crates/goose/src/config/signup_nanogpt/mod.rs +++ b/crates/goose/src/config/signup_nanogpt/mod.rs @@ -122,7 +122,7 @@ pub async fn complete_nanogpt_auth() -> Result { pub fn configure_nanogpt(config: &Config, api_key: String) -> Result<()> { config.set_secret("NANOGPT_API_KEY", &api_key)?; - config.set_goose_provider("nanogpt")?; + config.set_goose_provider("nano-gpt")?; config.set_goose_model(NANOGPT_DEFAULT_MODEL)?; Ok(()) } diff --git a/crates/goose/src/providers/nanogpt.rs b/crates/goose/src/providers/nanogpt.rs index 408dde0a04ff..661754ec3c34 100644 --- a/crates/goose/src/providers/nanogpt.rs +++ b/crates/goose/src/providers/nanogpt.rs @@ -12,10 +12,10 @@ use async_trait::async_trait; use futures::future::BoxFuture; use rmcp::model::Tool; -const NANOGPT_PROVIDER_NAME: &str = "nanogpt"; +const NANOGPT_PROVIDER_NAME: &str = "nano-gpt"; pub const NANOGPT_API_HOST: &str = "https://nano-gpt.com/api/v1"; pub const NANOGPT_SUBSCRIPTION_HOST: &str = "https://nano-gpt.com/api/subscription/v1"; -pub const NANOGPT_DEFAULT_MODEL: &str = "openai/gpt-4.1-nano"; +pub const NANOGPT_DEFAULT_MODEL: &str = "mistralai/mistral-large-3-675b-instruct"; pub const NANOGPT_DOC_URL: &str = "https://docs.nano-gpt.com/"; const NANOGPT_API_KEY: &str = "NANOGPT_API_KEY"; @@ -204,7 +204,7 @@ mod tests { #[test] fn test_metadata() { let metadata = NanoGptProvider::metadata(); - assert_eq!(metadata.name, "nanogpt"); + assert_eq!(metadata.name, "nano-gpt"); assert_eq!(metadata.default_model, "openai/gpt-4.1-nano"); assert_eq!(metadata.config_keys[0].name, NANOGPT_API_KEY); assert!(metadata.config_keys[0].required); diff --git a/ui/desktop/src/components/onboarding/FreeOptionCards.tsx b/ui/desktop/src/components/onboarding/FreeOptionCards.tsx index d5343a9d8bf1..a199b23a7f32 100644 --- a/ui/desktop/src/components/onboarding/FreeOptionCards.tsx +++ b/ui/desktop/src/components/onboarding/FreeOptionCards.tsx @@ -6,7 +6,7 @@ import LocalModelPicker from './LocalModelPicker'; import { HardDrive } from 'lucide-react'; const TETRATE = 'tetrate' as const; -const NANOGPT = 'nanogpt' as const; +const NANOGPT = 'nano-gpt' as const; const LOCAL_PROVIDER = 'local' as const; type FreeOption = typeof TETRATE | typeof NANOGPT | typeof LOCAL_PROVIDER; From 5c959b657932c1a3889cda8a40b7544816406ba6 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Wed, 25 Feb 2026 14:17:10 +1100 Subject: [PATCH 36/41] update text position --- .../onboarding/LocalModelPicker.tsx | 367 +++++++++--------- 1 file changed, 185 insertions(+), 182 deletions(-) diff --git a/ui/desktop/src/components/onboarding/LocalModelPicker.tsx b/ui/desktop/src/components/onboarding/LocalModelPicker.tsx index 215510a278e5..60f0c1f89429 100644 --- a/ui/desktop/src/components/onboarding/LocalModelPicker.tsx +++ b/ui/desktop/src/components/onboarding/LocalModelPicker.tsx @@ -168,213 +168,216 @@ export default function LocalModelPicker({ onConfigured, onBack }: LocalModelPic } return ( -
-

- ℹ️ Local models keep everything on your machine for full privacy. Performance and context - window size may vary compared to cloud providers depending on your hardware and model size. -

- - {phase === 'error' && ( -
-
-

{errorMessage}

+
+
+ {phase === 'error' && ( +
+
+

{errorMessage}

+
+
- -
- )} + )} - {phase === 'select' && ( -
- {recommended && ( -
setSelectedModelId(recommended.id)} - className={`relative w-full p-4 border rounded-lg cursor-pointer transition-all duration-200 ${ - selectedModelId === recommended.id - ? 'border-blue-500 bg-blue-500/5' - : 'border-border-subtle hover:border-border-default' - }`} - > -
- - Best for your machine - -
-
- setSelectedModelId(recommended.id)} - className="cursor-pointer flex-shrink-0 mt-1" - /> -
-
- {recommended.id} - {recommended.status.state === 'Downloaded' && ( - - Ready + {phase === 'select' && ( +
+ {recommended && ( +
setSelectedModelId(recommended.id)} + className={`relative w-full p-4 border rounded-lg cursor-pointer transition-all duration-200 ${ + selectedModelId === recommended.id + ? 'border-blue-500 bg-blue-500/5' + : 'border-border-subtle hover:border-border-default' + }`} + > +
+ + Best for your machine + +
+
+ setSelectedModelId(recommended.id)} + className="cursor-pointer flex-shrink-0 mt-1" + /> +
+
+ + {recommended.id} - )} + {recommended.status.state === 'Downloaded' && ( + + Ready + + )} +
+

+ {formatSize(recommended.size_bytes)} +

-

- {formatSize(recommended.size_bytes)} -

-
- )} + )} - {otherModels.length > 0 && ( -
- + {showAllModels ? 'Hide other sizes' : `Show ${otherModels.length} other sizes`} + + + + - {showAllModels && ( -
- {otherModels.map((model) => ( -
setSelectedModelId(model.id)} - className={`w-full p-4 border rounded-lg cursor-pointer transition-all duration-200 ${ - selectedModelId === model.id - ? 'border-blue-500 bg-blue-500/5' - : 'border-border-subtle hover:border-border-default' - }`} - > -
- setSelectedModelId(model.id)} - className="cursor-pointer flex-shrink-0 mt-0.5" - /> -
-
- - {model.id} - - - {formatSize(model.size_bytes)} - - {model.status.state === 'Downloaded' && ( - - Ready + {showAllModels && ( +
+ {otherModels.map((model) => ( +
setSelectedModelId(model.id)} + className={`w-full p-4 border rounded-lg cursor-pointer transition-all duration-200 ${ + selectedModelId === model.id + ? 'border-blue-500 bg-blue-500/5' + : 'border-border-subtle hover:border-border-default' + }`} + > +
+ setSelectedModelId(model.id)} + className="cursor-pointer flex-shrink-0 mt-0.5" + /> +
+
+ + {model.id} - )} + + {formatSize(model.size_bytes)} + + {model.status.state === 'Downloaded' && ( + + Ready + + )} +
-
- ))} -
- )} -
- )} - - + ))} +
+ )} +
+ )} - {onBack && ( - )} -
- )} - {phase === 'downloading' && selectedModel && ( -
-
-

- Downloading {selectedModel.id} -

+ {onBack && ( + + )} +
+ )} - {downloadProgress ? ( -
-
-
-
+ {phase === 'downloading' && selectedModel && ( +
+
+

+ Downloading {selectedModel.id} +

-
- - {formatBytes(downloadProgress.bytes_downloaded)} of{' '} - {formatBytes(downloadProgress.total_bytes)} - - {downloadProgress.progress_percent.toFixed(0)}% -
+ {downloadProgress ? ( +
+
+
+
-
- {downloadProgress.speed_bps ? ( - {formatBytes(downloadProgress.speed_bps)}/s - ) : ( - - )} - {downloadProgress.eta_seconds != null && downloadProgress.eta_seconds > 0 && ( +
- ~ - {downloadProgress.eta_seconds < 60 - ? `${Math.round(downloadProgress.eta_seconds)}s` - : `${Math.round(downloadProgress.eta_seconds / 60)}m`}{' '} - remaining + {formatBytes(downloadProgress.bytes_downloaded)} of{' '} + {formatBytes(downloadProgress.total_bytes)} - )} + {downloadProgress.progress_percent.toFixed(0)}% +
+ +
+ {downloadProgress.speed_bps ? ( + {formatBytes(downloadProgress.speed_bps)}/s + ) : ( + + )} + {downloadProgress.eta_seconds != null && downloadProgress.eta_seconds > 0 && ( + + ~ + {downloadProgress.eta_seconds < 60 + ? `${Math.round(downloadProgress.eta_seconds)}s` + : `${Math.round(downloadProgress.eta_seconds / 60)}m`}{' '} + remaining + + )} +
-
- ) : ( -
-
- Starting download... -
- )} -
+ ) : ( +
+
+ Starting download... +
+ )} +
- -
- )} + +
+ )} +
+

+ Local models keep everything on your machine for full privacy. Performance and context + window size may vary compared to cloud providers depending on your hardware and model size. +

); } From 5454a49031492c4f008ccabe17488d06483a406f Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Thu, 26 Feb 2026 11:00:31 +1100 Subject: [PATCH 37/41] fixed test --- crates/goose/src/providers/nanogpt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/goose/src/providers/nanogpt.rs b/crates/goose/src/providers/nanogpt.rs index 661754ec3c34..b969784c2562 100644 --- a/crates/goose/src/providers/nanogpt.rs +++ b/crates/goose/src/providers/nanogpt.rs @@ -205,7 +205,7 @@ mod tests { fn test_metadata() { let metadata = NanoGptProvider::metadata(); assert_eq!(metadata.name, "nano-gpt"); - assert_eq!(metadata.default_model, "openai/gpt-4.1-nano"); + assert_eq!(metadata.default_model, "mistralai/mistral-large-3-675b-instruct"); assert_eq!(metadata.config_keys[0].name, NANOGPT_API_KEY); assert!(metadata.config_keys[0].required); assert!(metadata.config_keys[0].secret); From 45f83d1d1ace0f29ca837cf47f6143c83243b305 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Mon, 16 Mar 2026 13:15:09 +1100 Subject: [PATCH 38/41] updated local model style --- .../components/onboarding/LocalModelPicker.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ui/desktop/src/components/onboarding/LocalModelPicker.tsx b/ui/desktop/src/components/onboarding/LocalModelPicker.tsx index 60f0c1f89429..b349213241d8 100644 --- a/ui/desktop/src/components/onboarding/LocalModelPicker.tsx +++ b/ui/desktop/src/components/onboarding/LocalModelPicker.tsx @@ -296,7 +296,7 @@ export default function LocalModelPicker({ onConfigured, onBack }: LocalModelPic @@ -374,10 +374,13 @@ export default function LocalModelPicker({ onConfigured, onBack }: LocalModelPic
)}
-

- Local models keep everything on your machine for full privacy. Performance and context - window size may vary compared to cloud providers depending on your hardware and model size. -

+
+

+ Local models keep everything on your machine for full privacy. Performance and context + window size may vary compared to cloud providers depending on your hardware and model + size. +

+
); } From da52745d00c5d8ce6cfb600d4a56b0a91a247920 Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Mon, 16 Mar 2026 13:54:11 +1100 Subject: [PATCH 39/41] tracking onboarding events --- crates/goose/src/posthog.rs | 11 +++++------ ui/desktop/src/components/ProviderGuard.tsx | 10 +++++----- .../src/components/onboarding/OnboardingGuard.tsx | 2 +- ui/desktop/src/utils/analytics.ts | 9 ++++++--- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/crates/goose/src/posthog.rs b/crates/goose/src/posthog.rs index 1c4693c0a8f3..b34945c16862 100644 --- a/crates/goose/src/posthog.rs +++ b/crates/goose/src/posthog.rs @@ -581,15 +581,14 @@ pub async fn emit_event( event_name: &str, mut properties: HashMap, ) -> Result<(), String> { - if !is_telemetry_enabled() { + // Only onboarding events are enabled for now. These bypass the telemetry + // check so we can track the funnel before the user makes their choice. + let is_onboarding_event = + event_name.starts_with("onboarding_") || event_name == "telemetry_preference_set"; + if !is_onboarding_event { return Ok(()); } - // Temporarily disabled - only session_started events are sent - let _ = (event_name, &mut properties); - return Ok(()); - - #[allow(unreachable_code)] let installation = load_or_create_installation(); insert(&mut properties, "os", std::env::consts::OS); diff --git a/ui/desktop/src/components/ProviderGuard.tsx b/ui/desktop/src/components/ProviderGuard.tsx index f6751e25fae8..6234ba26a77f 100644 --- a/ui/desktop/src/components/ProviderGuard.tsx +++ b/ui/desktop/src/components/ProviderGuard.tsx @@ -79,7 +79,7 @@ export default function ProviderGuard({ didSelectProvider, children }: ProviderG } | null>(null); const handleTetrateSetup = async () => { - trackOnboardingProviderSelected('tetrate'); + trackOnboardingProviderSelected({ method: 'tetrate' }); try { const result = await startTetrateSetup(); if (result.success) { @@ -107,7 +107,7 @@ export default function ProviderGuard({ didSelectProvider, children }: ProviderG }; const handleChatGptCodexSetup = async () => { - trackOnboardingProviderSelected('chatgpt_codex'); + trackOnboardingProviderSelected({ method: 'chatgpt_codex' }); try { const result = await startChatGptCodexSetup(); if (result.success) { @@ -136,7 +136,7 @@ export default function ProviderGuard({ didSelectProvider, children }: ProviderG }; const handleApiKeySuccess = async (provider: string, _model: string, apiKey: string) => { - trackOnboardingProviderSelected('api_key'); + trackOnboardingProviderSelected({ method: 'api_key' }); const keyName = `${provider.toUpperCase()}_API_KEY`; await upsert(keyName, apiKey, true); await upsert('GOOSE_PROVIDER', provider, false); @@ -161,7 +161,7 @@ export default function ProviderGuard({ didSelectProvider, children }: ProviderG }; const handleOpenRouterSetup = async () => { - trackOnboardingProviderSelected('openrouter'); + trackOnboardingProviderSelected({ method: 'openrouter' }); try { const result = await startOpenRouterSetup(); if (result.success) { @@ -339,7 +339,7 @@ export default function ProviderGuard({ didSelectProvider, children }: ProviderG
{ - trackOnboardingProviderSelected('local'); + trackOnboardingProviderSelected({ method: 'local' }); setShowLocalModelSetup(true); }} className="w-full p-4 sm:p-6 bg-transparent border rounded-xl transition-all duration-200 cursor-pointer group" diff --git a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx index 2d0df8284d49..01b1ea062be7 100644 --- a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx +++ b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx @@ -54,7 +54,7 @@ export default function OnboardingGuard({ children }: OnboardingGuardProps) { }, [isCheckingProvider, hasProvider]); const handleConfigured = async (providerName: string, modelId?: string) => { - trackOnboardingProviderSelected(providerName); + trackOnboardingProviderSelected({ provider: providerName }); await upsert('GOOSE_PROVIDER', providerName, false); if (modelId) { await upsert('GOOSE_MODEL', modelId, false); diff --git a/ui/desktop/src/utils/analytics.ts b/ui/desktop/src/utils/analytics.ts index ea4441e1936f..8c818f653eee 100644 --- a/ui/desktop/src/utils/analytics.ts +++ b/ui/desktop/src/utils/analytics.ts @@ -67,7 +67,7 @@ async function sendEvent( export type AnalyticsEvent = | { name: 'page_view'; properties: { page: string; referrer?: string } } | { name: 'onboarding_started'; properties: Record } - | { name: 'onboarding_provider_selected'; properties: { method: string } } + | { name: 'onboarding_provider_selected'; properties: { provider?: string; method?: string } } | { name: 'onboarding_completed'; properties: { provider: string; model?: string; duration_seconds?: number }; @@ -281,10 +281,13 @@ export function trackOnboardingStarted(): void { trackEvent({ name: 'onboarding_started', properties: {} }); } -export function trackOnboardingProviderSelected(method: string): void { +export function trackOnboardingProviderSelected(options: { + provider?: string; + method?: string; +}): void { trackEvent({ name: 'onboarding_provider_selected', - properties: { method }, + properties: options, }); } From 636d00719d64aa2764bafa31da9b0c8ab77f8e4a Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Mon, 16 Mar 2026 14:24:27 +1100 Subject: [PATCH 40/41] updated default model for nanogpt --- crates/goose/src/providers/nanogpt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/goose/src/providers/nanogpt.rs b/crates/goose/src/providers/nanogpt.rs index b969784c2562..a549bfdb6221 100644 --- a/crates/goose/src/providers/nanogpt.rs +++ b/crates/goose/src/providers/nanogpt.rs @@ -15,7 +15,7 @@ use rmcp::model::Tool; const NANOGPT_PROVIDER_NAME: &str = "nano-gpt"; pub const NANOGPT_API_HOST: &str = "https://nano-gpt.com/api/v1"; pub const NANOGPT_SUBSCRIPTION_HOST: &str = "https://nano-gpt.com/api/subscription/v1"; -pub const NANOGPT_DEFAULT_MODEL: &str = "mistralai/mistral-large-3-675b-instruct"; +pub const NANOGPT_DEFAULT_MODEL: &str = "anthropic/claude-sonnet-4.6"; pub const NANOGPT_DOC_URL: &str = "https://docs.nano-gpt.com/"; const NANOGPT_API_KEY: &str = "NANOGPT_API_KEY"; @@ -205,7 +205,7 @@ mod tests { fn test_metadata() { let metadata = NanoGptProvider::metadata(); assert_eq!(metadata.name, "nano-gpt"); - assert_eq!(metadata.default_model, "mistralai/mistral-large-3-675b-instruct"); + assert_eq!(metadata.default_model, "anthropic/claude-sonnet-4.6"); assert_eq!(metadata.config_keys[0].name, NANOGPT_API_KEY); assert!(metadata.config_keys[0].required); assert!(metadata.config_keys[0].secret); From 51ef2dd2334cf0b93f02a9609817498cd1fecace Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Tue, 17 Mar 2026 11:56:13 +1100 Subject: [PATCH 41/41] address review comments --- crates/goose/src/providers/anthropic.rs | 3 +-- crates/goose/src/providers/nanogpt.rs | 4 ++-- .../components/onboarding/OnboardingGuard.tsx | 22 +++++++++++-------- .../onboarding/ProviderSelector.tsx | 4 ++-- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/crates/goose/src/providers/anthropic.rs b/crates/goose/src/providers/anthropic.rs index 3ccd78e540be..21338a732b18 100644 --- a/crates/goose/src/providers/anthropic.rs +++ b/crates/goose/src/providers/anthropic.rs @@ -169,8 +169,7 @@ impl ProviderDef for AnthropicProvider { ], ) .with_setup_steps(vec![ - "Go to https://console.anthropic.com and sign up or log in", - "Click 'API Keys' in the left sidebar", + "Go to https://platform.claude.com/settings/keys", "Click 'Create Key'", "Copy the key and paste it above", ]) diff --git a/crates/goose/src/providers/nanogpt.rs b/crates/goose/src/providers/nanogpt.rs index a549bfdb6221..c5e12babdcf6 100644 --- a/crates/goose/src/providers/nanogpt.rs +++ b/crates/goose/src/providers/nanogpt.rs @@ -55,10 +55,10 @@ impl NanoGptProvider { let is_subscription = Self::check_subscription(&api_key).await; let host = if is_subscription { - tracing::info!("NanoGPT subscription active, using subscription endpoint"); + tracing::debug!("NanoGPT subscription active, using subscription endpoint"); NANOGPT_SUBSCRIPTION_HOST.to_string() } else { - tracing::info!("NanoGPT using pay-as-you-go endpoint"); + tracing::debug!("NanoGPT using pay-as-you-go endpoint"); NANOGPT_API_HOST.to_string() }; diff --git a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx index 01b1ea062be7..89a44b85cb90 100644 --- a/ui/desktop/src/components/onboarding/OnboardingGuard.tsx +++ b/ui/desktop/src/components/onboarding/OnboardingGuard.tsx @@ -28,6 +28,9 @@ export default function OnboardingGuard({ children }: OnboardingGuardProps) { const [hasProvider, setHasProvider] = useState(false); const [hasSelection, setHasSelection] = useState(false); const [configuredProvider, setConfiguredProvider] = useState(null); + const [configuredProviderDisplayName, setConfiguredProviderDisplayName] = useState( + null + ); const [configuredModel, setConfiguredModel] = useState(null); const hasTrackedOnboardingStart = useRef(false); @@ -56,19 +59,18 @@ export default function OnboardingGuard({ children }: OnboardingGuardProps) { const handleConfigured = async (providerName: string, modelId?: string) => { trackOnboardingProviderSelected({ provider: providerName }); await upsert('GOOSE_PROVIDER', providerName, false); + const providers = await getProviders(true); + const matchedProvider = providers.find((p) => p.name === providerName); if (modelId) { await upsert('GOOSE_MODEL', modelId, false); setConfiguredModel(modelId); - } else { - const providers = await getProviders(true); - const matchedProvider = providers.find((p) => p.name === providerName); - if (matchedProvider) { - await upsert('GOOSE_MODEL', matchedProvider.metadata.default_model, false); - setConfiguredModel(matchedProvider.metadata.default_model); - } + } else if (matchedProvider) { + await upsert('GOOSE_MODEL', matchedProvider.metadata.default_model, false); + setConfiguredModel(matchedProvider.metadata.default_model); } await refreshCurrentModelAndProvider(); setConfiguredProvider(providerName); + setConfiguredProviderDisplayName(matchedProvider?.metadata.display_name || providerName); }; const finishOnboarding = async (telemetryEnabled: boolean) => { @@ -96,8 +98,10 @@ export default function OnboardingGuard({ children }: OnboardingGuardProps) { return <>{children}; } - if (configuredProvider) { - return ; + if (configuredProviderDisplayName) { + return ( + + ); } return ( diff --git a/ui/desktop/src/components/onboarding/ProviderSelector.tsx b/ui/desktop/src/components/onboarding/ProviderSelector.tsx index 7a81ecb05bfc..06376d58bae2 100644 --- a/ui/desktop/src/components/onboarding/ProviderSelector.tsx +++ b/ui/desktop/src/components/onboarding/ProviderSelector.tsx @@ -119,7 +119,7 @@ export default function ProviderSelector({ Use Free/Local Providers

- Free credits or run locally on your machine + Use a local model or a provider with free credits

@@ -133,7 +133,7 @@ export default function ProviderSelector({ > - Use Your Own Provider + Connect to a Provider

Connect OpenAI, Anthropic, Google, etc