From 5b882f4e1372da91ab85549bc2b6d623370a5935 Mon Sep 17 00:00:00 2001 From: overcuriousity Date: Thu, 18 Jul 2024 21:54:02 +0200 Subject: [PATCH] added persistent storage for the settings --- src/db/schema.ts | 11 +++++++++ src/routes/index.ts | 2 ++ src/routes/settings.ts | 38 ++++++++++++++++++++++++++++++++ ui/components/ChatWindow.tsx | 24 ++++++++++++++++++++ ui/components/SettingsDialog.tsx | 24 +++++++++++--------- 5 files changed, 89 insertions(+), 10 deletions(-) create mode 100644 src/routes/settings.ts diff --git a/src/db/schema.ts b/src/db/schema.ts index 9eefa55..094852d 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -17,3 +17,14 @@ export const chats = sqliteTable('chats', { createdAt: text('createdAt').notNull(), focusMode: text('focusMode').notNull(), }); + +export const settings = sqliteTable('settings', { + id: integer('id').primaryKey(), + chatModelProvider: text('chatModelProvider'), + chatModel: text('chatModel'), + embeddingModelProvider: text('embeddingModelProvider'), + embeddingModel: text('embeddingModel'), + openAIApiKey: text('openAIApiKey'), + openAIBaseURL: text('openAIBaseURL'), + // TODO: add user auth +}); \ No newline at end of file diff --git a/src/routes/index.ts b/src/routes/index.ts index af928ab..a9a0264 100644 --- a/src/routes/index.ts +++ b/src/routes/index.ts @@ -5,6 +5,7 @@ import configRouter from './config'; import modelsRouter from './models'; import suggestionsRouter from './suggestions'; import chatsRouter from './chats'; +import settingsRouter from './settings'; const router = express.Router(); @@ -14,5 +15,6 @@ router.use('/config', configRouter); router.use('/models', modelsRouter); router.use('/suggestions', suggestionsRouter); router.use('/chats', chatsRouter); +router.use('/settings', settingsRouter); export default router; diff --git a/src/routes/settings.ts b/src/routes/settings.ts new file mode 100644 index 0000000..4fc5967 --- /dev/null +++ b/src/routes/settings.ts @@ -0,0 +1,38 @@ +import express from 'express'; +import db from '../db'; +import { settings } from '../db/schema'; + +const router = express.Router(); + +router.post('/', async (req, res) => { + try { + const { chatModelProvider, chatModel, embeddingModelProvider, embeddingModel, openAIApiKey, openAIBaseURL } = req.body; + + // TODO: Add user authentication + + await db.insert(settings).values({ + chatModelProvider, + chatModel, + embeddingModelProvider, + embeddingModel, + openAIApiKey, + openAIBaseURL, + }).execute(); + + res.status(200).json({ message: 'Settings saved successfully' }); + } catch (err) { + res.status(500).json({ message: 'An error occurred while saving settings' }); + } +}); + +router.get('/', async (req, res) => { + try { + // TODO: Add user authentication + const userSettings = await db.query.settings.findFirst(); + res.status(200).json(userSettings); + } catch (err) { + res.status(500).json({ message: 'An error occurred while fetching settings' }); + } +}); + +export default router; \ No newline at end of file diff --git a/ui/components/ChatWindow.tsx b/ui/components/ChatWindow.tsx index f2c89a3..a0415e0 100644 --- a/ui/components/ChatWindow.tsx +++ b/ui/components/ChatWindow.tsx @@ -21,6 +21,25 @@ export type Message = { sources?: Document[]; }; + +const fetchSettings = async () => { + try { + const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/settings`); + const settings = await res.json(); + + if (settings) { + localStorage.setItem('chatModelProvider', settings.chatModelProvider); + localStorage.setItem('chatModel', settings.chatModel); + localStorage.setItem('embeddingModelProvider', settings.embeddingModelProvider); + localStorage.setItem('embeddingModel', settings.embeddingModel); + localStorage.setItem('openAIApiKey', settings.openAIApiKey); + localStorage.setItem('openAIBaseURL', settings.openAIBaseURL); + } + } catch (err) { + console.error('Failed to fetch settings:', err); + } +}; + const useSocket = ( url: string, setIsWSReady: (ready: boolean) => void, @@ -31,6 +50,8 @@ const useSocket = ( useEffect(() => { if (!ws) { const connectWs = async () => { + await fetchSettings(); + let chatModel = localStorage.getItem('chatModel'); let chatModelProvider = localStorage.getItem('chatModelProvider'); let embeddingModel = localStorage.getItem('embeddingModel'); @@ -306,6 +327,9 @@ const ChatWindow = ({ id }: { id?: string }) => { const messagesRef = useRef([]); + useEffect(() => { + fetchSettings(); + }, []); useEffect(() => { messagesRef.current = messages; }, [messages]); diff --git a/ui/components/SettingsDialog.tsx b/ui/components/SettingsDialog.tsx index 788469b..825553f 100644 --- a/ui/components/SettingsDialog.tsx +++ b/ui/components/SettingsDialog.tsx @@ -146,31 +146,35 @@ const SettingsDialog = ({ const handleSubmit = async () => { setIsUpdating(true); - + try { - await fetch(`${process.env.NEXT_PUBLIC_API_URL}/config`, { + await fetch(`${process.env.NEXT_PUBLIC_API_URL}/settings`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify(config), + body: JSON.stringify({ + chatModelProvider: selectedChatModelProvider, + chatModel: selectedChatModel, + embeddingModelProvider: selectedEmbeddingModelProvider, + embeddingModel: selectedEmbeddingModel, + openAIApiKey: customOpenAIApiKey, + openAIBaseURL: customOpenAIBaseURL, + }), }); - + + // Still keep localStorage for quick access on the client-side localStorage.setItem('chatModelProvider', selectedChatModelProvider!); localStorage.setItem('chatModel', selectedChatModel!); - localStorage.setItem( - 'embeddingModelProvider', - selectedEmbeddingModelProvider!, - ); + localStorage.setItem('embeddingModelProvider', selectedEmbeddingModelProvider!); localStorage.setItem('embeddingModel', selectedEmbeddingModel!); localStorage.setItem('openAIApiKey', customOpenAIApiKey!); localStorage.setItem('openAIBaseURL', customOpenAIBaseURL!); } catch (err) { - console.log(err); + console.error(err); } finally { setIsUpdating(false); setIsOpen(false); - window.location.reload(); } };