diff --git a/electron/main/electron-store/storeConfig.ts b/electron/main/electron-store/storeConfig.ts index af2ab3ef..9c0780a0 100644 --- a/electron/main/electron-store/storeConfig.ts +++ b/electron/main/electron-store/storeConfig.ts @@ -9,7 +9,7 @@ export interface LLMAPIConfig { apiKey?: string } -export interface LLM { +export interface LLMConfig { modelName: string apiName: string contextLength?: number @@ -48,7 +48,7 @@ export interface StoreSchema { vaultDirectories: string[] directoryFromPreviousSession?: string } - LLMs: LLM[] + LLMs: LLMConfig[] LLMAPIs: LLMAPIConfig[] embeddingModels: { [modelAlias: string]: EmbeddingModelConfig diff --git a/electron/main/electron-store/storeSchemaMigrator.ts b/electron/main/electron-store/storeSchemaMigrator.ts index 7f256201..ab7e52ba 100644 --- a/electron/main/electron-store/storeSchemaMigrator.ts +++ b/electron/main/electron-store/storeSchemaMigrator.ts @@ -62,6 +62,28 @@ export function setupDefaultStoreValues(store: Store) { setupDefaultLLMAPIs(store) } +function ensureChatHistoryIsCorrectProperty(store: Store) { + const chatHistories = store.get(StoreKeys.ChatHistories) + if (!chatHistories) { + return + } + + Object.keys(chatHistories).forEach((vaultDir) => { + const chats = chatHistories[vaultDir] + chats.map((chat) => { + const outputChat = chat + if (chat.displayableChatHistory) { + outputChat.messages = chat.displayableChatHistory + delete outputChat.displayableChatHistory + } + return outputChat + }) + chatHistories[vaultDir] = chats + }) + + store.set(StoreKeys.ChatHistories, chatHistories) +} + export const initializeAndMaybeMigrateStore = (store: Store) => { const storeSchemaVersion = store.get(StoreKeys.SchemaVersion) if (storeSchemaVersion !== currentSchemaVersion) { @@ -69,5 +91,8 @@ export const initializeAndMaybeMigrateStore = (store: Store) => { store.set(StoreKeys.LLMAPIs, []) store.set(StoreKeys.DefaultLLM, '') } + + ensureChatHistoryIsCorrectProperty(store) + setupDefaultStoreValues(store) } diff --git a/electron/main/llm/ipcHandlers.ts b/electron/main/llm/ipcHandlers.ts index 35d8950f..df1fca72 100644 --- a/electron/main/llm/ipcHandlers.ts +++ b/electron/main/llm/ipcHandlers.ts @@ -2,7 +2,7 @@ import { ipcMain } from 'electron' import Store from 'electron-store' import { ProgressResponse } from 'ollama' -import { LLM, LLMAPIConfig, StoreKeys, StoreSchema } from '../electron-store/storeConfig' +import { LLMConfig, LLMAPIConfig, StoreKeys, StoreSchema } from '../electron-store/storeConfig' import { addOrUpdateLLMAPIInStore, removeLLM, getLLMConfigs, addOrUpdateLLMInStore } from './llmConfig' import AnthropicModelSessionService from './models/Anthropic' @@ -25,7 +25,7 @@ export const registerLLMSessionHandlers = (store: Store) => { ipcMain.handle('get-llm-api-configs', async () => store.get(StoreKeys.LLMAPIs)) - ipcMain.handle('add-or-update-llm-config', async (event, llmConfig: LLM) => { + ipcMain.handle('add-or-update-llm-config', async (event, llmConfig: LLMConfig) => { await addOrUpdateLLMInStore(store, llmConfig) }) diff --git a/electron/main/llm/llmConfig.ts b/electron/main/llm/llmConfig.ts index ccb12aa4..b8c9cb09 100644 --- a/electron/main/llm/llmConfig.ts +++ b/electron/main/llm/llmConfig.ts @@ -1,6 +1,6 @@ import Store from 'electron-store' -import { LLM, LLMAPIConfig, StoreKeys, StoreSchema } from '../electron-store/storeConfig' +import { LLMConfig, LLMAPIConfig, StoreKeys, StoreSchema } from '../electron-store/storeConfig' import OllamaService from './models/Ollama' @@ -18,7 +18,7 @@ export async function addOrUpdateLLMAPIInStore(store: Store, newAPI } } -export async function addOrUpdateLLMInStore(store: Store, newLLM: LLM): Promise { +export async function addOrUpdateLLMInStore(store: Store, newLLM: LLMConfig): Promise { const existingLLMs = store.get(StoreKeys.LLMs) || [] const foundLLM = existingLLMs.find((llm) => llm.modelName === newLLM.modelName) @@ -32,7 +32,7 @@ export async function addOrUpdateLLMInStore(store: Store, newLLM: L } } -export async function getLLMConfigs(store: Store, ollamaSession: OllamaService): Promise { +export async function getLLMConfigs(store: Store, ollamaSession: OllamaService): Promise { const llmConfigsFromStore = store.get(StoreKeys.LLMs) const ollamaLLMConfigs = await ollamaSession.getAvailableModels() @@ -43,11 +43,11 @@ export async function getLLMConfig( store: Store, ollamaSession: OllamaService, modelName: string, -): Promise { +): Promise { const llmConfigs = await getLLMConfigs(store, ollamaSession) if (llmConfigs) { - return llmConfigs.find((model: LLM) => model.modelName === modelName) + return llmConfigs.find((model: LLMConfig) => model.modelName === modelName) } return undefined } diff --git a/electron/main/llm/models/Ollama.ts b/electron/main/llm/models/Ollama.ts index 18965aa1..ac6146c1 100644 --- a/electron/main/llm/models/Ollama.ts +++ b/electron/main/llm/models/Ollama.ts @@ -7,7 +7,7 @@ import * as os from 'os' import * as path from 'path' import { app } from 'electron' -import { LLM, LLMAPIConfig } from 'electron/main/electron-store/storeConfig' +import { LLMConfig, LLMAPIConfig } from 'electron/main/electron-store/storeConfig' import { Tiktoken, TiktokenModel, encodingForModel } from 'js-tiktoken' import { ModelResponse, ProgressResponse, Ollama } from 'ollama' @@ -173,11 +173,11 @@ class OllamaService { this.childProcess = null } - public getAvailableModels = async (): Promise => { + public getAvailableModels = async (): Promise => { const ollamaModelsResponse = await this.client.list() const output = ollamaModelsResponse.models.map( - (model: ModelResponse): LLM => ({ + (model: ModelResponse): LLMConfig => ({ modelName: model.name, contextLength: 4096, apiName: defaultOllamaAPI.name, diff --git a/electron/preload/index.ts b/electron/preload/index.ts index cf9b06ec..8d44aa76 100644 --- a/electron/preload/index.ts +++ b/electron/preload/index.ts @@ -3,7 +3,7 @@ import { EmbeddingModelConfig, EmbeddingModelWithLocalPath, EmbeddingModelWithRepo, - LLM, + LLMConfig, LLMAPIConfig, LLMGenerationParameters, Tab, @@ -133,9 +133,9 @@ const llm = { (llmName: string, llmConfig: LLMAPIConfig, isJSONMode: boolean, chatHistory: Chat) => Promise >('streaming-llm-response'), - getLLMConfigs: createIPCHandler<() => Promise>('get-llm-configs'), + getLLMConfigs: createIPCHandler<() => Promise>('get-llm-configs'), getLLMAPIConfigs: createIPCHandler<() => Promise>('get-llm-api-configs'), - addOrUpdateLLMConfig: createIPCHandler<(model: LLM) => Promise>('add-or-update-llm-config'), + addOrUpdateLLMConfig: createIPCHandler<(model: LLMConfig) => Promise>('add-or-update-llm-config'), addOrUpdateLLMAPIConfig: createIPCHandler<(modelConfig: LLMAPIConfig) => Promise>('add-or-update-llm-api-config'), removeLLM: createIPCHandler<(modelNameToDelete: string) => Promise>('remove-llm'), diff --git a/src/components/Chat/ChatInterface.tsx b/src/components/Chat/ChatInterface.tsx index 4d129d22..06a686bd 100644 --- a/src/components/Chat/ChatInterface.tsx +++ b/src/components/Chat/ChatInterface.tsx @@ -83,7 +83,7 @@ const ChatInterface: React.FC = ({ >
- {currentChatHistory && currentChatHistory.messages.length > 0 ? ( + {currentChatHistory && currentChatHistory.messages && currentChatHistory.messages.length > 0 ? ( // Display chat history if it exists currentChatHistory.messages .filter((msg) => msg.role !== 'system') diff --git a/src/components/Chat/ChatWrapper.tsx b/src/components/Chat/ChatWrapper.tsx index ea46f185..0928fcbd 100644 --- a/src/components/Chat/ChatWrapper.tsx +++ b/src/components/Chat/ChatWrapper.tsx @@ -107,10 +107,6 @@ const ChatWrapper: React.FC = ({ return { id: prev!.id, messages: newDisplayableHistory, - openAIChatHistory: newDisplayableHistory.map((message) => ({ - role: message.role, - content: message.content, - })), } }) }, diff --git a/src/components/Chat/chatUtils.ts b/src/components/Chat/chatUtils.ts index 3281839a..88cf3cae 100644 --- a/src/components/Chat/chatUtils.ts +++ b/src/components/Chat/chatUtils.ts @@ -11,6 +11,7 @@ export type ReorChatMessage = CoreMessage & { } export type Chat = { + [x: string]: any id: string messages: ReorChatMessage[] } @@ -120,13 +121,13 @@ export const resolveRAGContext = async (query: string, chatFilters: ChatFilters) } export const getChatHistoryContext = (chatHistory: Chat | undefined): DBQueryResult[] => { - if (!chatHistory) return [] + if (!chatHistory || !chatHistory.messages) return [] const contextForChat = chatHistory.messages.map((message) => message.context).flat() return contextForChat as DBQueryResult[] } export const getDisplayableChatName = (chat: Chat): string => { - if (chat.messages.length === 0 || !chat.messages[chat.messages.length - 1].content) { + if (!chat.messages || chat.messages.length === 0 || !chat.messages[chat.messages.length - 1].content) { return 'Empty Chat' } diff --git a/src/components/Settings/LLMSettings/DefaultLLMSelector.tsx b/src/components/Settings/LLMSettings/DefaultLLMSelector.tsx index 1a21c8bc..098eb890 100644 --- a/src/components/Settings/LLMSettings/DefaultLLMSelector.tsx +++ b/src/components/Settings/LLMSettings/DefaultLLMSelector.tsx @@ -1,13 +1,13 @@ import React from 'react' -import { LLM } from 'electron/main/electron-store/storeConfig' +import { LLMConfig } from 'electron/main/electron-store/storeConfig' import posthog from 'posthog-js' import CustomSelect from '../../Common/Select' interface DefaultLLMSelectorProps { onModelChange: (model: string) => void - llmConfigs: LLM[] + llmConfigs: LLMConfig[] defaultLLM: string setDefaultLLM: (model: string) => void } diff --git a/src/components/Settings/LLMSettings/hooks/useLLMConfigs.tsx b/src/components/Settings/LLMSettings/hooks/useLLMConfigs.tsx index 1af291fb..cd79591d 100644 --- a/src/components/Settings/LLMSettings/hooks/useLLMConfigs.tsx +++ b/src/components/Settings/LLMSettings/hooks/useLLMConfigs.tsx @@ -1,9 +1,9 @@ import { useState, useEffect } from 'react' -import { LLM } from 'electron/main/electron-store/storeConfig' +import { LLMConfig } from 'electron/main/electron-store/storeConfig' const useLLMConfigs = () => { - const [llmConfigs, setLLMConfigs] = useState([]) + const [llmConfigs, setLLMConfigs] = useState([]) const [defaultLLM, setDefaultLLM] = useState('') const fetchAndUpdateModelConfigs = async () => { diff --git a/src/components/Settings/LLMSettings/modals/DefaultLLMAPISetupModal.tsx b/src/components/Settings/LLMSettings/modals/DefaultLLMAPISetupModal.tsx index 45c7416f..60eb3790 100644 --- a/src/components/Settings/LLMSettings/modals/DefaultLLMAPISetupModal.tsx +++ b/src/components/Settings/LLMSettings/modals/DefaultLLMAPISetupModal.tsx @@ -2,13 +2,13 @@ import React, { useState } from 'react' import { Button } from '@material-tailwind/react' -import { APIInterface, LLM, LLMAPIConfig } from 'electron/main/electron-store/storeConfig' +import { APIInterface, LLMConfig, LLMAPIConfig } from 'electron/main/electron-store/storeConfig' import ReorModal from '../../../Common/Modal' export const openAIDefaultAPIName = 'OpenAI' export const anthropicDefaultAPIName = 'Anthropic' -export const openAIDefaultModels: LLM[] = [ +export const openAIDefaultModels: LLMConfig[] = [ { contextLength: 128000, modelName: 'gpt-4o', @@ -31,7 +31,7 @@ export const openAIDefaultModels: LLM[] = [ }, ] -export const anthropicDefaultModels: LLM[] = [ +export const anthropicDefaultModels: LLMConfig[] = [ { contextLength: 180000, modelName: 'claude-3-5-sonnet-20240620', diff --git a/src/components/Writing-Assistant/WritingAssistantFloatingMenu.tsx b/src/components/Writing-Assistant/WritingAssistantFloatingMenu.tsx index e9a081dd..42fcba47 100644 --- a/src/components/Writing-Assistant/WritingAssistantFloatingMenu.tsx +++ b/src/components/Writing-Assistant/WritingAssistantFloatingMenu.tsx @@ -265,10 +265,6 @@ const WritingAssistant: React.FC = ({ return { id: prev!.id, messages: newDisplayableHistory, - openAIChatHistory: newDisplayableHistory.map((message) => ({ - role: message.role, - content: message.content, - })), } }) }