diff --git a/ui/desktop/src/App.test.tsx b/ui/desktop/src/App.test.tsx index a4a9049f4ad5..2459ea715efd 100644 --- a/ui/desktop/src/App.test.tsx +++ b/ui/desktop/src/App.test.tsx @@ -37,12 +37,33 @@ vi.mock('./utils/costDatabase', () => ({ initializeCostDatabase: vi.fn().mockResolvedValue(undefined), })); -vi.mock('./api/sdk.gen', () => ({ - initConfig: vi.fn().mockResolvedValue(undefined), - readAllConfig: vi.fn().mockResolvedValue(undefined), - backupConfig: vi.fn().mockResolvedValue(undefined), - recoverConfig: vi.fn().mockResolvedValue(undefined), - validateConfig: vi.fn().mockResolvedValue(undefined), +vi.mock('./api/sdk.gen', () => { + const test_chat = { + data: { + session_id: 'test', + messages: [], + metadata: { + description: '', + }, + }, + }; + + return { + initConfig: vi.fn().mockResolvedValue(undefined), + readAllConfig: vi.fn().mockResolvedValue(undefined), + backupConfig: vi.fn().mockResolvedValue(undefined), + recoverConfig: vi.fn().mockResolvedValue(undefined), + validateConfig: vi.fn().mockResolvedValue(undefined), + startAgent: vi.fn().mockResolvedValue(test_chat), + resumeAgent: vi.fn().mockResolvedValue(test_chat), + }; +}); + +vi.mock('./sessions', () => ({ + fetchSessionDetails: vi + .fn() + .mockResolvedValue({ sessionId: 'test', messages: [], metadata: { description: '' } }), + generateSessionId: vi.fn(), })); vi.mock('./utils/openRouterSetup', () => ({ diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index 20ebe9eebe99..b73fe725e298 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -33,7 +33,12 @@ import { Recipe } from './recipe'; import RecipesView from './components/RecipesView'; import RecipeEditor from './components/RecipeEditor'; import { createNavigationHandler, View, ViewOptions } from './utils/navigationUtils'; -import { AgentState, InitializationContext, useAgent } from './hooks/useAgent'; +import { + AgentState, + InitializationContext, + NoProviderOrModelError, + useAgent, +} from './hooks/useAgent'; // Route Components const HubRouteWrapper = ({ @@ -373,7 +378,15 @@ export default function App() { recipeConfig: recipeConfig, }; (async () => { - await loadCurrentChat({ setAgentWaitingMessage, ...stateData }); + try { + await loadCurrentChat({ setAgentWaitingMessage, ...stateData }); + } catch (e) { + if (e instanceof NoProviderOrModelError) { + // the onboarding flow will trigger + } else { + throw e; + } + } })(); if (resumeSessionId || (recipeConfig && typeof recipeConfig === 'object')) { diff --git a/ui/desktop/src/components/OllamaSetup.test.tsx b/ui/desktop/src/components/OllamaSetup.test.tsx index 945a8beb0831..5c4674a748ce 100644 --- a/ui/desktop/src/components/OllamaSetup.test.tsx +++ b/ui/desktop/src/components/OllamaSetup.test.tsx @@ -143,7 +143,8 @@ describe('OllamaSetup', () => { }); }); - describe('when Ollama and model are both available', () => { + // TODO: re-enable when we have ollama back in the onboarding + describe.skip('when Ollama and model are both available', () => { beforeEach(() => { vi.mocked(ollamaDetection.checkOllamaStatus).mockResolvedValue({ isRunning: true, diff --git a/ui/desktop/src/hooks/useAgent.ts b/ui/desktop/src/hooks/useAgent.ts index f0db5f198c55..0b43a36ba802 100644 --- a/ui/desktop/src/hooks/useAgent.ts +++ b/ui/desktop/src/hooks/useAgent.ts @@ -38,6 +38,13 @@ interface UseAgentReturn { loadCurrentChat: (context: InitializationContext) => Promise; } +export class NoProviderOrModelError extends Error { + constructor() { + super('No provider or model configured'); + this.name = this.constructor.name; + } +} + export function useAgent(): UseAgentReturn { const [agentState, setAgentState] = useState(AgentState.UNINITIALIZED); const [sessionId, setSessionId] = useState(null); @@ -88,7 +95,7 @@ export function useAgent(): UseAgentReturn { if (!provider || !model) { setAgentState(AgentState.NO_PROVIDER); - throw new Error('No provider or model configured'); + throw new NoProviderOrModelError(); } const agentResponse = initContext.resumeSessionId