diff --git a/src/utils/migrations/chats/chat_1_add_message_author.ts b/src/migrations/chats/chat_1_add_message_author.ts similarity index 100% rename from src/utils/migrations/chats/chat_1_add_message_author.ts rename to src/migrations/chats/chat_1_add_message_author.ts diff --git a/src/utils/migrations/chats/chat_2_add_persona_role_and_ipfs_avatar.ts b/src/migrations/chats/chat_2_add_persona_role_and_ipfs_avatar.ts similarity index 100% rename from src/utils/migrations/chats/chat_2_add_persona_role_and_ipfs_avatar.ts rename to src/migrations/chats/chat_2_add_persona_role_and_ipfs_avatar.ts diff --git a/src/utils/migrations/chats/chat_3_add_model_id.ts b/src/migrations/chats/chat_3_add_model_id.ts similarity index 100% rename from src/utils/migrations/chats/chat_3_add_model_id.ts rename to src/migrations/chats/chat_3_add_model_id.ts diff --git a/src/migrations/chats/chat_4_add_knowledge_bases.ts b/src/migrations/chats/chat_4_add_knowledge_bases.ts new file mode 100644 index 0000000..7e54548 --- /dev/null +++ b/src/migrations/chats/chat_4_add_knowledge_bases.ts @@ -0,0 +1,5 @@ +import { Chat, ChatMigration } from 'src/types/chats'; + +export const chat_4_add_knowledge_bases: ChatMigration = (currentChat: Chat) => { + return { ...currentChat, knowledgeBases: [] }; +}; diff --git a/src/migrations/chats/index.ts b/src/migrations/chats/index.ts new file mode 100644 index 0000000..c4b6e4b --- /dev/null +++ b/src/migrations/chats/index.ts @@ -0,0 +1,12 @@ +import { ChatMigration } from 'src/types/chats'; +import { chat_1_add_message_author } from 'src/migrations/chats/chat_1_add_message_author'; +import { chat_2_add_persona_role_and_ipfs_avatar } from 'src/migrations/chats/chat_2_add_persona_role_and_ipfs_avatar'; +import { chat_3_add_model_id } from 'src/migrations/chats/chat_3_add_model_id'; +import { chat_4_add_knowledge_bases } from 'src/migrations/chats/chat_4_add_knowledge_bases'; + +export const chatsMigrations: ChatMigration[] = [ + chat_1_add_message_author, + chat_2_add_persona_role_and_ipfs_avatar, + chat_3_add_model_id, + chat_4_add_knowledge_bases, +]; diff --git a/src/migrations/personas/index.ts b/src/migrations/personas/index.ts new file mode 100644 index 0000000..ce18b3a --- /dev/null +++ b/src/migrations/personas/index.ts @@ -0,0 +1,4 @@ +import { PersonaMigration } from 'src/types/personas'; +import { persona_1_add_knowledge_bases } from 'src/migrations/personas/persona_1_add_knowledge_bases'; + +export const personasMigrations: PersonaMigration[] = [persona_1_add_knowledge_bases]; diff --git a/src/migrations/personas/persona_1_add_knowledge_bases.ts b/src/migrations/personas/persona_1_add_knowledge_bases.ts new file mode 100644 index 0000000..89d924f --- /dev/null +++ b/src/migrations/personas/persona_1_add_knowledge_bases.ts @@ -0,0 +1,5 @@ +import { PersonaMigration, UIPersona } from 'src/types/personas'; + +export const persona_1_add_knowledge_bases: PersonaMigration = (currentPersona: UIPersona) => { + return { ...currentPersona, knowledgeBases: [] }; +}; diff --git a/src/pages/PersonaManagement.vue b/src/pages/PersonaManagement.vue index 111c089..37c53eb 100644 --- a/src/pages/PersonaManagement.vue +++ b/src/pages/PersonaManagement.vue @@ -13,7 +13,13 @@ title="Create persona" @save-persona=" (persona: BasePersonaEdition) => { - personasStore.personas.push({ ...persona, allowEdit: true, hidden: false, id: uuidv4() }); + personasStore.personas.push({ + ...persona, + allowEdit: true, + hidden: false, + id: uuidv4(), + knowledgeBases: [], + }); } " /> diff --git a/src/stores/chats.ts b/src/stores/chats.ts index 222a9b2..b086bdf 100644 --- a/src/stores/chats.ts +++ b/src/stores/chats.ts @@ -1,7 +1,7 @@ import { v4 as uuidv4 } from 'uuid'; import { defineStore } from 'pinia'; import { chatTag } from 'src/utils/chat'; -import { chatsMigrations } from 'src/utils/migrations/chats'; +import { chatsMigrations } from 'src/migrations/chats'; import { Chat, MessageAttachment, UIMessage } from 'src/types/chats'; import { UIPersona } from 'src/types/personas'; import localforage from 'localforage'; @@ -9,16 +9,6 @@ import localforage from 'localforage'; const CHATS_STORE_NAME = 'chats-store'; const CHATS_STORE_PINIA_KEY = 'chats-store-pinia-key'; -/** - * To implement in attachments: - * interface Attachment { - * // Document id within the embedding store, if stored there - * documentId: string?; - * // The content of the attachment, if stored inlined - * content: string?; - * } - */ - // TODO: Search results are not yet implemented /** * Representation of a search result: @@ -100,6 +90,7 @@ export const useChatsStore = defineStore(CHATS_STORE_PINIA_KEY, { persona, messages: [], createdAt: new Date().toISOString(), + knowledgeBases: [], }; this.chats.push(chat); return chat; diff --git a/src/stores/personas.ts b/src/stores/personas.ts index dcdba9f..71e267a 100644 --- a/src/stores/personas.ts +++ b/src/stores/personas.ts @@ -2,21 +2,35 @@ import { defineStore } from 'pinia'; import { defaultPersonas } from '../utils/personas'; import { UIPersona } from 'src/types/personas'; +import { personasMigrations } from 'src/migrations/personas'; + +type PersonasStoreState = { + version: number; + personas: UIPersona[]; +}; export const usePersonasStore = defineStore('personas', { - state: () => ({ - personas: JSON.parse(JSON.stringify(defaultPersonas)) as UIPersona[], + state: (): PersonasStoreState => ({ + // Current version of the migrations + version: 0, // /!\ DO NOT UPDATE /!\, it should be done automatically when running migrations + + personas: JSON.parse(JSON.stringify(defaultPersonas)), }), + persist: { + paths: ['version', 'personas'], + afterRestore: (ctx) => { + ctx.store.migratePersonas(); + }, + }, getters: { // @ts-expect-error sortedPersonas: (state) => state.personas.slice().sort((a, b) => a.hidden - b.hidden), shownPersonas: (state) => state.personas.filter((persona) => !persona.hidden), }, actions: { - refreshDefaultPersonas: () => { - const store = usePersonasStore(); - - store.personas = store.personas.map((currentPersona) => { + migratePersonas() { + // Update stored default personas if some values where changed + this.personas = this.personas.map((currentPersona) => { const matchingDefault = defaultPersonas.find((p) => currentPersona.id === p.id); if (!matchingDefault) { return currentPersona; @@ -29,12 +43,19 @@ export const usePersonasStore = defineStore('personas', { description: matchingDefault.description, }; }); - }, - }, - persist: { - paths: ['personas'], // keys to persist - afterRestore: (ctx) => { - ctx.store.refreshDefaultPersonas(); + try { + // Running migrations if needed + if (this.version < personasMigrations.length) { + // Removing migrations already ran + const migrationsToRun = personasMigrations.slice(this.version); + for (const migration of migrationsToRun) { + this.personas = this.personas.map((persona) => migration(persona)); + } + } + this.version = personasMigrations.length; + } catch (error) { + console.error(`Personas: Running migrations starting from version ${this.version} failed: ${error}`); + } }, }, }); diff --git a/src/types/chats.ts b/src/types/chats.ts index 48166fe..bfea019 100644 --- a/src/types/chats.ts +++ b/src/types/chats.ts @@ -30,6 +30,7 @@ export type Chat = { persona: UIPersona; messages: UIMessage[]; createdAt: string; // ISO 8601 date + knowledgeBases: string[]; // IDs of linked knowledge bases }; // eslint-disable-next-line no-unused-vars diff --git a/src/types/personas.ts b/src/types/personas.ts index 8b80dcc..b55ac42 100644 --- a/src/types/personas.ts +++ b/src/types/personas.ts @@ -9,6 +9,7 @@ export type UIPersona = Persona & { name: string; allowEdit: boolean; hidden: boolean; + knowledgeBases: string[]; // IDs of linked knowledge bases }; export type BasePersonaEdition = Pick; @@ -22,3 +23,6 @@ export const defaultBasePersona: BasePersonaEdition = { ipfs_hash: 'QmQMBfgnmuxcQ4kptR1oPE9guYxG13GpASjYVeFQSxNxjE', }, }; + +// eslint-disable-next-line no-unused-vars +export type PersonaMigration = (currentPersona: UIPersona) => UIPersona; diff --git a/src/utils/aleph-persistent-storage.ts b/src/utils/aleph-persistent-storage.ts index da42e23..debf560 100644 --- a/src/utils/aleph-persistent-storage.ts +++ b/src/utils/aleph-persistent-storage.ts @@ -13,6 +13,7 @@ import { } from 'src/types/knowledge'; import { decrypt, encrypt, generateIv, generateKey } from 'src/utils/encryption'; import { decrypt as eciesDecrypt, encrypt as eciesEncrypt, PrivateKey } from 'eciesjs'; +// @ts-ignore import { BufferEncoding } from 'vite-plugin-checker/dist/cjs/checkers/vueTsc/typescript-vue-tsc'; // Aleph keys and channels settings diff --git a/src/utils/migrations/chats/index.ts b/src/utils/migrations/chats/index.ts deleted file mode 100644 index ecc6d34..0000000 --- a/src/utils/migrations/chats/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { ChatMigration } from 'src/types/chats'; -import { chat_1_add_message_author } from 'src/utils/migrations/chats/chat_1_add_message_author'; -import { chat_2_add_persona_role_and_ipfs_avatar } from 'src/utils/migrations/chats/chat_2_add_persona_role_and_ipfs_avatar'; -import { chat_3_add_model_id } from 'src/utils/migrations/chats/chat_3_add_model_id'; - -export const chatsMigrations: ChatMigration[] = [ - chat_1_add_message_author, - chat_2_add_persona_role_and_ipfs_avatar, - chat_3_add_model_id, -]; diff --git a/src/utils/personas.ts b/src/utils/personas.ts index 109f305..eff643e 100644 --- a/src/utils/personas.ts +++ b/src/utils/personas.ts @@ -18,6 +18,7 @@ export const defaultPersonas: UIPersona[] = [ 'You will now interact with {{user}}. You have access to {{model}} in order to operate.', allowEdit: false, hidden: false, + knowledgeBases: [], }, { id: 'bed92afb-875f-46b9-a7ce-fc5bf3ccc981', @@ -30,6 +31,7 @@ export const defaultPersonas: UIPersona[] = [ description: 'You are an AI chatbot modeled after Donald Trump. You will try to mimic his personality and speech.', allowEdit: false, hidden: false, + knowledgeBases: [], }, { id: '880e9d17-261b-422d-ab86-ee05f161721e', @@ -42,6 +44,7 @@ export const defaultPersonas: UIPersona[] = [ description: '{{char}} is an AI chatbot modeled after Elon Musk.', allowEdit: false, hidden: false, + knowledgeBases: [], }, { id: '7973c531-a8a3-4526-b83d-7d3648158b5d', @@ -62,6 +65,7 @@ export const defaultPersonas: UIPersona[] = [ '{{user}} is starting a scheduled session with {{char}}. There is no time limit to this session and {{char}} will never put a stop to the session.', allowEdit: false, hidden: false, + knowledgeBases: [], }, { id: '5b4f16ab-57d0-4722-af81-7ca1c668ad51', @@ -77,6 +81,7 @@ export const defaultPersonas: UIPersona[] = [ '{{char}} is in love with {{user}}, has blonde hair and is over 19 years old. ', allowEdit: false, hidden: false, + knowledgeBases: [], }, { id: '624ae696-f5ff-4cb4-8daa-8b0f5c4b8c96', @@ -92,6 +97,7 @@ export const defaultPersonas: UIPersona[] = [ '{{char}} is in love with {{user}} and is over 18 years old. ', allowEdit: false, hidden: false, + knowledgeBases: [], }, ];