@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.
@@ -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": ["DROP TABLE \"user_budgets\";", "\nDROP TABLE \"user_subscriptions\";"],
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": ["ALTER TABLE \"messages\" ADD COLUMN \"reasoning\" jsonb;"],
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": ["ALTER TABLE \"ai_providers\" ADD COLUMN \"config\" jsonb;"],
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": ["ALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"virtual\" boolean DEFAULT false;"],
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": ["ALTER TABLE \"user_settings\" ADD COLUMN IF NOT EXISTS \"image\" jsonb;"],
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": ["ALTER TABLE \"documents\" ADD COLUMN IF NOT EXISTS \"editor_data\" jsonb;"],
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": ["ALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"market_identifier\" text;\n"],
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": ["ALTER TABLE \"message_plugins\" ADD COLUMN IF NOT EXISTS \"intervention\" jsonb;\n"],
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": ["ALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"editor_data\" jsonb;"],
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 show all documents in All category (no filtering)', async () => {
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 everything
153
- expect(results.length).toBeGreaterThanOrEqual(6); // 2 files + 4 documents
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
- expect(editorDoc).toBeDefined();
159
- expect(uploadedPdf).toBeDefined();
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[] = [sql`${documents.userId} = ${this.userId}`];
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 and source_type='file' from Documents category
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('userId')
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('userId')
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('userId')
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
- type: text('type', { enum: ['continuation', 'standalone'] }).notNull(),
53
- status: text('status', { enum: ['active', 'deprecated', 'archived'] }).default('active'),
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').notNull(),
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: string;
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: string;
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: string) => void;
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>;
@@ -20,7 +20,7 @@ export interface ChatThreadState {
20
20
  /**
21
21
  * when open thread creator, set the message id to it
22
22
  */
23
- threadStartMessageId?: string;
23
+ threadStartMessageId?: string | null;
24
24
  threadsInit?: boolean;
25
25
  }
26
26
 
@@ -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 [];