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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 27 additions & 6 deletions ui/desktop/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => ({
Expand Down
17 changes: 15 additions & 2 deletions ui/desktop/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ({
Expand Down Expand Up @@ -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')) {
Expand Down
3 changes: 2 additions & 1 deletion ui/desktop/src/components/OllamaSetup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 8 additions & 1 deletion ui/desktop/src/hooks/useAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ interface UseAgentReturn {
loadCurrentChat: (context: InitializationContext) => Promise<ChatType>;
}

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>(AgentState.UNINITIALIZED);
const [sessionId, setSessionId] = useState<string | null>(null);
Expand Down Expand Up @@ -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
Expand Down