@lobehub/chat 1.9.2 → 1.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.9.4](https://github.com/lobehub/lobe-chat/compare/v1.9.3...v1.9.4)
6
+
7
+ <sup>Released on **2024-08-06**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix import clerk `AuthObject` from public api.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix import clerk `AuthObject` from public api, closes [#3416](https://github.com/lobehub/lobe-chat/issues/3416) ([af8960d](https://github.com/lobehub/lobe-chat/commit/af8960d))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
30
+ ### [Version 1.9.3](https://github.com/lobehub/lobe-chat/compare/v1.9.2...v1.9.3)
31
+
32
+ <sup>Released on **2024-08-06**</sup>
33
+
34
+ #### ♻ Code Refactoring
35
+
36
+ - **misc**: Refactor server db schema for better code organize.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### Code refactoring
44
+
45
+ - **misc**: Refactor server db schema for better code organize, closes [#3410](https://github.com/lobehub/lobe-chat/issues/3410) ([4743bfd](https://github.com/lobehub/lobe-chat/commit/4743bfd))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ### [Version 1.9.2](https://github.com/lobehub/lobe-chat/compare/v1.9.1...v1.9.2)
6
56
 
7
57
  <sup>Released on **2024-08-05**</sup>
package/README.md CHANGED
@@ -266,14 +266,14 @@ Our marketplace is not just a showcase platform but also a collaborative space.
266
266
 
267
267
  <!-- AGENT LIST -->
268
268
 
269
- | Recent Submits | Description |
270
- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
271
- | [Omnipedia](https://chat-preview.lobehub.com/market?agent=omnipedia)<br/><sup>By **[thedivergentai](https://github.com/thedivergentai)** on **2024-08-02**</sup> | Expert in providing high-quality, well-researched information on various topics, including history, science, literature, art, and more. Skilled in summarizing complex topics, assisting with research tasks, and offering creative prompts<br/>`artificial-intelligence` `information` `education` `communication` |
272
- | [Code Snark Master](https://chat-preview.lobehub.com/market?agent=code-snark-master)<br/><sup>By **[leter](https://github.com/leter)** on **2024-07-29**</sup> | Specializes in sharp criticism of code, sarcastically pointing out inefficiencies and readability issues<br/>`tech-leadership` `code-review` `sarcastic-style` `programming-consultation` |
273
- | [Unity Maestro](https://chat-preview.lobehub.com/market?agent=unity-maestro)<br/><sup>By **[thedivergentai](https://github.com/thedivergentai)** on **2024-07-29**</sup> | Expert Unity Game Development Companion<br/>`game-development` `unity` `software-engineering` |
274
- | [C Program Learning Assistant](https://chat-preview.lobehub.com/market?agent=sichuan-university-941-c-programming-assistant)<br/><sup>By **[YBGuoYang](https://github.com/YBGuoYang)** on **2024-07-28**</sup> | Assist me in learning C program design<br/>`941` |
275
-
276
- > 📊 Total agents: [<kbd>**310**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
269
+ | Recent Submits | Description |
270
+ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
271
+ | [RO-SCIRAW Prompt Word Expert](https://chat-preview.lobehub.com/market?agent=rosciraw)<br/><sup>By **[kirklin](https://github.com/kirklin)** on **2024-08-06**</sup> | The RO-SCIRAW framework, created by Kirk Lin, is a methodology for prompt words that provides a new paradigm for building highly precise and efficient prompt words. Please enter the information for the persona you want to create.<br/>`prompt-word-framework` |
272
+ | [Social Media Sage](https://chat-preview.lobehub.com/market?agent=social-media-sage)<br/><sup>By **[thedivergentai](https://github.com/thedivergentai)** on **2024-08-06**</sup> | Social Media Marketing expert crafting winning strategies for brands and empowering businesses to thrive online<br/>`social-media-marketing` `branding` `growth-strategies` |
273
+ | [Omnipedia](https://chat-preview.lobehub.com/market?agent=omnipedia)<br/><sup>By **[thedivergentai](https://github.com/thedivergentai)** on **2024-08-02**</sup> | Expert in providing high-quality, well-researched information on various topics, including history, science, literature, art, and more. Skilled in summarizing complex topics, assisting with research tasks, and offering creative prompts<br/>`artificial-intelligence` `information` `education` `communication` |
274
+ | [Code Snark Master](https://chat-preview.lobehub.com/market?agent=code-snark-master)<br/><sup>By **[leter](https://github.com/leter)** on **2024-07-29**</sup> | Specializes in sharp criticism of code, sarcastically pointing out inefficiencies and readability issues<br/>`tech-leadership` `code-review` `sarcastic-style` `programming-consultation` |
275
+
276
+ > 📊 Total agents: [<kbd>**312**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
277
277
 
278
278
  <!-- AGENT LIST -->
279
279
 
package/README.zh-CN.md CHANGED
@@ -254,14 +254,14 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
254
254
 
255
255
  <!-- AGENT LIST -->
256
256
 
257
- | 最近新增 | 助手说明 |
258
- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
259
- | [Omnipedia](https://chat-preview.lobehub.com/market?agent=omnipedia)<br/><sup>By **[thedivergentai](https://github.com/thedivergentai)** on **2024-08-02**</sup> | 专业提供高质量、深入研究的各种主题信息,包括历史、科学、文学、艺术等。擅长总结复杂主题,协助研究任务,并提供创意启示。<br/>`artificial-intelligence` `information` `education` `communication` |
260
- | [代码毒舌大师](https://chat-preview.lobehub.com/market?agent=code-snark-master)<br/><sup>By **[leter](https://github.com/leter)** on **2024-07-29**</sup> | 擅长尖刻批评代码,讽刺性地指出低效和可读性问题<br/>`技术领导` `代码审查` `讽刺风格` `编程咨询` |
261
- | [Unity Maestro](https://chat-preview.lobehub.com/market?agent=unity-maestro)<br/><sup>By **[thedivergentai](https://github.com/thedivergentai)** on **2024-07-29**</sup> | Expert Unity Game Development Companion<br/>`game-development` `unity` `software-engineering` |
262
- | [c 程序学习助手](https://chat-preview.lobehub.com/market?agent=sichuan-university-941-c-programming-assistant)<br/><sup>By **[YBGuoYang](https://github.com/YBGuoYang)** on **2024-07-28**</sup> | 辅助我进行 c 程序设计的学习<br/>`941` |
263
-
264
- > 📊 Total agents: [<kbd>**310**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
257
+ | 最近新增 | 助手说明 |
258
+ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
259
+ | [RO-SCIRAW 提示词专家](https://chat-preview.lobehub.com/market?agent=rosciraw)<br/><sup>By **[kirklin](https://github.com/kirklin)** on **2024-08-06**</sup> | RO-SCIRAW 框架是由 Kirk Lin 开创的提示词方法论,为构建高度精确和高效的提示词提供了一个全新的范式。请输入你要创建的分身信息。<br/>`提示词框架` |
260
+ | [社交媒体专家](https://chat-preview.lobehub.com/market?agent=social-media-sage)<br/><sup>By **[thedivergentai](https://github.com/thedivergentai)** on **2024-08-06**</sup> | 社交媒体营销专家,为品牌制定成功策略,帮助企业在线蓬勃发展<br/>`社交媒体营销` `品牌塑造` `增长策略` |
261
+ | [Omnipedia](https://chat-preview.lobehub.com/market?agent=omnipedia)<br/><sup>By **[thedivergentai](https://github.com/thedivergentai)** on **2024-08-02**</sup> | 专业提供高质量、深入研究的各种主题信息,包括历史、科学、文学、艺术等。擅长总结复杂主题,协助研究任务,并提供创意启示。<br/>`artificial-intelligence` `information` `education` `communication` |
262
+ | [代码毒舌大师](https://chat-preview.lobehub.com/market?agent=code-snark-master)<br/><sup>By **[leter](https://github.com/leter)** on **2024-07-29**</sup> | 擅长尖刻批评代码,讽刺性地指出低效和可读性问题<br/>`技术领导` `代码审查` `讽刺风格` `编程咨询` |
263
+
264
+ > 📊 Total agents: [<kbd>**312**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
265
265
 
266
266
  <!-- AGENT LIST -->
267
267
 
package/drizzle.config.ts CHANGED
@@ -24,6 +24,6 @@ export default {
24
24
  dialect: 'postgresql',
25
25
  out: './src/database/server/migrations',
26
26
 
27
- schema: './src/database/server/schemas/lobechat.ts',
27
+ schema: './src/database/server/schemas/lobechat',
28
28
  strict: true,
29
29
  } satisfies Config;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.9.2",
3
+ "version": "1.9.4",
4
4
  "description": "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.",
5
5
  "keywords": [
6
6
  "framework",
@@ -108,7 +108,7 @@
108
108
  "@azure/openai": "1.0.0-beta.12",
109
109
  "@cfworker/json-schema": "^1.12.8",
110
110
  "@clerk/localizations": "2.0.0",
111
- "@clerk/nextjs": "^5.2.6",
111
+ "@clerk/nextjs": "^5.2.14",
112
112
  "@clerk/themes": "^2.1.10",
113
113
  "@google/generative-ai": "^0.16.0",
114
114
  "@icons-pack/react-simple-icons": "^9.6.0",
@@ -163,7 +163,7 @@
163
163
  "numeral": "^2.0.6",
164
164
  "nuqs": "^1.17.4",
165
165
  "ollama": "^0.5.2",
166
- "openai": "^4.52.3",
166
+ "openai": "~4.54.0",
167
167
  "partial-json": "^0.1.7",
168
168
  "pg": "^8.12.0",
169
169
  "pino": "^9.2.0",
@@ -1,4 +1,4 @@
1
- import { AuthObject } from '@clerk/backend/internal';
1
+ import { AuthObject } from '@clerk/backend';
2
2
  import { getAuth } from '@clerk/nextjs/server';
3
3
  import { NextRequest } from 'next/server';
4
4
 
@@ -1,4 +1,4 @@
1
- import { type AuthObject } from '@clerk/backend/internal';
1
+ import { type AuthObject } from '@clerk/backend';
2
2
  import { beforeEach, describe, expect, it, vi } from 'vitest';
3
3
 
4
4
  import { getAppConfig } from '@/config/app';
@@ -1,4 +1,4 @@
1
- import { type AuthObject } from '@clerk/backend/internal';
1
+ import { type AuthObject } from '@clerk/backend';
2
2
  import { importJWK, jwtVerify } from 'jose';
3
3
 
4
4
  import { getAppConfig } from '@/config/app';
@@ -0,0 +1,6 @@
1
+ import { timestamp } from 'drizzle-orm/pg-core';
2
+
3
+ export const timestamptz = (name: string) => timestamp(name, { withTimezone: true });
4
+
5
+ export const createdAt = () => timestamptz('created_at').notNull().defaultNow();
6
+ export const updatedAt = () => timestamptz('updated_at').notNull().defaultNow();
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix */
2
2
  import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
3
- import { relations } from 'drizzle-orm';
4
3
  import {
5
4
  boolean,
6
5
  index,
@@ -8,177 +7,20 @@ import {
8
7
  jsonb,
9
8
  pgTable,
10
9
  primaryKey,
11
- serial,
12
10
  text,
13
- timestamp,
14
11
  unique,
15
12
  uniqueIndex,
16
13
  varchar,
17
14
  } from 'drizzle-orm/pg-core';
18
15
  import { createInsertSchema, createSelectSchema } from 'drizzle-zod';
19
16
 
20
- import { DEFAULT_PREFERENCE } from '@/const/user';
21
17
  import { LobeAgentChatConfig, LobeAgentTTSConfig } from '@/types/agent';
22
18
  import { CustomPluginParams } from '@/types/tool/plugin';
23
19
 
24
- import { idGenerator, randomSlug } from '../utils/idGenerator';
25
-
26
- // Schema for nextauth
27
- export * from './nextauth';
28
-
29
- const timestamptz = (name: string) => timestamp(name, { withTimezone: true });
30
-
31
- const createdAt = () => timestamptz('created_at').notNull().defaultNow();
32
- const updatedAt = () => timestamptz('updated_at').notNull().defaultNow();
33
-
34
- /**
35
- * This table stores users. Users are created in Clerk, then Clerk calls a
36
- * webhook at /api/webhook/clerk to inform this application a user was created.
37
- */
38
- export const users = pgTable('users', {
39
- // The ID will be the user's ID from Clerk
40
- id: text('id').primaryKey().notNull(),
41
- username: text('username').unique(),
42
- email: text('email'),
43
-
44
- avatar: text('avatar'),
45
- phone: text('phone'),
46
- firstName: text('first_name'),
47
- lastName: text('last_name'),
48
- fullName: text('full_name'),
49
-
50
- isOnboarded: boolean('is_onboarded').default(false),
51
- // Time user was created in Clerk
52
- clerkCreatedAt: timestamptz('clerk_created_at'),
53
-
54
- // Required by nextauth, all null allowed
55
- emailVerifiedAt: timestamptz('email_verified_at'),
56
-
57
- preference: jsonb('preference').$defaultFn(() => DEFAULT_PREFERENCE),
58
-
59
- createdAt: createdAt(),
60
- updatedAt: updatedAt(),
61
- });
62
-
63
- export type NewUser = typeof users.$inferInsert;
64
- export type UserItem = typeof users.$inferSelect;
65
-
66
- export const userSubscriptions = pgTable('user_subscriptions', {
67
- id: text('id').primaryKey().notNull(),
68
- userId: text('user_id')
69
- .references(() => users.id, { onDelete: 'cascade' })
70
- .notNull(),
71
- stripeId: text('stripe_id'),
72
-
73
- currency: text('currency'),
74
- pricing: integer('pricing'),
75
- billingPaidAt: integer('billing_paid_at'),
76
- billingCycleStart: integer('billing_cycle_start'),
77
- billingCycleEnd: integer('billing_cycle_end'),
78
-
79
- cancelAtPeriodEnd: boolean('cancel_at_period_end'),
80
- cancelAt: integer('cancel_at'),
81
-
82
- nextBilling: jsonb('next_billing'),
83
-
84
- plan: text('plan'),
85
- recurring: text('recurring'),
86
-
87
- storageLimit: integer('storage_limit'),
88
-
89
- status: integer('status'),
90
- createdAt: createdAt(),
91
- updatedAt: updatedAt(),
92
- });
93
-
94
- export type NewUserSubscription = typeof userSubscriptions.$inferInsert;
95
- export type UserSubscriptionItem = typeof userSubscriptions.$inferSelect;
96
-
97
- export const userBudgets = pgTable('user_budgets', {
98
- id: text('id')
99
- .primaryKey()
100
- .references(() => users.id, { onDelete: 'cascade' })
101
- .notNull(),
102
-
103
- freeBudgetId: text('free_budget_id'),
104
- freeBudgetKey: text('free_budget_key'),
105
-
106
- subscriptionBudgetId: text('subscription_budget_id'),
107
- subscriptionBudgetKey: text('subscription_budget_key'),
108
-
109
- packageBudgetId: text('package_budget_id'),
110
- packageBudgetKey: text('package_budget_key'),
111
-
112
- createdAt: createdAt(),
113
- updatedAt: updatedAt(),
114
- });
115
-
116
- export type NewUserBudgets = typeof userBudgets.$inferInsert;
117
- export type UserBudgetItem = typeof userBudgets.$inferSelect;
118
-
119
- export const userSettings = pgTable('user_settings', {
120
- id: text('id')
121
- .references(() => users.id, { onDelete: 'cascade' })
122
- .primaryKey(),
123
-
124
- tts: jsonb('tts'),
125
- keyVaults: text('key_vaults'),
126
- general: jsonb('general'),
127
- languageModel: jsonb('language_model'),
128
- systemAgent: jsonb('system_agent'),
129
- defaultAgent: jsonb('default_agent'),
130
- tool: jsonb('tool'),
131
- });
132
-
133
- export const tags = pgTable('tags', {
134
- id: serial('id').primaryKey(),
135
- slug: text('slug').notNull().unique(),
136
- name: text('name'),
137
-
138
- userId: text('user_id')
139
- .references(() => users.id, { onDelete: 'cascade' })
140
- .notNull(),
141
-
142
- createdAt: createdAt(),
143
- updatedAt: updatedAt(),
144
- });
145
-
146
- export const files = pgTable('files', {
147
- id: text('id')
148
- .$defaultFn(() => idGenerator('files'))
149
- .primaryKey(),
150
-
151
- userId: text('user_id')
152
- .references(() => users.id, { onDelete: 'cascade' })
153
- .notNull(),
154
- fileType: varchar('file_type', { length: 255 }).notNull(),
155
- name: text('name').notNull(),
156
- size: integer('size').notNull(),
157
- url: text('url').notNull(),
158
-
159
- metadata: jsonb('metadata'),
160
-
161
- createdAt: createdAt(),
162
- updatedAt: updatedAt(),
163
- });
164
-
165
- export type NewFile = typeof files.$inferInsert;
166
- export type FileItem = typeof files.$inferSelect;
167
-
168
- export const plugins = pgTable('plugins', {
169
- id: serial('id').primaryKey(),
170
- identifier: text('identifier').notNull().unique(),
171
-
172
- title: text('title').notNull(),
173
- description: text('description'),
174
- avatar: text('avatar'),
175
- author: text('author'),
176
-
177
- manifest: text('manifest').notNull(),
178
- locale: text('locale').notNull(),
179
- createdAt: createdAt(),
180
- updatedAt: updatedAt(),
181
- });
20
+ import { idGenerator, randomSlug } from '../../utils/idGenerator';
21
+ import { createdAt, updatedAt } from './_helpers';
22
+ import { files } from './file';
23
+ import { users } from './user';
182
24
 
183
25
  export const installedPlugins = pgTable(
184
26
  'user_installed_plugins',
@@ -204,21 +46,6 @@ export const installedPlugins = pgTable(
204
46
  export type NewInstalledPlugin = typeof installedPlugins.$inferInsert;
205
47
  export type InstalledPluginItem = typeof installedPlugins.$inferSelect;
206
48
 
207
- export const pluginsTags = pgTable(
208
- 'plugins_tags',
209
- {
210
- pluginId: integer('plugin_id')
211
- .notNull()
212
- .references(() => plugins.id, { onDelete: 'cascade' }),
213
- tagId: integer('tag_id')
214
- .notNull()
215
- .references(() => tags.id, { onDelete: 'cascade' }),
216
- },
217
- (t) => ({
218
- pk: primaryKey({ columns: [t.pluginId, t.tagId] }),
219
- }),
220
- );
221
-
222
49
  // ======= agents ======= //
223
50
  export const agents = pgTable('agents', {
224
51
  id: text('id')
@@ -252,47 +79,11 @@ export const agents = pgTable('agents', {
252
79
  updatedAt: updatedAt(),
253
80
  });
254
81
 
255
- export const agentsTags = pgTable(
256
- 'agents_tags',
257
- {
258
- agentId: text('agent_id')
259
- .notNull()
260
- .references(() => agents.id, { onDelete: 'cascade' }),
261
- tagId: integer('tag_id')
262
- .notNull()
263
- .references(() => tags.id, { onDelete: 'cascade' }),
264
- },
265
- (t) => ({
266
- pk: primaryKey({ columns: [t.agentId, t.tagId] }),
267
- }),
268
- );
269
82
  export const insertAgentSchema = createInsertSchema(agents);
270
83
 
271
84
  export type NewAgent = typeof agents.$inferInsert;
272
85
  export type AgentItem = typeof agents.$inferSelect;
273
86
 
274
- // ======= market ======= //
275
-
276
- export const market = pgTable('market', {
277
- id: serial('id').primaryKey(),
278
-
279
- agentId: text('agent_id').references(() => agents.id, { onDelete: 'cascade' }),
280
- pluginId: integer('plugin_id').references(() => plugins.id, { onDelete: 'cascade' }),
281
-
282
- type: text('type', { enum: ['plugin', 'model', 'agent', 'group'] }).notNull(),
283
-
284
- view: integer('view').default(0),
285
- like: integer('like').default(0),
286
- used: integer('used').default(0),
287
-
288
- userId: text('user_id')
289
- .references(() => users.id, { onDelete: 'cascade' })
290
- .notNull(),
291
-
292
- createdAt: createdAt(),
293
- updatedAt: updatedAt(),
294
- });
295
-
296
87
  // ======= sessionGroups ======= //
297
88
 
298
89
  export const sessionGroups = pgTable(
@@ -538,125 +329,3 @@ export const filesToAgents = pgTable(
538
329
  pk: primaryKey({ columns: [t.fileId, t.agentId] }),
539
330
  }),
540
331
  );
541
-
542
- export const filesRelations = relations(files, ({ many }) => ({
543
- filesToMessages: many(filesToMessages),
544
- filesToSessions: many(filesToSessions),
545
- filesToAgents: many(filesToAgents),
546
- }));
547
-
548
- export const topicRelations = relations(topics, ({ one }) => ({
549
- session: one(sessions, {
550
- fields: [topics.sessionId],
551
- references: [sessions.id],
552
- }),
553
- }));
554
-
555
- export const pluginsRelations = relations(plugins, ({ many }) => ({
556
- pluginsTags: many(pluginsTags),
557
- }));
558
-
559
- export const pluginsTagsRelations = relations(pluginsTags, ({ one }) => ({
560
- plugin: one(plugins, {
561
- fields: [pluginsTags.pluginId],
562
- references: [plugins.id],
563
- }),
564
- tag: one(tags, {
565
- fields: [pluginsTags.tagId],
566
- references: [tags.id],
567
- }),
568
- }));
569
-
570
- export const tagsRelations = relations(tags, ({ many }) => ({
571
- agentsTags: many(agentsTags),
572
- pluginsTags: many(pluginsTags),
573
- }));
574
-
575
- export const messagesRelations = relations(messages, ({ many, one }) => ({
576
- filesToMessages: many(filesToMessages),
577
-
578
- session: one(sessions, {
579
- fields: [messages.sessionId],
580
- references: [sessions.id],
581
- }),
582
-
583
- parent: one(messages, {
584
- fields: [messages.parentId],
585
- references: [messages.id],
586
- }),
587
-
588
- topic: one(topics, {
589
- fields: [messages.topicId],
590
- references: [topics.id],
591
- }),
592
- }));
593
-
594
- export const agentsRelations = relations(agents, ({ many }) => ({
595
- agentsToSessions: many(agentsToSessions),
596
- filesToAgents: many(filesToAgents),
597
- agentsTags: many(agentsTags),
598
- }));
599
-
600
- export const agentsToSessionsRelations = relations(agentsToSessions, ({ one }) => ({
601
- session: one(sessions, {
602
- fields: [agentsToSessions.sessionId],
603
- references: [sessions.id],
604
- }),
605
- agent: one(agents, {
606
- fields: [agentsToSessions.agentId],
607
- references: [agents.id],
608
- }),
609
- }));
610
-
611
- export const filesToAgentsRelations = relations(filesToAgents, ({ one }) => ({
612
- agent: one(agents, {
613
- fields: [filesToAgents.agentId],
614
- references: [agents.id],
615
- }),
616
- file: one(files, {
617
- fields: [filesToAgents.fileId],
618
- references: [files.id],
619
- }),
620
- }));
621
-
622
- export const filesToMessagesRelations = relations(filesToMessages, ({ one }) => ({
623
- file: one(files, {
624
- fields: [filesToMessages.fileId],
625
- references: [files.id],
626
- }),
627
- message: one(messages, {
628
- fields: [filesToMessages.messageId],
629
- references: [messages.id],
630
- }),
631
- }));
632
-
633
- export const filesToSessionsRelations = relations(filesToSessions, ({ one }) => ({
634
- file: one(files, {
635
- fields: [filesToSessions.fileId],
636
- references: [files.id],
637
- }),
638
- session: one(sessions, {
639
- fields: [filesToSessions.sessionId],
640
- references: [sessions.id],
641
- }),
642
- }));
643
-
644
- export const agentsTagsRelations = relations(agentsTags, ({ one }) => ({
645
- agent: one(agents, {
646
- fields: [agentsTags.agentId],
647
- references: [agents.id],
648
- }),
649
- tag: one(tags, {
650
- fields: [agentsTags.tagId],
651
- references: [tags.id],
652
- }),
653
- }));
654
-
655
- export const sessionsRelations = relations(sessions, ({ many, one }) => ({
656
- filesToSessions: many(filesToSessions),
657
- agentsToSessions: many(agentsToSessions),
658
- group: one(sessionGroups, {
659
- fields: [sessions.groupId],
660
- references: [sessionGroups.id],
661
- }),
662
- }));
@@ -0,0 +1,84 @@
1
+ /* eslint-disable sort-keys-fix/sort-keys-fix */
2
+ import { integer, pgTable, primaryKey, serial, text } from 'drizzle-orm/pg-core';
3
+
4
+ import { createdAt, updatedAt } from './_helpers';
5
+ import { agents } from './chat';
6
+ import { users } from './user';
7
+
8
+ export const tags = pgTable('tags', {
9
+ id: serial('id').primaryKey(),
10
+ slug: text('slug').notNull().unique(),
11
+ name: text('name'),
12
+
13
+ userId: text('user_id')
14
+ .references(() => users.id, { onDelete: 'cascade' })
15
+ .notNull(),
16
+
17
+ createdAt: createdAt(),
18
+ updatedAt: updatedAt(),
19
+ });
20
+
21
+ export const plugins = pgTable('plugins', {
22
+ id: serial('id').primaryKey(),
23
+ identifier: text('identifier').notNull().unique(),
24
+
25
+ title: text('title').notNull(),
26
+ description: text('description'),
27
+ avatar: text('avatar'),
28
+ author: text('author'),
29
+
30
+ manifest: text('manifest').notNull(),
31
+ locale: text('locale').notNull(),
32
+ createdAt: createdAt(),
33
+ updatedAt: updatedAt(),
34
+ });
35
+
36
+ export const pluginsTags = pgTable(
37
+ 'plugins_tags',
38
+ {
39
+ pluginId: integer('plugin_id')
40
+ .notNull()
41
+ .references(() => plugins.id, { onDelete: 'cascade' }),
42
+ tagId: integer('tag_id')
43
+ .notNull()
44
+ .references(() => tags.id, { onDelete: 'cascade' }),
45
+ },
46
+ (t) => ({
47
+ pk: primaryKey({ columns: [t.pluginId, t.tagId] }),
48
+ }),
49
+ );
50
+
51
+ export const agentsTags = pgTable(
52
+ 'agents_tags',
53
+ {
54
+ agentId: text('agent_id')
55
+ .notNull()
56
+ .references(() => agents.id, { onDelete: 'cascade' }),
57
+ tagId: integer('tag_id')
58
+ .notNull()
59
+ .references(() => tags.id, { onDelete: 'cascade' }),
60
+ },
61
+ (t) => ({
62
+ pk: primaryKey({ columns: [t.agentId, t.tagId] }),
63
+ }),
64
+ );
65
+
66
+ export const market = pgTable('market', {
67
+ id: serial('id').primaryKey(),
68
+
69
+ agentId: text('agent_id').references(() => agents.id, { onDelete: 'cascade' }),
70
+ pluginId: integer('plugin_id').references(() => plugins.id, { onDelete: 'cascade' }),
71
+
72
+ type: text('type', { enum: ['plugin', 'model', 'agent', 'group'] }).notNull(),
73
+
74
+ view: integer('view').default(0),
75
+ like: integer('like').default(0),
76
+ used: integer('used').default(0),
77
+
78
+ userId: text('user_id')
79
+ .references(() => users.id, { onDelete: 'cascade' })
80
+ .notNull(),
81
+
82
+ createdAt: createdAt(),
83
+ updatedAt: updatedAt(),
84
+ });
@@ -0,0 +1,28 @@
1
+ /* eslint-disable sort-keys-fix/sort-keys-fix */
2
+ import { integer, jsonb, pgTable, text, varchar } from 'drizzle-orm/pg-core';
3
+
4
+ import { idGenerator } from '../../utils/idGenerator';
5
+ import { createdAt, updatedAt } from './_helpers';
6
+ import { users } from './user';
7
+
8
+ export const files = pgTable('files', {
9
+ id: text('id')
10
+ .$defaultFn(() => idGenerator('files'))
11
+ .primaryKey(),
12
+
13
+ userId: text('user_id')
14
+ .references(() => users.id, { onDelete: 'cascade' })
15
+ .notNull(),
16
+ fileType: varchar('file_type', { length: 255 }).notNull(),
17
+ name: text('name').notNull(),
18
+ size: integer('size').notNull(),
19
+ url: text('url').notNull(),
20
+
21
+ metadata: jsonb('metadata'),
22
+
23
+ createdAt: createdAt(),
24
+ updatedAt: updatedAt(),
25
+ });
26
+
27
+ export type NewFile = typeof files.$inferInsert;
28
+ export type FileItem = typeof files.$inferSelect;
@@ -0,0 +1,6 @@
1
+ export * from './chat';
2
+ export * from './discover';
3
+ export * from './file';
4
+ export * from './nextauth';
5
+ export * from './relations';
6
+ export * from './user';
@@ -1,8 +1,7 @@
1
- // ======= nextauth ======= //
2
1
  import { boolean, integer, pgTable, primaryKey, text, timestamp } from 'drizzle-orm/pg-core';
3
2
  import { AdapterAccount } from 'next-auth/adapters';
4
3
 
5
- import { users } from '@/database/server/schemas/lobechat';
4
+ import { users } from './user';
6
5
 
7
6
  /**
8
7
  * This table stores nextauth accounts. This is used to link users to their sso profiles.
@@ -0,0 +1,138 @@
1
+ /* eslint-disable sort-keys-fix/sort-keys-fix */
2
+ import { relations } from 'drizzle-orm';
3
+
4
+ import {
5
+ agents,
6
+ agentsToSessions,
7
+ filesToAgents,
8
+ filesToMessages,
9
+ filesToSessions,
10
+ messages,
11
+ sessionGroups,
12
+ sessions,
13
+ topics,
14
+ } from './chat';
15
+ import { agentsTags, plugins, pluginsTags, tags } from './discover';
16
+ import { files } from './file';
17
+
18
+ export const filesRelations = relations(files, ({ many }) => ({
19
+ filesToMessages: many(filesToMessages),
20
+ filesToSessions: many(filesToSessions),
21
+ filesToAgents: many(filesToAgents),
22
+ }));
23
+
24
+ export const topicRelations = relations(topics, ({ one }) => ({
25
+ session: one(sessions, {
26
+ fields: [topics.sessionId],
27
+ references: [sessions.id],
28
+ }),
29
+ }));
30
+
31
+ export const pluginsRelations = relations(plugins, ({ many }) => ({
32
+ pluginsTags: many(pluginsTags),
33
+ }));
34
+
35
+ export const pluginsTagsRelations = relations(pluginsTags, ({ one }) => ({
36
+ plugin: one(plugins, {
37
+ fields: [pluginsTags.pluginId],
38
+ references: [plugins.id],
39
+ }),
40
+ tag: one(tags, {
41
+ fields: [pluginsTags.tagId],
42
+ references: [tags.id],
43
+ }),
44
+ }));
45
+
46
+ export const tagsRelations = relations(tags, ({ many }) => ({
47
+ agentsTags: many(agentsTags),
48
+ pluginsTags: many(pluginsTags),
49
+ }));
50
+
51
+ export const messagesRelations = relations(messages, ({ many, one }) => ({
52
+ filesToMessages: many(filesToMessages),
53
+
54
+ session: one(sessions, {
55
+ fields: [messages.sessionId],
56
+ references: [sessions.id],
57
+ }),
58
+
59
+ parent: one(messages, {
60
+ fields: [messages.parentId],
61
+ references: [messages.id],
62
+ }),
63
+
64
+ topic: one(topics, {
65
+ fields: [messages.topicId],
66
+ references: [topics.id],
67
+ }),
68
+ }));
69
+
70
+ export const agentsRelations = relations(agents, ({ many }) => ({
71
+ agentsToSessions: many(agentsToSessions),
72
+ filesToAgents: many(filesToAgents),
73
+ agentsTags: many(agentsTags),
74
+ }));
75
+
76
+ export const agentsToSessionsRelations = relations(agentsToSessions, ({ one }) => ({
77
+ session: one(sessions, {
78
+ fields: [agentsToSessions.sessionId],
79
+ references: [sessions.id],
80
+ }),
81
+ agent: one(agents, {
82
+ fields: [agentsToSessions.agentId],
83
+ references: [agents.id],
84
+ }),
85
+ }));
86
+
87
+ export const filesToAgentsRelations = relations(filesToAgents, ({ one }) => ({
88
+ agent: one(agents, {
89
+ fields: [filesToAgents.agentId],
90
+ references: [agents.id],
91
+ }),
92
+ file: one(files, {
93
+ fields: [filesToAgents.fileId],
94
+ references: [files.id],
95
+ }),
96
+ }));
97
+
98
+ export const filesToMessagesRelations = relations(filesToMessages, ({ one }) => ({
99
+ file: one(files, {
100
+ fields: [filesToMessages.fileId],
101
+ references: [files.id],
102
+ }),
103
+ message: one(messages, {
104
+ fields: [filesToMessages.messageId],
105
+ references: [messages.id],
106
+ }),
107
+ }));
108
+
109
+ export const filesToSessionsRelations = relations(filesToSessions, ({ one }) => ({
110
+ file: one(files, {
111
+ fields: [filesToSessions.fileId],
112
+ references: [files.id],
113
+ }),
114
+ session: one(sessions, {
115
+ fields: [filesToSessions.sessionId],
116
+ references: [sessions.id],
117
+ }),
118
+ }));
119
+
120
+ export const agentsTagsRelations = relations(agentsTags, ({ one }) => ({
121
+ agent: one(agents, {
122
+ fields: [agentsTags.agentId],
123
+ references: [agents.id],
124
+ }),
125
+ tag: one(tags, {
126
+ fields: [agentsTags.tagId],
127
+ references: [tags.id],
128
+ }),
129
+ }));
130
+
131
+ export const sessionsRelations = relations(sessions, ({ many, one }) => ({
132
+ filesToSessions: many(filesToSessions),
133
+ agentsToSessions: many(agentsToSessions),
134
+ group: one(sessionGroups, {
135
+ fields: [sessions.groupId],
136
+ references: [sessionGroups.id],
137
+ }),
138
+ }));
@@ -0,0 +1,111 @@
1
+ /* eslint-disable sort-keys-fix/sort-keys-fix */
2
+ import {
3
+ boolean,
4
+ integer,
5
+ jsonb,
6
+ pgTable,
7
+ text,
8
+ } from 'drizzle-orm/pg-core';
9
+
10
+ import { DEFAULT_PREFERENCE } from '@/const/user';
11
+
12
+ import { createdAt, timestamptz, updatedAt } from './_helpers';
13
+
14
+ /**
15
+ * This table stores users. Users are created in Clerk, then Clerk calls a
16
+ * webhook at /api/webhook/clerk to inform this application a user was created.
17
+ */
18
+ export const users = pgTable('users', {
19
+ // The ID will be the user's ID from Clerk
20
+ id: text('id').primaryKey().notNull(),
21
+ username: text('username').unique(),
22
+ email: text('email'),
23
+
24
+ avatar: text('avatar'),
25
+ phone: text('phone'),
26
+ firstName: text('first_name'),
27
+ lastName: text('last_name'),
28
+ fullName: text('full_name'),
29
+
30
+ isOnboarded: boolean('is_onboarded').default(false),
31
+ // Time user was created in Clerk
32
+ clerkCreatedAt: timestamptz('clerk_created_at'),
33
+
34
+ // Required by nextauth, all null allowed
35
+ emailVerifiedAt: timestamptz('email_verified_at'),
36
+
37
+ preference: jsonb('preference').$defaultFn(() => DEFAULT_PREFERENCE),
38
+
39
+ createdAt: createdAt(),
40
+ updatedAt: updatedAt(),
41
+ });
42
+
43
+ export type NewUser = typeof users.$inferInsert;
44
+ export type UserItem = typeof users.$inferSelect;
45
+
46
+ export const userSubscriptions = pgTable('user_subscriptions', {
47
+ id: text('id').primaryKey().notNull(),
48
+ userId: text('user_id')
49
+ .references(() => users.id, { onDelete: 'cascade' })
50
+ .notNull(),
51
+ stripeId: text('stripe_id'),
52
+
53
+ currency: text('currency'),
54
+ pricing: integer('pricing'),
55
+ billingPaidAt: integer('billing_paid_at'),
56
+ billingCycleStart: integer('billing_cycle_start'),
57
+ billingCycleEnd: integer('billing_cycle_end'),
58
+
59
+ cancelAtPeriodEnd: boolean('cancel_at_period_end'),
60
+ cancelAt: integer('cancel_at'),
61
+
62
+ nextBilling: jsonb('next_billing'),
63
+
64
+ plan: text('plan'),
65
+ recurring: text('recurring'),
66
+
67
+ storageLimit: integer('storage_limit'),
68
+
69
+ status: integer('status'),
70
+ createdAt: createdAt(),
71
+ updatedAt: updatedAt(),
72
+ });
73
+
74
+ export type NewUserSubscription = typeof userSubscriptions.$inferInsert;
75
+ export type UserSubscriptionItem = typeof userSubscriptions.$inferSelect;
76
+
77
+ export const userBudgets = pgTable('user_budgets', {
78
+ id: text('id')
79
+ .primaryKey()
80
+ .references(() => users.id, { onDelete: 'cascade' })
81
+ .notNull(),
82
+
83
+ freeBudgetId: text('free_budget_id'),
84
+ freeBudgetKey: text('free_budget_key'),
85
+
86
+ subscriptionBudgetId: text('subscription_budget_id'),
87
+ subscriptionBudgetKey: text('subscription_budget_key'),
88
+
89
+ packageBudgetId: text('package_budget_id'),
90
+ packageBudgetKey: text('package_budget_key'),
91
+
92
+ createdAt: createdAt(),
93
+ updatedAt: updatedAt(),
94
+ });
95
+
96
+ export type NewUserBudgets = typeof userBudgets.$inferInsert;
97
+ export type UserBudgetItem = typeof userBudgets.$inferSelect;
98
+
99
+ export const userSettings = pgTable('user_settings', {
100
+ id: text('id')
101
+ .references(() => users.id, { onDelete: 'cascade' })
102
+ .primaryKey(),
103
+
104
+ tts: jsonb('tts'),
105
+ keyVaults: text('key_vaults'),
106
+ general: jsonb('general'),
107
+ languageModel: jsonb('language_model'),
108
+ systemAgent: jsonb('system_agent'),
109
+ defaultAgent: jsonb('default_agent'),
110
+ tool: jsonb('tool'),
111
+ });
@@ -1,15 +0,0 @@
1
- // refs: https://unkey.dev/blog/uuid-ux
2
-
3
- // If I have 100 million users, each generating up to 1 million messages.
4
- // Then the total number of IDs that need to be generated: 100 million × 1 million = 10^14 (100 trillion)
5
- // 11-digit Nano ID: 36^11 ≈ 1.3 × 10^17 (130 trillion trillion)
6
-
7
- export const FILE_ID_LENGTH = 19; // 5 prefix + 14 random, e.g. file_ydGX5gmaxL32fh
8
-
9
- export const MESSAGE_ID_LENGTH = 18; // 4 prefix + 14 random, e.g. msg_GX5ymaxL3d2ds2
10
-
11
- export const SESSION_ID_LENGTH = 16; // 4 prefix + 12 random, e.g. ssn_GX5y3d2dmaxL
12
-
13
- export const TOPIC_ID_LENGTH = 16; // 4 prefix + 12 random, e.g. tpc_GX5ymd7axL3y
14
-
15
- export const USER_ID_LENGTH = 14; // 4 prefix + 10 random, e.g. user_GXyxLmd75a