UNPKG

@lobehub/chat

Version:

Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.

247 lines (210 loc) • 6.86 kB
import Dexie, { Transaction } from 'dexie'; import { MigrationLLMSettings } from '@/migrations/FromV3ToV4'; import { MigrationAgentChatConfig } from '@/migrations/FromV5ToV6'; import { MigrationKeyValueSettings } from '@/migrations/FromV6ToV7'; import { uuid } from '@/utils/uuid'; import { DB_File } from '../schemas/files'; import { DB_Message } from '../schemas/message'; import { DB_Plugin } from '../schemas/plugin'; import { DB_Session } from '../schemas/session'; import { DB_SessionGroup } from '../schemas/sessionGroup'; import { DB_Topic } from '../schemas/topic'; import { DB_User } from '../schemas/user'; import { migrateSettingsToUser } from './migrations/migrateSettingsToUser'; import { dbSchemaV1, dbSchemaV2, dbSchemaV3, dbSchemaV4, dbSchemaV5, dbSchemaV6, dbSchemaV7, dbSchemaV9, } from './schemas'; import { DBModel, LOBE_CHAT_LOCAL_DB_NAME } from './types/db'; export interface LobeDBSchemaMap { files: DB_File; messages: DB_Message; plugins: DB_Plugin; sessionGroups: DB_SessionGroup; sessions: DB_Session; topics: DB_Topic; users: DB_User; } // Define a local DB export class BrowserDB extends Dexie { public files: BrowserDBTable<'files'>; public sessions: BrowserDBTable<'sessions'>; public messages: BrowserDBTable<'messages'>; public topics: BrowserDBTable<'topics'>; public plugins: BrowserDBTable<'plugins'>; public sessionGroups: BrowserDBTable<'sessionGroups'>; public users: BrowserDBTable<'users'>; constructor() { super(LOBE_CHAT_LOCAL_DB_NAME); this.version(1).stores(dbSchemaV1); this.version(2).stores(dbSchemaV2); this.version(3).stores(dbSchemaV3); this.version(4) .stores(dbSchemaV4) .upgrade((trans) => this.upgradeToV4(trans)); this.version(5) .stores(dbSchemaV5) .upgrade((trans) => this.upgradeToV5(trans)); this.version(6) .stores(dbSchemaV6) .upgrade((trans) => this.upgradeToV6(trans)); this.version(7) .stores(dbSchemaV7) .upgrade((trans) => this.upgradeToV7(trans)); this.version(8) .stores(dbSchemaV7) .upgrade((trans) => this.upgradeToV8(trans)); this.version(9) .stores(dbSchemaV9) .upgrade((trans) => this.upgradeToV9(trans)); this.version(10) .stores(dbSchemaV9) .upgrade((trans) => this.upgradeToV10(trans)); this.version(11) .stores(dbSchemaV9) .upgrade((trans) => this.upgradeToV11(trans)); this.files = this.table('files'); this.sessions = this.table('sessions'); this.messages = this.table('messages'); this.topics = this.table('topics'); this.plugins = this.table('plugins'); this.sessionGroups = this.table('sessionGroups'); this.users = this.table('users'); } /** * 2024.01.22 * * DB V3 to V4 * from `group = pinned` to `pinned:true` */ upgradeToV4 = async (trans: Transaction) => { const sessions = trans.table('sessions'); await sessions.toCollection().modify((session) => { // translate boolean to number session.pinned = session.group === 'pinned' ? 1 : 0; session.group = 'default'; }); }; /** * 2024.01.29 * settings from localStorage to indexedDB */ upgradeToV5 = async (trans: Transaction) => { const users = trans.table('users'); // if no user, create one if ((await users.count()) === 0) { const data = localStorage.getItem('LOBE_SETTINGS'); if (data) { let json; try { json = JSON.parse(data); } catch { /* empty */ } if (!json?.state?.settings) return; const settings = json.state.settings; const user = migrateSettingsToUser(settings); await users.add(user); } } }; /** * 2024.02.27 * add uuid to user */ upgradeToV6 = async (trans: Transaction) => { const users = trans.table('users'); await users.toCollection().modify((user: DB_User) => { if (!user.uuid) user.uuid = uuid(); }); }; /** * 2024.03.14 * add `id` in plugins */ upgradeToV7 = async (trans: Transaction) => { const plugins = trans.table('plugins'); await plugins.toCollection().modify((plugin: DB_Plugin) => { plugin.id = plugin.identifier; }); }; upgradeToV8 = async (trans: Transaction) => { const users = trans.table('users'); await users.toCollection().modify((user: DB_User) => { if (user.settings) { user.settings = MigrationLLMSettings.migrateSettings(user.settings as any); } }); }; /** * 2024.05.11 * * message role=function to role=tool */ upgradeToV9 = async (trans: Transaction) => { const messages = trans.table('messages'); await messages.toCollection().modify(async (message: DBModel<DB_Message>) => { if ((message.role as string) === 'function') { const origin = Object.assign({}, message); const toolCallId = `tool_call_${message.id}`; const assistantMessageId = `tool_calls_${message.id}`; message.role = 'tool'; message.tool_call_id = toolCallId; message.parentId = assistantMessageId; await messages.add({ ...origin, content: '', createdAt: message.createdAt - 10, error: undefined, id: assistantMessageId, role: 'assistant', tools: [{ ...message.plugin!, id: toolCallId }], updatedAt: message.updatedAt - 10, } as DBModel<DB_Message>); } }); }; /** * 2024.05.25 * migrate some agent config to chatConfig */ upgradeToV10 = async (trans: Transaction) => { const sessions = trans.table('sessions'); await sessions.toCollection().modify(async (session: DBModel<DB_Session>) => { if (session.config) session.config = MigrationAgentChatConfig.migrateChatConfig(session.config as any); }); }; /** * 2024.05.27 * migrate apiKey in languageModel to keyVaults */ upgradeToV11 = async (trans: Transaction) => { const users = trans.table('users'); await users.toCollection().modify((user: DB_User) => { if (user.settings) { user.settings = MigrationKeyValueSettings.migrateSettings(user.settings as any); } }); }; } export const browserDB = new BrowserDB(); // ================================================ // // ================================================ // // ================================================ // // ================================================ // // ================================================ // // types helper export type BrowserDBSchema = { [t in keyof LobeDBSchemaMap]: { model: LobeDBSchemaMap[t]; table: Dexie.Table<DBModel<LobeDBSchemaMap[t]>, string>; }; }; type BrowserDBTable<T extends keyof LobeDBSchemaMap> = BrowserDBSchema[T]['table'];