@lobehub/chat 1.9.2 → 1.9.3
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 +25 -0
- package/drizzle.config.ts +1 -1
- package/package.json +1 -1
- package/src/database/server/schemas/lobechat/_helpers.ts +6 -0
- package/src/database/server/schemas/{lobechat.ts → lobechat/chat.ts} +4 -335
- package/src/database/server/schemas/lobechat/discover.ts +84 -0
- package/src/database/server/schemas/lobechat/file.ts +28 -0
- package/src/database/server/schemas/lobechat/index.ts +6 -0
- package/src/database/server/schemas/{nextauth.ts → lobechat/nextauth.ts} +1 -2
- package/src/database/server/schemas/lobechat/relations.ts +138 -0
- package/src/database/server/schemas/lobechat/user.ts +111 -0
- package/src/database/server/schemas/_id.ts +0 -15
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 1.9.3](https://github.com/lobehub/lobe-chat/compare/v1.9.2...v1.9.3)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-08-06**</sup>
|
|
8
|
+
|
|
9
|
+
#### ♻ Code Refactoring
|
|
10
|
+
|
|
11
|
+
- **misc**: Refactor server db schema for better code organize.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Code refactoring
|
|
19
|
+
|
|
20
|
+
- **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))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
5
30
|
### [Version 1.9.2](https://github.com/lobehub/lobe-chat/compare/v1.9.1...v1.9.2)
|
|
6
31
|
|
|
7
32
|
<sup>Released on **2024-08-05**</sup>
|
package/drizzle.config.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.3",
|
|
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",
|
|
@@ -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 '
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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;
|
|
@@ -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 '
|
|
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
|