|
1 | | -import { Divider, HStack, Stack } from '@chakra-ui/layout'; |
| 1 | +import React, { FC, useEffect, useState } from 'react'; |
| 2 | +import { Stack, Divider, Box, Avatar, Link, Text } from '@chakra-ui/react'; |
2 | 3 | import { ExternalLinkIcon } from '@chakra-ui/icons'; |
3 | | -import { Avatar, Link, Button, Icon, Text } from '@chakra-ui/react'; |
4 | | -import { useModal } from 'hooks/useModal/useModal'; |
5 | | -import { useEffect, useState } from 'react'; |
6 | | -import { FaTrash } from 'react-icons/fa'; |
7 | | -import { HiRefresh } from 'react-icons/hi'; |
8 | | -import { IoFileTray } from 'react-icons/io5'; |
9 | | -import { TbRefreshAlert } from 'react-icons/tb'; |
10 | | -import { MdPlayArrow, MdStop, MdViewList } from 'react-icons/md'; |
11 | | -import { FC } from 'react'; |
12 | | -import axios from 'axios'; |
13 | | - |
| 4 | +import bex from 'assets/ollama.png'; |
14 | 5 | import { SettingsListItem } from './SettingsListItem'; |
| 6 | +import OllamaStatus from './ollama/OllamaStatus'; |
| 7 | +import ModelSelector from './ollama/ModelSelector'; |
| 8 | +import ModelInstaller from './ollama/ModelInstaller'; |
| 9 | +import Logs from './ollama/Logs'; |
| 10 | +// @ts-ignore |
| 11 | +import { Ollama } from 'keepkey-ollama/browser'; |
15 | 12 |
|
16 | | -interface OllamaSettingsProps { |
17 | | - shouldAutoUpdate: boolean; |
18 | | - shouldMinimizeToTray: boolean; |
19 | | - allowPreRelease: boolean; |
20 | | - autoScanQr: boolean; |
| 13 | +interface KnownModel { |
| 14 | + name: string; |
| 15 | + sizes: string[]; |
21 | 16 | } |
22 | 17 |
|
23 | 18 | export const OllamaSettings: FC = () => { |
24 | | - const { settings, onboardingSteps } = useModal(); |
25 | | - const [appSettings, setAppSettings] = useState<OllamaSettingsProps>({ |
26 | | - shouldAutoUpdate: true, |
27 | | - shouldMinimizeToTray: true, |
28 | | - allowPreRelease: false, |
29 | | - autoScanQr: false, |
30 | | - }); |
31 | | - |
32 | | - const [prevAppSettings, setPrevAppSettings] = useState<OllamaSettingsProps>(appSettings); |
33 | | - const [isOllamaRunning, setIsOllamaRunning] = useState(false); |
34 | | - |
35 | | - const handleTestConnection = async () => { |
| 19 | + const [installedModels, setInstalledModels] = useState<string[]>([]); |
| 20 | + const [selectedModel, setSelectedModel] = useState(''); |
| 21 | + const [needToInstall, setNeedToInstall] = useState(false); |
| 22 | + const [logs, setLogs] = useState<string[]>([]); |
| 23 | + const [showLogs, setShowLogs] = useState(false); |
| 24 | + |
| 25 | + const knownModels: KnownModel[] = [ |
| 26 | + { name: 'llama-3.2', sizes: ['small', 'medium', 'large'] }, |
| 27 | + { name: 'gemma-2', sizes: ['small', 'medium'] }, |
| 28 | + { name: 'dolphin-mixtral', sizes: ['medium', 'large'] }, |
| 29 | + ]; |
| 30 | + |
| 31 | + const listInstalledModels = async () => { |
36 | 32 | try { |
37 | | - const response = await axios.get('http://127.0.0.1:11434/'); |
38 | | - console.log('Ollama is healthy:', response.data); |
39 | | - setIsOllamaRunning(true); |
| 33 | + const response = await Ollama.list(); |
| 34 | + setInstalledModels(response.models); |
40 | 35 | } catch (error) { |
41 | | - console.error('Ollama is not responding:', error); |
42 | | - setIsOllamaRunning(false); |
| 36 | + console.error('Error listing models:', error); |
| 37 | + setLogs((prevLogs) => [...prevLogs, `Error listing models: ${error}`]); |
43 | 38 | } |
44 | 39 | }; |
45 | 40 |
|
46 | | - useEffect(() => { |
47 | | - handleTestConnection(); |
48 | | - }, []); |
| 41 | + const handleModelSelect = (modelName: string) => { |
| 42 | + setSelectedModel(modelName); |
| 43 | + setNeedToInstall(!installedModels.includes(modelName)); |
| 44 | + }; |
| 45 | + |
| 46 | + const handleInstallComplete = () => { |
| 47 | + // After installation, refresh the installed models list |
| 48 | + listInstalledModels(); |
| 49 | + setNeedToInstall(false); |
| 50 | + }; |
49 | 51 |
|
50 | 52 | useEffect(() => { |
51 | | - if ( |
52 | | - prevAppSettings && |
53 | | - appSettings.shouldAutoUpdate === prevAppSettings.shouldAutoUpdate && |
54 | | - appSettings.shouldMinimizeToTray === prevAppSettings.shouldMinimizeToTray && |
55 | | - appSettings.allowPreRelease === prevAppSettings.allowPreRelease && |
56 | | - appSettings.autoScanQr === prevAppSettings.autoScanQr |
57 | | - ) return; |
58 | | - |
59 | | - setPrevAppSettings(appSettings); |
60 | | - console.log('APP SETTINGS SAVED', appSettings); |
61 | | - }, [appSettings, prevAppSettings]); |
| 53 | + listInstalledModels(); |
| 54 | + }, []); |
62 | 55 |
|
63 | 56 | return ( |
64 | | - <Stack width='full' p={0}> |
| 57 | + <Stack width="full" p={0}> |
65 | 58 | <Divider my={1} /> |
66 | | - <Link href='http://127.0.0.1:11434/' isExternal> |
| 59 | + <Box maxW={{ base: '100%', md: '45%' }} mb={{ base: 4, md: 0 }} mx="auto"> |
| 60 | + <Avatar src={bex} size="lg" /> |
| 61 | + </Box> |
| 62 | + |
| 63 | + <Link href="http://127.0.0.1:11434/" isExternal> |
67 | 64 | <SettingsListItem |
68 | | - icon={<Icon as={ExternalLinkIcon} color='gray.500' />} |
69 | | - label='connectWallet.menu.openDev' |
| 65 | + icon={<ExternalLinkIcon color="gray.500" />} |
| 66 | + label="Open Ollama" |
70 | 67 | /> |
71 | 68 | </Link> |
| 69 | + |
72 | 70 | <Divider my={1} /> |
73 | | - <HStack> |
74 | | - <SettingsListItem |
75 | | - label={'Test Connection'} |
76 | | - onClick={handleTestConnection} |
77 | | - icon={<Icon as={HiRefresh} color='gray.500' />} |
78 | | - > |
79 | | - <Button variant={'ghost'} onClick={handleTestConnection}> |
80 | | - Test |
81 | | - </Button> |
82 | | - </SettingsListItem> |
83 | | - <Text color={isOllamaRunning ? 'green.500' : 'red.500'}> |
84 | | - {isOllamaRunning ? 'Online' : 'Offline'} |
85 | | - </Text> |
86 | | - </HStack> |
| 71 | + |
| 72 | + {/* Model Selector */} |
| 73 | + <ModelSelector |
| 74 | + installedModels={installedModels} |
| 75 | + knownModels={knownModels} |
| 76 | + onModelSelect={handleModelSelect} |
| 77 | + /> |
| 78 | + |
| 79 | + <Divider my={1} /> |
| 80 | + |
| 81 | + {/* Install Model if needed */} |
| 82 | + {needToInstall && selectedModel && ( |
| 83 | + <> |
| 84 | + <ModelInstaller |
| 85 | + modelName={selectedModel} |
| 86 | + onInstallComplete={handleInstallComplete} |
| 87 | + setLogs={setLogs} |
| 88 | + /> |
| 89 | + <Divider my={1} /> |
| 90 | + </> |
| 91 | + )} |
| 92 | + |
| 93 | + {/* Link to find more models */} |
| 94 | + <Link href="https://ollama.com/library" isExternal> |
| 95 | + Find more models |
| 96 | + </Link> |
| 97 | + |
| 98 | + <Divider my={1} /> |
| 99 | + |
| 100 | + {/* Ollama Status */} |
| 101 | + <OllamaStatus /> |
| 102 | + |
| 103 | + <Divider my={1} /> |
| 104 | + |
| 105 | + {/* Logs Section */} |
| 106 | + <Logs logs={logs} showLogs={showLogs} setShowLogs={setShowLogs} /> |
87 | 107 | </Stack> |
88 | 108 | ); |
89 | 109 | }; |
0 commit comments