@lobehub/lobehub 2.0.0-next.128 → 2.0.0-next.129
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/README.md +6 -6
- package/README.zh-CN.md +6 -6
- package/changelog/v1.json +9 -0
- package/docs/development/database-schema.dbml +8 -6
- package/package.json +1 -1
- package/packages/database/migrations/0050_thread_and_user_id.sql +18 -0
- package/packages/database/migrations/meta/0050_snapshot.json +8792 -0
- package/packages/database/migrations/meta/_journal.json +7 -0
- package/packages/database/src/core/migrations.json +51 -10
- package/packages/database/src/repositories/knowledge/index.test.ts +17 -5
- package/packages/database/src/repositories/knowledge/index.ts +6 -6
- package/packages/database/src/schemas/nextauth.ts +3 -3
- package/packages/database/src/schemas/topic.ts +8 -3
- package/packages/types/src/topic/thread.ts +3 -3
- package/src/store/chat/slices/thread/action.ts +1 -1
- package/src/store/chat/slices/thread/initialState.ts +1 -1
- package/src/store/chat/slices/thread/selectors/util.ts +1 -1
|
@@ -350,6 +350,13 @@
|
|
|
350
350
|
"when": 1764229953081,
|
|
351
351
|
"tag": "0049_better_auth",
|
|
352
352
|
"breakpoints": true
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
"idx": 50,
|
|
356
|
+
"version": "7",
|
|
357
|
+
"when": 1764303057060,
|
|
358
|
+
"tag": "0050_thread_and_user_id",
|
|
359
|
+
"breakpoints": true
|
|
353
360
|
}
|
|
354
361
|
],
|
|
355
362
|
"version": "6"
|
|
@@ -223,7 +223,10 @@
|
|
|
223
223
|
"hash": "9646161fa041354714f823d726af27247bcd6e60fa3be5698c0d69f337a5700b"
|
|
224
224
|
},
|
|
225
225
|
{
|
|
226
|
-
"sql": [
|
|
226
|
+
"sql": [
|
|
227
|
+
"DROP TABLE \"user_budgets\";",
|
|
228
|
+
"\nDROP TABLE \"user_subscriptions\";"
|
|
229
|
+
],
|
|
227
230
|
"bps": true,
|
|
228
231
|
"folderMillis": 1729699958471,
|
|
229
232
|
"hash": "7dad43a2a25d1aec82124a4e53f8d82f8505c3073f23606c1dc5d2a4598eacf9"
|
|
@@ -295,7 +298,9 @@
|
|
|
295
298
|
"hash": "845a692ceabbfc3caf252a97d3e19a213bc0c433df2689900135f9cfded2cf49"
|
|
296
299
|
},
|
|
297
300
|
{
|
|
298
|
-
"sql": [
|
|
301
|
+
"sql": [
|
|
302
|
+
"ALTER TABLE \"messages\" ADD COLUMN \"reasoning\" jsonb;"
|
|
303
|
+
],
|
|
299
304
|
"bps": true,
|
|
300
305
|
"folderMillis": 1737609172353,
|
|
301
306
|
"hash": "2cb36ae4fcdd7b7064767e04bfbb36ae34518ff4bb1b39006f2dd394d1893868"
|
|
@@ -510,7 +515,9 @@
|
|
|
510
515
|
"hash": "a7ccf007fd185ff922823148d1eae6fafe652fc98d2fd2793f84a84f29e93cd1"
|
|
511
516
|
},
|
|
512
517
|
{
|
|
513
|
-
"sql": [
|
|
518
|
+
"sql": [
|
|
519
|
+
"ALTER TABLE \"ai_providers\" ADD COLUMN \"config\" jsonb;"
|
|
520
|
+
],
|
|
514
521
|
"bps": true,
|
|
515
522
|
"folderMillis": 1749309388370,
|
|
516
523
|
"hash": "39cea379f08ee4cb944875c0b67f7791387b508c2d47958bb4cd501ed1ef33eb"
|
|
@@ -628,7 +635,9 @@
|
|
|
628
635
|
"hash": "1ba9b1f74ea13348da98d6fcdad7867ab4316ed565bf75d84d160c526cdac14b"
|
|
629
636
|
},
|
|
630
637
|
{
|
|
631
|
-
"sql": [
|
|
638
|
+
"sql": [
|
|
639
|
+
"ALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"virtual\" boolean DEFAULT false;"
|
|
640
|
+
],
|
|
632
641
|
"bps": true,
|
|
633
642
|
"folderMillis": 1759116400580,
|
|
634
643
|
"hash": "433ddae88e785f2db734e49a4c115eee93e60afe389f7919d66e5ba9aa159a37"
|
|
@@ -678,13 +687,17 @@
|
|
|
678
687
|
"hash": "4bdc6505797d7a33b622498c138cfd47f637239f6905e1c484cd01d9d5f21d6b"
|
|
679
688
|
},
|
|
680
689
|
{
|
|
681
|
-
"sql": [
|
|
690
|
+
"sql": [
|
|
691
|
+
"ALTER TABLE \"user_settings\" ADD COLUMN IF NOT EXISTS \"image\" jsonb;"
|
|
692
|
+
],
|
|
682
693
|
"bps": true,
|
|
683
694
|
"folderMillis": 1760108430562,
|
|
684
695
|
"hash": "ce09b301abb80f6563abc2f526bdd20b4f69bae430f09ba2179b9e3bfec43067"
|
|
685
696
|
},
|
|
686
697
|
{
|
|
687
|
-
"sql": [
|
|
698
|
+
"sql": [
|
|
699
|
+
"ALTER TABLE \"documents\" ADD COLUMN IF NOT EXISTS \"editor_data\" jsonb;"
|
|
700
|
+
],
|
|
688
701
|
"bps": true,
|
|
689
702
|
"folderMillis": 1761554153406,
|
|
690
703
|
"hash": "bf2f21293e90e11cf60a784cf3ec219eafa95f7545d7d2f9d1449c0b0949599a"
|
|
@@ -764,13 +777,17 @@
|
|
|
764
777
|
"hash": "923ccbdf46c32be9a981dabd348e6923b4a365444241e9b8cc174bf5b914cbc5"
|
|
765
778
|
},
|
|
766
779
|
{
|
|
767
|
-
"sql": [
|
|
780
|
+
"sql": [
|
|
781
|
+
"ALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"market_identifier\" text;\n"
|
|
782
|
+
],
|
|
768
783
|
"bps": true,
|
|
769
784
|
"folderMillis": 1762870034882,
|
|
770
785
|
"hash": "4178aacb4b8892b7fd15d29209bbf9b1d1f9d7c406ba796f27542c0bcd919680"
|
|
771
786
|
},
|
|
772
787
|
{
|
|
773
|
-
"sql": [
|
|
788
|
+
"sql": [
|
|
789
|
+
"ALTER TABLE \"message_plugins\" ADD COLUMN IF NOT EXISTS \"intervention\" jsonb;\n"
|
|
790
|
+
],
|
|
774
791
|
"bps": true,
|
|
775
792
|
"folderMillis": 1762911968658,
|
|
776
793
|
"hash": "552a032cc0e595277232e70b5f9338658585bafe9481ae8346a5f322b673a68b"
|
|
@@ -799,7 +816,9 @@
|
|
|
799
816
|
"hash": "f823b521f4d25e5dc5ab238b372727d2d2d7f0aed27b5eabc8a9608ce4e50568"
|
|
800
817
|
},
|
|
801
818
|
{
|
|
802
|
-
"sql": [
|
|
819
|
+
"sql": [
|
|
820
|
+
"ALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"editor_data\" jsonb;"
|
|
821
|
+
],
|
|
803
822
|
"bps": true,
|
|
804
823
|
"folderMillis": 1764215503726,
|
|
805
824
|
"hash": "4188893a9083b3c7baebdbad0dd3f9d9400ede7584ca2394f5c64305dc9ec7b0"
|
|
@@ -816,5 +835,27 @@
|
|
|
816
835
|
"bps": true,
|
|
817
836
|
"folderMillis": 1764229953081,
|
|
818
837
|
"hash": "1532ebceae7b70550bc9c230fb0a65090aaa773bc7b873eefbc2ce2a815997e2"
|
|
838
|
+
},
|
|
839
|
+
{
|
|
840
|
+
"sql": [
|
|
841
|
+
"ALTER TABLE \"nextauth_accounts\" RENAME COLUMN \"userId\" TO \"user_id\";",
|
|
842
|
+
"\nALTER TABLE \"nextauth_authenticators\" RENAME COLUMN \"userId\" TO \"user_id\";",
|
|
843
|
+
"\nALTER TABLE \"nextauth_sessions\" RENAME COLUMN \"userId\" TO \"user_id\";",
|
|
844
|
+
"\nALTER TABLE \"nextauth_accounts\" DROP CONSTRAINT \"nextauth_accounts_userId_users_id_fk\";\n",
|
|
845
|
+
"\nALTER TABLE \"nextauth_authenticators\" DROP CONSTRAINT \"nextauth_authenticators_userId_users_id_fk\";\n",
|
|
846
|
+
"\nALTER TABLE \"nextauth_sessions\" DROP CONSTRAINT \"nextauth_sessions_userId_users_id_fk\";\n",
|
|
847
|
+
"\nALTER TABLE \"nextauth_authenticators\" DROP CONSTRAINT \"nextauth_authenticators_userId_credentialID_pk\";",
|
|
848
|
+
"\nALTER TABLE \"threads\" ALTER COLUMN \"status\" DROP DEFAULT;",
|
|
849
|
+
"\nALTER TABLE \"threads\" ALTER COLUMN \"source_message_id\" DROP NOT NULL;",
|
|
850
|
+
"\nALTER TABLE \"nextauth_authenticators\" ADD CONSTRAINT \"nextauth_authenticators_user_id_credentialID_pk\" PRIMARY KEY(\"user_id\",\"credentialID\");",
|
|
851
|
+
"\nALTER TABLE \"threads\" ADD COLUMN \"content\" text;",
|
|
852
|
+
"\nALTER TABLE \"threads\" ADD COLUMN \"editor_data\" jsonb;",
|
|
853
|
+
"\nALTER TABLE \"nextauth_accounts\" ADD CONSTRAINT \"nextauth_accounts_user_id_users_id_fk\" FOREIGN KEY (\"user_id\") REFERENCES \"public\".\"users\"(\"id\") ON DELETE cascade ON UPDATE no action;",
|
|
854
|
+
"\nALTER TABLE \"nextauth_authenticators\" ADD CONSTRAINT \"nextauth_authenticators_user_id_users_id_fk\" FOREIGN KEY (\"user_id\") REFERENCES \"public\".\"users\"(\"id\") ON DELETE cascade ON UPDATE no action;",
|
|
855
|
+
"\nALTER TABLE \"nextauth_sessions\" ADD CONSTRAINT \"nextauth_sessions_user_id_users_id_fk\" FOREIGN KEY (\"user_id\") REFERENCES \"public\".\"users\"(\"id\") ON DELETE cascade ON UPDATE no action;"
|
|
856
|
+
],
|
|
857
|
+
"bps": true,
|
|
858
|
+
"folderMillis": 1764303057060,
|
|
859
|
+
"hash": "edcebee8f59971210c1f8b567d3bd0ffa37da286afeead5bdaaa19eeaa4b89cb"
|
|
819
860
|
}
|
|
820
|
-
]
|
|
861
|
+
]
|
|
@@ -146,17 +146,29 @@ describe('KnowledgeRepo', () => {
|
|
|
146
146
|
expect(regularFile?.sourceType).toBe('file');
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
-
it('should
|
|
149
|
+
it('should exclude sourceType=file documents from All category', async () => {
|
|
150
150
|
const results = await knowledgeRepo.query({ category: FilesTabs.All });
|
|
151
151
|
|
|
152
|
-
// All category should include
|
|
153
|
-
|
|
152
|
+
// All category should include files from files table + documents with sourceType != 'file'
|
|
153
|
+
// 2 files + 2 documents (api-pdf and web-doc)
|
|
154
|
+
// Excluded: uploaded-pdf and editor-doc both have sourceType='file'
|
|
155
|
+
expect(results.length).toBe(4);
|
|
154
156
|
|
|
157
|
+
// Should NOT include documents with sourceType='file' (globally excluded now)
|
|
155
158
|
const editorDoc = results.find((item) => item.name === 'editor-doc.md');
|
|
156
159
|
const uploadedPdf = results.find((item) => item.name === 'uploaded-pdf.pdf');
|
|
160
|
+
expect(editorDoc).toBeUndefined();
|
|
161
|
+
expect(uploadedPdf).toBeUndefined();
|
|
157
162
|
|
|
158
|
-
|
|
159
|
-
|
|
163
|
+
// Should include documents with sourceType != 'file'
|
|
164
|
+
const apiPdf = results.find((item) => item.name === 'api-pdf.pdf');
|
|
165
|
+
const webDoc = results.find((item) => item.name === 'web-doc.txt');
|
|
166
|
+
expect(apiPdf).toBeDefined();
|
|
167
|
+
expect(webDoc).toBeDefined();
|
|
168
|
+
|
|
169
|
+
// Should include files from files table
|
|
170
|
+
const regularFile = results.find((item) => item.name === 'regular-pdf-file.pdf');
|
|
171
|
+
expect(regularFile).toBeDefined();
|
|
160
172
|
});
|
|
161
173
|
|
|
162
174
|
it('should apply both filters together in Documents category', async () => {
|
|
@@ -281,7 +281,10 @@ export class KnowledgeRepo {
|
|
|
281
281
|
q,
|
|
282
282
|
knowledgeBaseId,
|
|
283
283
|
}: QueryFileListParams = {}): ReturnType<typeof sql> {
|
|
284
|
-
let whereConditions: any[] = [
|
|
284
|
+
let whereConditions: any[] = [
|
|
285
|
+
sql`${documents.userId} = ${this.userId}`,
|
|
286
|
+
sql`${documents.sourceType} != ${'file'}`,
|
|
287
|
+
];
|
|
285
288
|
|
|
286
289
|
// Search filter
|
|
287
290
|
if (q) {
|
|
@@ -300,12 +303,9 @@ export class KnowledgeRepo {
|
|
|
300
303
|
);
|
|
301
304
|
whereConditions.push(sql`(${sql.join(orConditions, sql` OR `)})`);
|
|
302
305
|
|
|
303
|
-
// Exclude custom/document
|
|
306
|
+
// Exclude custom/document from Documents category
|
|
304
307
|
if (category === FilesTabs.Documents) {
|
|
305
|
-
whereConditions.push(
|
|
306
|
-
sql`${documents.fileType} != ${'custom/document'}`,
|
|
307
|
-
sql`${documents.sourceType} != ${'file'}`,
|
|
308
|
-
);
|
|
308
|
+
whereConditions.push(sql`${documents.fileType} != ${'custom/document'}`);
|
|
309
309
|
}
|
|
310
310
|
} else if (fileTypePrefix) {
|
|
311
311
|
whereConditions.push(sql`${documents.fileType} ILIKE ${`${fileTypePrefix}%`}`);
|
|
@@ -20,7 +20,7 @@ export const nextauthAccounts = pgTable(
|
|
|
20
20
|
session_state: text('session_state'),
|
|
21
21
|
token_type: text('token_type'),
|
|
22
22
|
type: text('type').$type<AdapterAccount>().notNull(),
|
|
23
|
-
userId: text('
|
|
23
|
+
userId: text('user_id')
|
|
24
24
|
.notNull()
|
|
25
25
|
.references(() => users.id, { onDelete: 'cascade' }),
|
|
26
26
|
},
|
|
@@ -40,7 +40,7 @@ export const nextauthAccounts = pgTable(
|
|
|
40
40
|
export const nextauthSessions = pgTable(`nextauth_sessions`, {
|
|
41
41
|
expires: timestamp('expires', { mode: 'date' }).notNull(),
|
|
42
42
|
sessionToken: text('sessionToken').primaryKey(),
|
|
43
|
-
userId: text('
|
|
43
|
+
userId: text('user_id')
|
|
44
44
|
.notNull()
|
|
45
45
|
.references(() => users.id, { onDelete: 'cascade' }),
|
|
46
46
|
});
|
|
@@ -77,7 +77,7 @@ export const nextauthAuthenticators = pgTable(
|
|
|
77
77
|
credentialPublicKey: text('credentialPublicKey').notNull(),
|
|
78
78
|
providerAccountId: text('providerAccountId').notNull(),
|
|
79
79
|
transports: text('transports'),
|
|
80
|
-
userId: text('
|
|
80
|
+
userId: text('user_id')
|
|
81
81
|
.notNull()
|
|
82
82
|
.references(() => users.id, { onDelete: 'cascade' }),
|
|
83
83
|
},
|
|
@@ -49,12 +49,17 @@ export const threads = pgTable(
|
|
|
49
49
|
.primaryKey(),
|
|
50
50
|
|
|
51
51
|
title: text('title'),
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
content: text('content'),
|
|
53
|
+
editor_data: jsonb('editor_data'),
|
|
54
|
+
type: text('type', { enum: ['continuation', 'standalone', 'isolation'] }).notNull(),
|
|
55
|
+
status: text('status', {
|
|
56
|
+
enum: ['active', 'processing', 'pending', 'inReview', 'todo', 'cancel'],
|
|
57
|
+
}),
|
|
58
|
+
|
|
54
59
|
topicId: text('topic_id')
|
|
55
60
|
.references(() => topics.id, { onDelete: 'cascade' })
|
|
56
61
|
.notNull(),
|
|
57
|
-
sourceMessageId: text('source_message_id')
|
|
62
|
+
sourceMessageId: text('source_message_id'),
|
|
58
63
|
// @ts-ignore
|
|
59
64
|
parentThreadId: text('parent_thread_id').references(() => threads.id, { onDelete: 'set null' }),
|
|
60
65
|
clientId: text('client_id'),
|
|
@@ -16,7 +16,7 @@ export interface ThreadItem {
|
|
|
16
16
|
id: string;
|
|
17
17
|
lastActiveAt: Date;
|
|
18
18
|
parentThreadId?: string;
|
|
19
|
-
sourceMessageId
|
|
19
|
+
sourceMessageId?: string | null;
|
|
20
20
|
status: ThreadStatus;
|
|
21
21
|
title: string;
|
|
22
22
|
topicId: string;
|
|
@@ -27,7 +27,7 @@ export interface ThreadItem {
|
|
|
27
27
|
|
|
28
28
|
export interface CreateThreadParams {
|
|
29
29
|
parentThreadId?: string;
|
|
30
|
-
sourceMessageId
|
|
30
|
+
sourceMessageId?: string;
|
|
31
31
|
title?: string;
|
|
32
32
|
topicId: string;
|
|
33
33
|
type: ThreadType;
|
|
@@ -35,7 +35,7 @@ export interface CreateThreadParams {
|
|
|
35
35
|
|
|
36
36
|
export const createThreadSchema = z.object({
|
|
37
37
|
parentThreadId: z.string().optional(),
|
|
38
|
-
sourceMessageId: z.string(),
|
|
38
|
+
sourceMessageId: z.string().optional(),
|
|
39
39
|
title: z.string().optional(),
|
|
40
40
|
topicId: z.string(),
|
|
41
41
|
type: z.nativeEnum(ThreadType),
|
|
@@ -47,7 +47,7 @@ export interface ChatThreadAction {
|
|
|
47
47
|
type: ThreadType;
|
|
48
48
|
}) => Promise<{ threadId: string; messageId: string }>;
|
|
49
49
|
openThreadCreator: (messageId: string) => void;
|
|
50
|
-
openThreadInPortal: (threadId: string, sourceMessageId
|
|
50
|
+
openThreadInPortal: (threadId: string, sourceMessageId?: string | null) => void;
|
|
51
51
|
closeThreadPortal: () => void;
|
|
52
52
|
useFetchThreads: (enable: boolean, topicId?: string) => SWRResponse<ThreadItem[]>;
|
|
53
53
|
summaryThreadTitle: (threadId: string, messages: UIChatMessage[]) => Promise<void>;
|
|
@@ -2,7 +2,7 @@ import { ThreadType, UIChatMessage } from '@lobechat/types';
|
|
|
2
2
|
|
|
3
3
|
export const genMessage = (
|
|
4
4
|
messages: UIChatMessage[],
|
|
5
|
-
startMessageId: string | undefined,
|
|
5
|
+
startMessageId: string | null | undefined,
|
|
6
6
|
threadMode?: ThreadType,
|
|
7
7
|
) => {
|
|
8
8
|
if (!startMessageId) return [];
|