1
import Dexie, { Transaction } from 'dexie';
3
import { MigrationLLMSettings } from '@/migrations/FromV3ToV4';
4
import { MigrationAgentChatConfig } from '@/migrations/FromV5ToV6';
5
import { MigrationKeyValueSettings } from '@/migrations/FromV6ToV7';
6
import { uuid } from '@/utils/uuid';
8
import { DB_File } from '../schemas/files';
9
import { DB_Message } from '../schemas/message';
10
import { DB_Plugin } from '../schemas/plugin';
11
import { DB_Session } from '../schemas/session';
12
import { DB_SessionGroup } from '../schemas/sessionGroup';
13
import { DB_Topic } from '../schemas/topic';
14
import { DB_User } from '../schemas/user';
15
import { migrateSettingsToUser } from './migrations/migrateSettingsToUser';
26
import { DBModel, LOBE_CHAT_LOCAL_DB_NAME } from './types/db';
28
export interface LobeDBSchemaMap {
32
sessionGroups: DB_SessionGroup;
39
export class BrowserDB extends Dexie {
40
public files: BrowserDBTable<'files'>;
41
public sessions: BrowserDBTable<'sessions'>;
42
public messages: BrowserDBTable<'messages'>;
43
public topics: BrowserDBTable<'topics'>;
44
public plugins: BrowserDBTable<'plugins'>;
45
public sessionGroups: BrowserDBTable<'sessionGroups'>;
46
public users: BrowserDBTable<'users'>;
49
super(LOBE_CHAT_LOCAL_DB_NAME);
50
this.version(1).stores(dbSchemaV1);
51
this.version(2).stores(dbSchemaV2);
52
this.version(3).stores(dbSchemaV3);
55
.upgrade((trans) => this.upgradeToV4(trans));
59
.upgrade((trans) => this.upgradeToV5(trans));
63
.upgrade((trans) => this.upgradeToV6(trans));
67
.upgrade((trans) => this.upgradeToV7(trans));
71
.upgrade((trans) => this.upgradeToV8(trans));
75
.upgrade((trans) => this.upgradeToV9(trans));
79
.upgrade((trans) => this.upgradeToV10(trans));
83
.upgrade((trans) => this.upgradeToV11(trans));
85
this.files = this.table('files');
86
this.sessions = this.table('sessions');
87
this.messages = this.table('messages');
88
this.topics = this.table('topics');
89
this.plugins = this.table('plugins');
90
this.sessionGroups = this.table('sessionGroups');
91
this.users = this.table('users');
98
* from `group = pinned` to `pinned:true`
100
upgradeToV4 = async (trans: Transaction) => {
101
const sessions = trans.table('sessions');
102
await sessions.toCollection().modify((session) => {
103
// translate boolean to number
104
session.pinned = session.group === 'pinned' ? 1 : 0;
105
session.group = 'default';
111
* settings from localStorage to indexedDB
113
upgradeToV5 = async (trans: Transaction) => {
114
const users = trans.table('users');
116
// if no user, create one
117
if ((await users.count()) === 0) {
118
const data = localStorage.getItem('LOBE_SETTINGS');
124
json = JSON.parse(data);
129
if (!json?.state?.settings) return;
131
const settings = json.state.settings;
133
const user = migrateSettingsToUser(settings);
134
await users.add(user);
143
upgradeToV6 = async (trans: Transaction) => {
144
const users = trans.table('users');
146
await users.toCollection().modify((user: DB_User) => {
147
if (!user.uuid) user.uuid = uuid();
153
* add `id` in plugins
155
upgradeToV7 = async (trans: Transaction) => {
156
const plugins = trans.table('plugins');
158
await plugins.toCollection().modify((plugin: DB_Plugin) => {
159
plugin.id = plugin.identifier;
163
upgradeToV8 = async (trans: Transaction) => {
164
const users = trans.table('users');
165
await users.toCollection().modify((user: DB_User) => {
167
user.settings = MigrationLLMSettings.migrateSettings(user.settings as any);
175
* message role=function to role=tool
177
upgradeToV9 = async (trans: Transaction) => {
178
const messages = trans.table('messages');
179
await messages.toCollection().modify(async (message: DBModel<DB_Message>) => {
180
if ((message.role as string) === 'function') {
181
const origin = Object.assign({}, message);
183
const toolCallId = `tool_call_${message.id}`;
184
const assistantMessageId = `tool_calls_${message.id}`;
186
message.role = 'tool';
187
message.tool_call_id = toolCallId;
188
message.parentId = assistantMessageId;
193
createdAt: message.createdAt - 10,
195
id: assistantMessageId,
197
tools: [{ ...message.plugin!, id: toolCallId }],
198
updatedAt: message.updatedAt - 10,
199
} as DBModel<DB_Message>);
206
* migrate some agent config to chatConfig
208
upgradeToV10 = async (trans: Transaction) => {
209
const sessions = trans.table('sessions');
210
await sessions.toCollection().modify(async (session: DBModel<DB_Session>) => {
212
session.config = MigrationAgentChatConfig.migrateChatConfig(session.config as any);
218
* migrate apiKey in languageModel to keyVaults
220
upgradeToV11 = async (trans: Transaction) => {
221
const users = trans.table('users');
223
await users.toCollection().modify((user: DB_User) => {
225
user.settings = MigrationKeyValueSettings.migrateSettings(user.settings as any);
231
export const browserDB = new BrowserDB();
233
// ================================================ //
234
// ================================================ //
235
// ================================================ //
236
// ================================================ //
237
// ================================================ //
240
export type BrowserDBSchema = {
241
[t in keyof LobeDBSchemaMap]: {
242
model: LobeDBSchemaMap[t];
243
table: Dexie.Table<DBModel<LobeDBSchemaMap[t]>, string>;
246
type BrowserDBTable<T extends keyof LobeDBSchemaMap> = BrowserDBSchema[T]['table'];