@lobehub/lobehub 2.0.0-next.374 → 2.0.0-next.376

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.
Files changed (118) hide show
  1. package/.github/workflows/claude-migration-support.yml +1 -1
  2. package/.github/workflows/revalidate-docs.yml +25 -0
  3. package/CHANGELOG.md +66 -0
  4. package/apps/desktop/src/main/controllers/LocalFileCtr.ts +7 -1
  5. package/apps/desktop/src/main/controllers/ShellCommandCtr.ts +23 -10
  6. package/apps/desktop/src/main/controllers/__tests__/LocalFileCtr.test.ts +261 -0
  7. package/apps/desktop/src/main/controllers/__tests__/ShellCommandCtr.test.ts +36 -0
  8. package/apps/desktop/src/main/core/infrastructure/BackendProxyProtocolManager.ts +2 -1
  9. package/changelog/v1.json +21 -0
  10. package/docs/development/database-schema.dbml +89 -0
  11. package/docs/self-hosting/advanced/auth/nextauth-to-betterauth.mdx +6 -0
  12. package/docs/self-hosting/advanced/auth/nextauth-to-betterauth.zh-CN.mdx +5 -0
  13. package/docs/usage/features/auth.mdx +54 -33
  14. package/docs/usage/features/auth.zh-CN.mdx +56 -33
  15. package/locales/en-US/chat.json +13 -13
  16. package/locales/en-US/common.json +24 -0
  17. package/locales/en-US/setting.json +19 -0
  18. package/locales/zh-CN/authError.json +2 -0
  19. package/locales/zh-CN/chat.json +14 -14
  20. package/locales/zh-CN/common.json +24 -0
  21. package/locales/zh-CN/setting.json +19 -0
  22. package/package.json +2 -1
  23. package/packages/builtin-tool-group-agent-builder/src/ExecutionRuntime/index.ts +31 -9
  24. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/InviteAgent/index.tsx +28 -12
  25. package/packages/builtin-tool-group-agent-builder/src/client/Inspector/RemoveAgent/index.tsx +28 -12
  26. package/packages/builtin-tool-group-agent-builder/src/types.ts +8 -0
  27. package/packages/builtin-tool-local-system/src/client/Render/EditLocalFile/index.tsx +1 -11
  28. package/packages/builtin-tool-local-system/src/client/Render/ListFiles/index.tsx +6 -11
  29. package/packages/context-engine/src/engine/tools/ToolsEngine.ts +16 -10
  30. package/packages/context-engine/src/engine/tools/__tests__/ToolsEngine.test.ts +142 -0
  31. package/packages/context-engine/src/engine/tools/types.ts +6 -0
  32. package/packages/database/migrations/0074_add_fk_indexes_for_cascade_delete.sql +56 -0
  33. package/packages/database/migrations/meta/0074_snapshot.json +10901 -0
  34. package/packages/database/migrations/meta/_journal.json +7 -0
  35. package/packages/database/src/models/message.ts +84 -81
  36. package/packages/database/src/repositories/search/index.ts +330 -570
  37. package/packages/database/src/schemas/agent.ts +4 -0
  38. package/packages/database/src/schemas/chatGroup.ts +2 -0
  39. package/packages/database/src/schemas/file.ts +4 -0
  40. package/packages/database/src/schemas/generation.ts +1 -0
  41. package/packages/database/src/schemas/message.ts +16 -0
  42. package/packages/database/src/schemas/nextauth.ts +15 -8
  43. package/packages/database/src/schemas/oidc.ts +104 -68
  44. package/packages/database/src/schemas/rag.ts +4 -0
  45. package/packages/database/src/schemas/ragEvals.ts +97 -73
  46. package/packages/database/src/schemas/relations.ts +7 -0
  47. package/packages/database/src/schemas/session.ts +1 -0
  48. package/packages/database/src/schemas/topic.ts +8 -1
  49. package/packages/desktop-bridge/src/index.ts +17 -0
  50. package/scripts/_shared/checkDeprecatedAuth.js +26 -0
  51. package/src/app/(backend)/trpc/async/[trpc]/route.ts +2 -0
  52. package/src/app/(backend)/trpc/lambda/[trpc]/route.ts +2 -5
  53. package/src/app/(backend)/trpc/mobile/[trpc]/route.ts +2 -5
  54. package/src/app/(backend)/trpc/tools/[trpc]/route.ts +2 -0
  55. package/src/app/[variants]/(auth)/signup/[[...signup]]/useSignUp.tsx +7 -4
  56. package/src/app/[variants]/(main)/agent/features/Conversation/AgentWelcome/index.tsx +3 -23
  57. package/src/app/[variants]/(main)/group/features/Conversation/AgentWelcome/index.tsx +3 -23
  58. package/src/app/[variants]/(main)/resource/(home)/index.tsx +4 -1
  59. package/src/app/[variants]/(main)/resource/library/_layout/Header/LibraryHead.tsx +3 -0
  60. package/src/app/[variants]/(main)/resource/library/_layout/Header/index.tsx +2 -1
  61. package/src/app/[variants]/(main)/settings/storage/features/Advanced.tsx +19 -12
  62. package/src/app/[variants]/(main)/settings/storage/index.tsx +19 -1
  63. package/src/business/client/features/AccountDeletion/index.tsx +3 -0
  64. package/src/business/server/lambda-routers/accountDeletion.ts +3 -0
  65. package/src/components/DragUpload/index.tsx +1 -1
  66. package/src/config/routes/index.ts +9 -1
  67. package/src/features/CommandMenu/ContextCommands.tsx +10 -2
  68. package/src/features/CommandMenu/MainMenu.tsx +29 -22
  69. package/src/features/CommandMenu/SearchResults.tsx +19 -0
  70. package/src/features/CommandMenu/components/CommandInput.tsx +1 -0
  71. package/src/features/CommandMenu/index.tsx +25 -3
  72. package/src/features/CommandMenu/styles.ts +1 -0
  73. package/src/features/CommandMenu/useCommandMenu.ts +8 -2
  74. package/src/features/CommandMenu/utils/contextCommands.ts +17 -2
  75. package/src/features/CommandMenu/utils/queryParser.ts +1 -0
  76. package/src/features/Conversation/ChatItem/ChatItem.tsx +4 -7
  77. package/src/features/Conversation/ChatItem/style.ts +0 -3
  78. package/src/features/Conversation/ChatItem/type.ts +4 -1
  79. package/src/features/Conversation/Messages/Assistant/index.tsx +6 -2
  80. package/src/features/Conversation/Messages/AssistantGroup/index.tsx +8 -3
  81. package/src/features/Conversation/Messages/Supervisor/index.tsx +6 -2
  82. package/src/features/Conversation/Messages/Task/index.tsx +6 -2
  83. package/src/features/Conversation/Messages/components/useNewScreen.test.ts +331 -0
  84. package/src/features/Conversation/Messages/components/useNewScreen.ts +80 -5
  85. package/src/features/Electron/connection/Connection.tsx +20 -15
  86. package/src/features/FileViewer/index.tsx +28 -5
  87. package/src/features/ModelSwitchPanel/components/List/ListItemRenderer.tsx +10 -9
  88. package/src/features/ModelSwitchPanel/components/List/MultipleProvidersModelItem.tsx +1 -0
  89. package/src/features/ModelSwitchPanel/components/Toolbar.tsx +1 -1
  90. package/src/features/ResourceManager/components/Editor/index.tsx +7 -4
  91. package/src/features/ResourceManager/components/Explorer/Header/index.tsx +1 -1
  92. package/src/features/ResourceManager/components/Explorer/ItemDropdown/useFileItemDropdown.tsx +12 -1
  93. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +23 -43
  94. package/src/features/ResourceManager/components/Explorer/MasonryView/MasonryFileItem/ImageFileItem.tsx +1 -0
  95. package/src/features/ResourceManager/components/Explorer/MasonryView/MasonryFileItem/index.tsx +24 -44
  96. package/src/features/ResourceManager/components/Explorer/hooks/useFileItemClick.ts +78 -0
  97. package/src/features/ResourceManager/components/Header/AddButton.tsx +0 -5
  98. package/src/features/ResourceManager/index.tsx +38 -24
  99. package/src/libs/better-auth/define-config.ts +17 -0
  100. package/src/libs/better-auth/plugins/email-whitelist.ts +4 -1
  101. package/src/libs/redis/manager.ts +5 -9
  102. package/src/libs/trpc/utils/responseMeta.test.ts +82 -0
  103. package/src/libs/trpc/utils/responseMeta.ts +41 -0
  104. package/src/locales/default/authError.ts +3 -0
  105. package/src/locales/default/chat.ts +13 -13
  106. package/src/locales/default/common.ts +82 -4
  107. package/src/locales/default/setting.ts +23 -1
  108. package/src/server/modules/AgentRuntime/redis.ts +3 -0
  109. package/src/server/routers/lambda/index.ts +2 -0
  110. package/src/server/routers/lambda/search.ts +3 -2
  111. package/src/services/chat/chat.test.ts +125 -45
  112. package/src/services/chat/index.ts +10 -14
  113. package/src/services/chat/mecha/agentConfigResolver.ts +8 -0
  114. package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +29 -0
  115. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +27 -19
  116. package/src/utils/errorResponse.ts +2 -1
  117. package/src/app/[variants]/(main)/agent/features/Conversation/AgentWelcome/AddButton.tsx +0 -37
  118. package/src/app/[variants]/(main)/group/features/Conversation/AgentWelcome/AddButton.tsx +0 -32
@@ -105,6 +105,8 @@ export const agentsKnowledgeBases = pgTable(
105
105
  (t) => [
106
106
  primaryKey({ columns: [t.agentId, t.knowledgeBaseId] }),
107
107
  index('agents_knowledge_bases_agent_id_idx').on(t.agentId),
108
+ index('agents_knowledge_bases_knowledge_base_id_idx').on(t.knowledgeBaseId),
109
+ index('agents_knowledge_bases_user_id_idx').on(t.userId),
108
110
  ],
109
111
  );
110
112
 
@@ -127,5 +129,7 @@ export const agentsFiles = pgTable(
127
129
  (t) => [
128
130
  primaryKey({ columns: [t.fileId, t.agentId, t.userId] }),
129
131
  index('agents_files_agent_id_idx').on(t.agentId),
132
+ index('agents_files_file_id_idx').on(t.fileId),
133
+ index('agents_files_user_id_idx').on(t.userId),
130
134
  ],
131
135
  );
@@ -52,6 +52,7 @@ export const chatGroups = pgTable(
52
52
  },
53
53
  (t) => [
54
54
  uniqueIndex('chat_groups_client_id_user_id_unique').on(t.clientId, t.userId),
55
+ index('chat_groups_user_id_idx').on(t.userId),
55
56
  index('chat_groups_group_id_idx').on(t.groupId),
56
57
  ],
57
58
  );
@@ -95,6 +96,7 @@ export const chatGroupsAgents = pgTable(
95
96
  },
96
97
  (t) => ({
97
98
  pk: primaryKey({ columns: [t.chatGroupId, t.agentId] }),
99
+ userIdIdx: index('chat_groups_agents_user_id_idx').on(t.userId),
98
100
  }),
99
101
  );
100
102
 
@@ -166,6 +166,8 @@ export const files = pgTable(
166
166
  fileHashIdx: index('file_hash_idx').on(table.fileHash),
167
167
  userIdIdx: index('files_user_id_idx').on(table.userId),
168
168
  parentIdIdx: index('files_parent_id_idx').on(table.parentId),
169
+ chunkTaskIdIdx: index('files_chunk_task_id_idx').on(table.chunkTaskId),
170
+ embeddingTaskIdIdx: index('files_embedding_task_id_idx').on(table.embeddingTaskId),
169
171
  clientIdUnique: uniqueIndex('files_client_id_user_id_unique').on(
170
172
  table.clientId,
171
173
  table.userId,
@@ -231,5 +233,7 @@ export const knowledgeBaseFiles = pgTable(
231
233
  (t) => [
232
234
  primaryKey({ columns: [t.knowledgeBaseId, t.fileId] }),
233
235
  index('knowledge_base_files_kb_id_idx').on(t.knowledgeBaseId),
236
+ index('knowledge_base_files_user_id_idx').on(t.userId),
237
+ index('knowledge_base_files_file_id_idx').on(t.fileId),
234
238
  ],
235
239
  );
@@ -134,6 +134,7 @@ export const generations = pgTable(
134
134
  (t) => [
135
135
  index('generations_user_id_idx').on(t.userId),
136
136
  index('generations_batch_id_idx').on(t.generationBatchId),
137
+ index('generations_file_id_idx').on(t.fileId),
137
138
  ],
138
139
  );
139
140
 
@@ -70,8 +70,11 @@ export const messageGroups = pgTable(
70
70
  },
71
71
  (t) => [
72
72
  uniqueIndex('message_groups_client_id_user_id_unique').on(t.clientId, t.userId),
73
+ index('message_groups_user_id_idx').on(t.userId),
73
74
  index('message_groups_topic_id_idx').on(t.topicId),
74
75
  index('message_groups_type_idx').on(t.type),
76
+ index('message_groups_parent_group_id_idx').on(t.parentGroupId),
77
+ index('message_groups_parent_message_id_idx').on(t.parentMessageId),
75
78
  ],
76
79
  );
77
80
 
@@ -174,6 +177,7 @@ export const messagePlugins = pgTable(
174
177
  },
175
178
  (t) => [
176
179
  uniqueIndex('message_plugins_client_id_user_id_unique').on(t.clientId, t.userId),
180
+ index('message_plugins_user_id_idx').on(t.userId),
177
181
  index('message_plugins_tool_call_id_idx').on(t.toolCallId),
178
182
  ],
179
183
  );
@@ -194,6 +198,7 @@ export const messageTTS = pgTable(
194
198
  },
195
199
  (t) => ({
196
200
  clientIdUnique: uniqueIndex('message_tts_client_id_user_id_unique').on(t.clientId, t.userId),
201
+ userIdIdx: index('message_tts_user_id_idx').on(t.userId),
197
202
  }),
198
203
  );
199
204
 
@@ -216,6 +221,7 @@ export const messageTranslates = pgTable(
216
221
  t.clientId,
217
222
  t.userId,
218
223
  ),
224
+ userIdIdx: index('message_translates_user_id_idx').on(t.userId),
219
225
  }),
220
226
  );
221
227
 
@@ -236,6 +242,8 @@ export const messagesFiles = pgTable(
236
242
  },
237
243
  (t) => ({
238
244
  pk: primaryKey({ columns: [t.fileId, t.messageId] }),
245
+ userIdIdx: index('messages_files_user_id_idx').on(t.userId),
246
+ messageIdIdx: index('messages_files_message_id_idx').on(t.messageId),
239
247
  }),
240
248
  );
241
249
 
@@ -259,6 +267,9 @@ export const messageQueries = pgTable(
259
267
  t.clientId,
260
268
  t.userId,
261
269
  ),
270
+ userIdIdx: index('message_queries_user_id_idx').on(t.userId),
271
+ messageIdIdx: index('message_queries_message_id_idx').on(t.messageId),
272
+ embeddingsIdIdx: index('message_queries_embeddings_id_idx').on(t.embeddingsId),
262
273
  }),
263
274
  );
264
275
 
@@ -277,6 +288,9 @@ export const messageQueryChunks = pgTable(
277
288
  },
278
289
  (t) => ({
279
290
  pk: primaryKey({ columns: [t.chunkId, t.messageId, t.queryId] }),
291
+ userIdIdx: index('message_query_chunks_user_id_idx').on(t.userId),
292
+ messageIdIdx: index('message_query_chunks_message_id_idx').on(t.messageId),
293
+ queryIdIdx: index('message_query_chunks_query_id_idx').on(t.queryId),
280
294
  }),
281
295
  );
282
296
  export type NewMessageFileChunk = typeof messageQueryChunks.$inferInsert;
@@ -294,5 +308,7 @@ export const messageChunks = pgTable(
294
308
  },
295
309
  (t) => ({
296
310
  pk: primaryKey({ columns: [t.chunkId, t.messageId] }),
311
+ userIdIdx: index('message_chunks_user_id_idx').on(t.userId),
312
+ messageIdIdx: index('message_chunks_message_id_idx').on(t.messageId),
297
313
  }),
298
314
  );
@@ -1,4 +1,4 @@
1
- import { boolean, integer, pgTable, primaryKey, text, timestamp } from 'drizzle-orm/pg-core';
1
+ import { boolean, index, integer, pgTable, primaryKey, text, timestamp } from 'drizzle-orm/pg-core';
2
2
 
3
3
  import { users } from './user';
4
4
 
@@ -33,6 +33,7 @@ export const nextauthAccounts = pgTable(
33
33
  compositePk: primaryKey({
34
34
  columns: [account.provider, account.providerAccountId],
35
35
  }),
36
+ userIdIdx: index('nextauth_accounts_user_id_idx').on(account.userId),
36
37
  }),
37
38
  );
38
39
 
@@ -42,13 +43,19 @@ export const nextauthAccounts = pgTable(
42
43
  * which will enable remote logout and other features.
43
44
  * @see {@link https://authjs.dev/guides/creating-a-database-adapter#database-session-management | NextAuth Doc}
44
45
  */
45
- export const nextauthSessions = pgTable(`nextauth_sessions`, {
46
- expires: timestamp('expires', { mode: 'date' }).notNull(),
47
- sessionToken: text('sessionToken').primaryKey(),
48
- userId: text('user_id')
49
- .notNull()
50
- .references(() => users.id, { onDelete: 'cascade' }),
51
- });
46
+ export const nextauthSessions = pgTable(
47
+ `nextauth_sessions`,
48
+ {
49
+ expires: timestamp('expires', { mode: 'date' }).notNull(),
50
+ sessionToken: text('sessionToken').primaryKey(),
51
+ userId: text('user_id')
52
+ .notNull()
53
+ .references(() => users.id, { onDelete: 'cascade' }),
54
+ },
55
+ (t) => ({
56
+ userIdIdx: index('nextauth_sessions_user_id_idx').on(t.userId),
57
+ }),
58
+ );
52
59
 
53
60
  /**
54
61
  * @description This table stores nextauth verification tokens.
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix */
2
- import { boolean, jsonb, pgTable, primaryKey, text, varchar } from 'drizzle-orm/pg-core';
2
+ import { boolean, index, jsonb, pgTable, primaryKey, text, varchar } from 'drizzle-orm/pg-core';
3
3
  import { createInsertSchema, createSelectSchema } from 'drizzle-zod';
4
4
 
5
5
  import { timestamps, timestamptz } from './_helpers';
@@ -9,68 +9,92 @@ import { users } from './user';
9
9
  * OIDC authorization code
10
10
  * One of the models that oidc-provider needs to persist
11
11
  */
12
- export const oidcAuthorizationCodes = pgTable('oidc_authorization_codes', {
13
- id: varchar('id', { length: 255 }).primaryKey(),
14
- data: jsonb('data').notNull(),
15
- expiresAt: timestamptz('expires_at').notNull(),
16
- consumedAt: timestamptz('consumed_at'),
17
- userId: text('user_id')
18
- .references(() => users.id, { onDelete: 'cascade' })
19
- .notNull(),
20
- clientId: varchar('client_id', { length: 255 }).notNull(),
21
- grantId: varchar('grant_id', { length: 255 }),
22
- ...timestamps,
23
- });
12
+ export const oidcAuthorizationCodes = pgTable(
13
+ 'oidc_authorization_codes',
14
+ {
15
+ id: varchar('id', { length: 255 }).primaryKey(),
16
+ data: jsonb('data').notNull(),
17
+ expiresAt: timestamptz('expires_at').notNull(),
18
+ consumedAt: timestamptz('consumed_at'),
19
+ userId: text('user_id')
20
+ .references(() => users.id, { onDelete: 'cascade' })
21
+ .notNull(),
22
+ clientId: varchar('client_id', { length: 255 }).notNull(),
23
+ grantId: varchar('grant_id', { length: 255 }),
24
+ ...timestamps,
25
+ },
26
+ (t) => ({
27
+ userIdIdx: index('oidc_authorization_codes_user_id_idx').on(t.userId),
28
+ }),
29
+ );
24
30
 
25
31
  /**
26
32
  * OIDC access token
27
33
  * One of the models that oidc-provider needs to persist
28
34
  */
29
- export const oidcAccessTokens = pgTable('oidc_access_tokens', {
30
- id: varchar('id', { length: 255 }).primaryKey(),
31
- data: jsonb('data').notNull(),
32
- expiresAt: timestamptz('expires_at').notNull(),
33
- consumedAt: timestamptz('consumed_at'),
34
- userId: text('user_id')
35
- .references(() => users.id, { onDelete: 'cascade' })
36
- .notNull(),
37
- clientId: varchar('client_id', { length: 255 }).notNull(),
38
- grantId: varchar('grant_id', { length: 255 }),
39
- ...timestamps,
40
- });
35
+ export const oidcAccessTokens = pgTable(
36
+ 'oidc_access_tokens',
37
+ {
38
+ id: varchar('id', { length: 255 }).primaryKey(),
39
+ data: jsonb('data').notNull(),
40
+ expiresAt: timestamptz('expires_at').notNull(),
41
+ consumedAt: timestamptz('consumed_at'),
42
+ userId: text('user_id')
43
+ .references(() => users.id, { onDelete: 'cascade' })
44
+ .notNull(),
45
+ clientId: varchar('client_id', { length: 255 }).notNull(),
46
+ grantId: varchar('grant_id', { length: 255 }),
47
+ ...timestamps,
48
+ },
49
+ (t) => ({
50
+ userIdIdx: index('oidc_access_tokens_user_id_idx').on(t.userId),
51
+ }),
52
+ );
41
53
 
42
54
  /**
43
55
  * OIDC refresh token
44
56
  * One of the models that oidc-provider needs to persist
45
57
  */
46
- export const oidcRefreshTokens = pgTable('oidc_refresh_tokens', {
47
- id: varchar('id', { length: 255 }).primaryKey(),
48
- data: jsonb('data').notNull(),
49
- expiresAt: timestamptz('expires_at').notNull(),
50
- consumedAt: timestamptz('consumed_at'),
51
- userId: text('user_id')
52
- .references(() => users.id, { onDelete: 'cascade' })
53
- .notNull(),
54
- clientId: varchar('client_id', { length: 255 }).notNull(),
55
- grantId: varchar('grant_id', { length: 255 }),
56
- ...timestamps,
57
- });
58
+ export const oidcRefreshTokens = pgTable(
59
+ 'oidc_refresh_tokens',
60
+ {
61
+ id: varchar('id', { length: 255 }).primaryKey(),
62
+ data: jsonb('data').notNull(),
63
+ expiresAt: timestamptz('expires_at').notNull(),
64
+ consumedAt: timestamptz('consumed_at'),
65
+ userId: text('user_id')
66
+ .references(() => users.id, { onDelete: 'cascade' })
67
+ .notNull(),
68
+ clientId: varchar('client_id', { length: 255 }).notNull(),
69
+ grantId: varchar('grant_id', { length: 255 }),
70
+ ...timestamps,
71
+ },
72
+ (t) => ({
73
+ userIdIdx: index('oidc_refresh_tokens_user_id_idx').on(t.userId),
74
+ }),
75
+ );
58
76
 
59
77
  /**
60
78
  * OIDC device code
61
79
  * One of the models that oidc-provider needs to persist
62
80
  */
63
- export const oidcDeviceCodes = pgTable('oidc_device_codes', {
64
- id: varchar('id', { length: 255 }).primaryKey(),
65
- data: jsonb('data').notNull(),
66
- expiresAt: timestamptz('expires_at').notNull(),
67
- consumedAt: timestamptz('consumed_at'),
68
- userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
69
- clientId: varchar('client_id', { length: 255 }).notNull(),
70
- grantId: varchar('grant_id', { length: 255 }),
71
- userCode: varchar('user_code', { length: 255 }),
72
- ...timestamps,
73
- });
81
+ export const oidcDeviceCodes = pgTable(
82
+ 'oidc_device_codes',
83
+ {
84
+ id: varchar('id', { length: 255 }).primaryKey(),
85
+ data: jsonb('data').notNull(),
86
+ expiresAt: timestamptz('expires_at').notNull(),
87
+ consumedAt: timestamptz('consumed_at'),
88
+ userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
89
+ clientId: varchar('client_id', { length: 255 }).notNull(),
90
+ grantId: varchar('grant_id', { length: 255 }),
91
+ userCode: varchar('user_code', { length: 255 }),
92
+ ...timestamps,
93
+ },
94
+ (t) => ({
95
+ userIdIdx: index('oidc_device_codes_user_id_idx').on(t.userId),
96
+ }),
97
+ );
74
98
 
75
99
  /**
76
100
  * OIDC interaction session
@@ -87,17 +111,23 @@ export const oidcInteractions = pgTable('oidc_interactions', {
87
111
  * OIDC grant record
88
112
  * One of the models that oidc-provider needs to persist
89
113
  */
90
- export const oidcGrants = pgTable('oidc_grants', {
91
- id: varchar('id', { length: 255 }).primaryKey(),
92
- data: jsonb('data').notNull(),
93
- expiresAt: timestamptz('expires_at').notNull(),
94
- consumedAt: timestamptz('consumed_at'),
95
- userId: text('user_id')
96
- .references(() => users.id, { onDelete: 'cascade' })
97
- .notNull(),
98
- clientId: varchar('client_id', { length: 255 }).notNull(),
99
- ...timestamps,
100
- });
114
+ export const oidcGrants = pgTable(
115
+ 'oidc_grants',
116
+ {
117
+ id: varchar('id', { length: 255 }).primaryKey(),
118
+ data: jsonb('data').notNull(),
119
+ expiresAt: timestamptz('expires_at').notNull(),
120
+ consumedAt: timestamptz('consumed_at'),
121
+ userId: text('user_id')
122
+ .references(() => users.id, { onDelete: 'cascade' })
123
+ .notNull(),
124
+ clientId: varchar('client_id', { length: 255 }).notNull(),
125
+ ...timestamps,
126
+ },
127
+ (t) => ({
128
+ userIdIdx: index('oidc_grants_user_id_idx').on(t.userId),
129
+ }),
130
+ );
101
131
 
102
132
  /**
103
133
  * OIDC client configuration
@@ -126,15 +156,21 @@ export const oidcClients = pgTable('oidc_clients', {
126
156
  * OIDC session
127
157
  * One of the models that oidc-provider needs to persist
128
158
  */
129
- export const oidcSessions = pgTable('oidc_sessions', {
130
- id: varchar('id', { length: 255 }).primaryKey(),
131
- data: jsonb('data').notNull(),
132
- expiresAt: timestamptz('expires_at').notNull(),
133
- userId: text('user_id')
134
- .references(() => users.id, { onDelete: 'cascade' })
135
- .notNull(),
136
- ...timestamps,
137
- });
159
+ export const oidcSessions = pgTable(
160
+ 'oidc_sessions',
161
+ {
162
+ id: varchar('id', { length: 255 }).primaryKey(),
163
+ data: jsonb('data').notNull(),
164
+ expiresAt: timestamptz('expires_at').notNull(),
165
+ userId: text('user_id')
166
+ .references(() => users.id, { onDelete: 'cascade' })
167
+ .notNull(),
168
+ ...timestamps,
169
+ },
170
+ (t) => ({
171
+ userIdIdx: index('oidc_sessions_user_id_idx').on(t.userId),
172
+ }),
173
+ );
138
174
 
139
175
  /**
140
176
  * OIDC authorization consent record
@@ -61,6 +61,9 @@ export const unstructuredChunks = pgTable(
61
61
  t.clientId,
62
62
  t.userId,
63
63
  ),
64
+ userIdIdx: index('unstructured_chunks_user_id_idx').on(t.userId),
65
+ compositeIdIdx: index('unstructured_chunks_composite_id_idx').on(t.compositeId),
66
+ fileIdIdx: index('unstructured_chunks_file_id_idx').on(t.fileId),
64
67
  }),
65
68
  );
66
69
 
@@ -116,6 +119,7 @@ export const documentChunks = pgTable(
116
119
  primaryKey({ columns: [t.documentId, t.chunkId] }),
117
120
  index('document_chunks_document_id_idx').on(t.documentId),
118
121
  index('document_chunks_chunk_id_idx').on(t.chunkId),
122
+ index('document_chunks_user_id_idx').on(t.userId),
119
123
  ],
120
124
  );
121
125
 
@@ -1,102 +1,126 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix */
2
2
  import { DEFAULT_MODEL } from '@lobechat/const';
3
3
  import { EvalEvaluationStatus } from '@lobechat/types';
4
- import { integer, jsonb, pgTable, text, uuid } from 'drizzle-orm/pg-core';
4
+ import { index, integer, jsonb, pgTable, text, uuid } from 'drizzle-orm/pg-core';
5
5
 
6
6
  import { timestamps } from './_helpers';
7
7
  import { knowledgeBases } from './file';
8
8
  import { embeddings } from './rag';
9
9
  import { users } from './user';
10
10
 
11
- export const evalDatasets = pgTable('rag_eval_datasets', {
12
- id: integer('id').generatedAlwaysAsIdentity({ startWith: 30_000 }).primaryKey(),
11
+ export const evalDatasets = pgTable(
12
+ 'rag_eval_datasets',
13
+ {
14
+ id: integer('id').generatedAlwaysAsIdentity({ startWith: 30_000 }).primaryKey(),
13
15
 
14
- description: text('description'),
15
- name: text('name').notNull(),
16
+ description: text('description'),
17
+ name: text('name').notNull(),
16
18
 
17
- knowledgeBaseId: text('knowledge_base_id').references(() => knowledgeBases.id, {
18
- onDelete: 'cascade',
19
- }),
20
- userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
19
+ knowledgeBaseId: text('knowledge_base_id').references(() => knowledgeBases.id, {
20
+ onDelete: 'cascade',
21
+ }),
22
+ userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
21
23
 
22
- ...timestamps,
23
- });
24
+ ...timestamps,
25
+ },
26
+ (t) => ({
27
+ userIdIdx: index('rag_eval_datasets_user_id_idx').on(t.userId),
28
+ }),
29
+ );
24
30
 
25
31
  export type NewEvalDatasetsItem = typeof evalDatasets.$inferInsert;
26
32
  export type EvalDatasetsSelectItem = typeof evalDatasets.$inferSelect;
27
33
 
28
- export const evalDatasetRecords = pgTable('rag_eval_dataset_records', {
29
- id: integer('id').generatedAlwaysAsIdentity().primaryKey(),
30
- datasetId: integer('dataset_id')
31
- .references(() => evalDatasets.id, { onDelete: 'cascade' })
32
- .notNull(),
33
-
34
- ideal: text('ideal'),
35
- question: text('question'),
36
- referenceFiles: text('reference_files').array(),
37
- metadata: jsonb('metadata'),
38
-
39
- userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
40
- ...timestamps,
41
- });
34
+ export const evalDatasetRecords = pgTable(
35
+ 'rag_eval_dataset_records',
36
+ {
37
+ id: integer('id').generatedAlwaysAsIdentity().primaryKey(),
38
+ datasetId: integer('dataset_id')
39
+ .references(() => evalDatasets.id, { onDelete: 'cascade' })
40
+ .notNull(),
41
+
42
+ ideal: text('ideal'),
43
+ question: text('question'),
44
+ referenceFiles: text('reference_files').array(),
45
+ metadata: jsonb('metadata'),
46
+
47
+ userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
48
+ ...timestamps,
49
+ },
50
+ (t) => ({
51
+ userIdIdx: index('rag_eval_dataset_records_user_id_idx').on(t.userId),
52
+ }),
53
+ );
42
54
 
43
55
  export type NewEvalDatasetRecordsItem = typeof evalDatasetRecords.$inferInsert;
44
56
  export type EvalDatasetRecordsSelectItem = typeof evalDatasetRecords.$inferSelect;
45
57
 
46
- export const evalEvaluation = pgTable('rag_eval_evaluations', {
47
- id: integer('id').generatedAlwaysAsIdentity().primaryKey(),
48
- name: text('name').notNull(),
49
- description: text('description'),
50
-
51
- evalRecordsUrl: text('eval_records_url'),
52
- status: text('status').$defaultFn(() => EvalEvaluationStatus.Pending),
53
- error: jsonb('error'),
54
-
55
- datasetId: integer('dataset_id')
56
- .references(() => evalDatasets.id, { onDelete: 'cascade' })
57
- .notNull(),
58
- knowledgeBaseId: text('knowledge_base_id').references(() => knowledgeBases.id, {
59
- onDelete: 'cascade',
58
+ export const evalEvaluation = pgTable(
59
+ 'rag_eval_evaluations',
60
+ {
61
+ id: integer('id').generatedAlwaysAsIdentity().primaryKey(),
62
+ name: text('name').notNull(),
63
+ description: text('description'),
64
+
65
+ evalRecordsUrl: text('eval_records_url'),
66
+ status: text('status').$defaultFn(() => EvalEvaluationStatus.Pending),
67
+ error: jsonb('error'),
68
+
69
+ datasetId: integer('dataset_id')
70
+ .references(() => evalDatasets.id, { onDelete: 'cascade' })
71
+ .notNull(),
72
+ knowledgeBaseId: text('knowledge_base_id').references(() => knowledgeBases.id, {
73
+ onDelete: 'cascade',
74
+ }),
75
+ languageModel: text('language_model').$defaultFn(() => DEFAULT_MODEL),
76
+ embeddingModel: text('embedding_model'),
77
+
78
+ userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
79
+ ...timestamps,
80
+ },
81
+ (t) => ({
82
+ userIdIdx: index('rag_eval_evaluations_user_id_idx').on(t.userId),
60
83
  }),
61
- languageModel: text('language_model').$defaultFn(() => DEFAULT_MODEL),
62
- embeddingModel: text('embedding_model'),
63
-
64
- userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
65
- ...timestamps,
66
- });
84
+ );
67
85
 
68
86
  export type NewEvalEvaluationItem = typeof evalEvaluation.$inferInsert;
69
87
  export type EvalEvaluationSelectItem = typeof evalEvaluation.$inferSelect;
70
88
 
71
- export const evaluationRecords = pgTable('rag_eval_evaluation_records', {
72
- id: integer('id').generatedAlwaysAsIdentity().primaryKey(),
73
-
74
- question: text('question').notNull(),
75
- answer: text('answer'),
76
- context: text('context').array(),
77
- ideal: text('ideal'),
78
-
79
- status: text('status').$defaultFn(() => EvalEvaluationStatus.Pending),
80
- error: jsonb('error'),
81
-
82
- languageModel: text('language_model'),
83
- embeddingModel: text('embedding_model'),
84
-
85
- questionEmbeddingId: uuid('question_embedding_id').references(() => embeddings.id, {
86
- onDelete: 'set null',
89
+ export const evaluationRecords = pgTable(
90
+ 'rag_eval_evaluation_records',
91
+ {
92
+ id: integer('id').generatedAlwaysAsIdentity().primaryKey(),
93
+
94
+ question: text('question').notNull(),
95
+ answer: text('answer'),
96
+ context: text('context').array(),
97
+ ideal: text('ideal'),
98
+
99
+ status: text('status').$defaultFn(() => EvalEvaluationStatus.Pending),
100
+ error: jsonb('error'),
101
+
102
+ languageModel: text('language_model'),
103
+ embeddingModel: text('embedding_model'),
104
+
105
+ questionEmbeddingId: uuid('question_embedding_id').references(() => embeddings.id, {
106
+ onDelete: 'set null',
107
+ }),
108
+
109
+ duration: integer('duration'),
110
+ datasetRecordId: integer('dataset_record_id')
111
+ .references(() => evalDatasetRecords.id, { onDelete: 'cascade' })
112
+ .notNull(),
113
+ evaluationId: integer('evaluation_id')
114
+ .references(() => evalEvaluation.id, { onDelete: 'cascade' })
115
+ .notNull(),
116
+
117
+ userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
118
+ ...timestamps,
119
+ },
120
+ (t) => ({
121
+ userIdIdx: index('rag_eval_evaluation_records_user_id_idx').on(t.userId),
87
122
  }),
88
-
89
- duration: integer('duration'),
90
- datasetRecordId: integer('dataset_record_id')
91
- .references(() => evalDatasetRecords.id, { onDelete: 'cascade' })
92
- .notNull(),
93
- evaluationId: integer('evaluation_id')
94
- .references(() => evalEvaluation.id, { onDelete: 'cascade' })
95
- .notNull(),
96
-
97
- userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
98
- ...timestamps,
99
- });
123
+ );
100
124
 
101
125
  export type NewEvaluationRecordsItem = typeof evaluationRecords.$inferInsert;
102
126
  export type EvaluationRecordsSelectItem = typeof evaluationRecords.$inferSelect;
@@ -31,6 +31,7 @@ export const agentsToSessions = pgTable(
31
31
  primaryKey({ columns: [t.agentId, t.sessionId] }),
32
32
  index('agents_to_sessions_session_id_idx').on(t.sessionId),
33
33
  index('agents_to_sessions_agent_id_idx').on(t.agentId),
34
+ index('agents_to_sessions_user_id_idx').on(t.userId),
34
35
  ],
35
36
  );
36
37
 
@@ -49,6 +50,9 @@ export const filesToSessions = pgTable(
49
50
  },
50
51
  (t) => ({
51
52
  pk: primaryKey({ columns: [t.fileId, t.sessionId] }),
53
+ userIdIdx: index('files_to_sessions_user_id_idx').on(t.userId),
54
+ fileIdIdx: index('files_to_sessions_file_id_idx').on(t.fileId),
55
+ sessionIdIdx: index('files_to_sessions_session_id_idx').on(t.sessionId),
52
56
  }),
53
57
  );
54
58
 
@@ -64,6 +68,9 @@ export const fileChunks = pgTable(
64
68
  },
65
69
  (t) => ({
66
70
  pk: primaryKey({ columns: [t.fileId, t.chunkId] }),
71
+ userIdIdx: index('file_chunks_user_id_idx').on(t.userId),
72
+ fileIdIdx: index('file_chunks_file_id_idx').on(t.fileId),
73
+ chunkIdIdx: index('file_chunks_chunk_id_idx').on(t.chunkId),
67
74
  }),
68
75
  );
69
76
  export type NewFileChunkItem = typeof fileChunks.$inferInsert;
@@ -29,6 +29,7 @@ export const sessionGroups = pgTable(
29
29
  table.clientId,
30
30
  table.userId,
31
31
  ),
32
+ userIdIdx: index('session_groups_user_id_idx').on(table.userId),
32
33
  }),
33
34
  );
34
35