@lobehub/lobehub 2.0.0-next.79 → 2.0.0-next.80

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.
@@ -322,6 +322,13 @@
322
322
  "when": 1762911968658,
323
323
  "tag": "0045_add_tool_intervention",
324
324
  "breakpoints": true
325
+ },
326
+ {
327
+ "idx": 46,
328
+ "version": "7",
329
+ "when": 1763453175961,
330
+ "tag": "0046_add_parent_id",
331
+ "breakpoints": true
325
332
  }
326
333
  ],
327
334
  "version": "6"
@@ -223,10 +223,7 @@
223
223
  "hash": "9646161fa041354714f823d726af27247bcd6e60fa3be5698c0d69f337a5700b"
224
224
  },
225
225
  {
226
- "sql": [
227
- "DROP TABLE \"user_budgets\";",
228
- "\nDROP TABLE \"user_subscriptions\";"
229
- ],
226
+ "sql": ["DROP TABLE \"user_budgets\";", "\nDROP TABLE \"user_subscriptions\";"],
230
227
  "bps": true,
231
228
  "folderMillis": 1729699958471,
232
229
  "hash": "7dad43a2a25d1aec82124a4e53f8d82f8505c3073f23606c1dc5d2a4598eacf9"
@@ -298,9 +295,7 @@
298
295
  "hash": "845a692ceabbfc3caf252a97d3e19a213bc0c433df2689900135f9cfded2cf49"
299
296
  },
300
297
  {
301
- "sql": [
302
- "ALTER TABLE \"messages\" ADD COLUMN \"reasoning\" jsonb;"
303
- ],
298
+ "sql": ["ALTER TABLE \"messages\" ADD COLUMN \"reasoning\" jsonb;"],
304
299
  "bps": true,
305
300
  "folderMillis": 1737609172353,
306
301
  "hash": "2cb36ae4fcdd7b7064767e04bfbb36ae34518ff4bb1b39006f2dd394d1893868"
@@ -515,9 +510,7 @@
515
510
  "hash": "a7ccf007fd185ff922823148d1eae6fafe652fc98d2fd2793f84a84f29e93cd1"
516
511
  },
517
512
  {
518
- "sql": [
519
- "ALTER TABLE \"ai_providers\" ADD COLUMN \"config\" jsonb;"
520
- ],
513
+ "sql": ["ALTER TABLE \"ai_providers\" ADD COLUMN \"config\" jsonb;"],
521
514
  "bps": true,
522
515
  "folderMillis": 1749309388370,
523
516
  "hash": "39cea379f08ee4cb944875c0b67f7791387b508c2d47958bb4cd501ed1ef33eb"
@@ -635,9 +628,7 @@
635
628
  "hash": "1ba9b1f74ea13348da98d6fcdad7867ab4316ed565bf75d84d160c526cdac14b"
636
629
  },
637
630
  {
638
- "sql": [
639
- "ALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"virtual\" boolean DEFAULT false;"
640
- ],
631
+ "sql": ["ALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"virtual\" boolean DEFAULT false;"],
641
632
  "bps": true,
642
633
  "folderMillis": 1759116400580,
643
634
  "hash": "433ddae88e785f2db734e49a4c115eee93e60afe389f7919d66e5ba9aa159a37"
@@ -687,17 +678,13 @@
687
678
  "hash": "4bdc6505797d7a33b622498c138cfd47f637239f6905e1c484cd01d9d5f21d6b"
688
679
  },
689
680
  {
690
- "sql": [
691
- "ALTER TABLE \"user_settings\" ADD COLUMN IF NOT EXISTS \"image\" jsonb;"
692
- ],
681
+ "sql": ["ALTER TABLE \"user_settings\" ADD COLUMN IF NOT EXISTS \"image\" jsonb;"],
693
682
  "bps": true,
694
683
  "folderMillis": 1760108430562,
695
684
  "hash": "ce09b301abb80f6563abc2f526bdd20b4f69bae430f09ba2179b9e3bfec43067"
696
685
  },
697
686
  {
698
- "sql": [
699
- "ALTER TABLE \"documents\" ADD COLUMN IF NOT EXISTS \"editor_data\" jsonb;"
700
- ],
687
+ "sql": ["ALTER TABLE \"documents\" ADD COLUMN IF NOT EXISTS \"editor_data\" jsonb;"],
701
688
  "bps": true,
702
689
  "folderMillis": 1761554153406,
703
690
  "hash": "bf2f21293e90e11cf60a784cf3ec219eafa95f7545d7d2f9d1449c0b0949599a"
@@ -777,19 +764,29 @@
777
764
  "hash": "923ccbdf46c32be9a981dabd348e6923b4a365444241e9b8cc174bf5b914cbc5"
778
765
  },
779
766
  {
780
- "sql": [
781
- "ALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"market_identifier\" text;\n"
782
- ],
767
+ "sql": ["ALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"market_identifier\" text;\n"],
783
768
  "bps": true,
784
769
  "folderMillis": 1762870034882,
785
770
  "hash": "4178aacb4b8892b7fd15d29209bbf9b1d1f9d7c406ba796f27542c0bcd919680"
786
771
  },
787
772
  {
788
- "sql": [
789
- "ALTER TABLE \"message_plugins\" ADD COLUMN IF NOT EXISTS \"intervention\" jsonb;\n"
790
- ],
773
+ "sql": ["ALTER TABLE \"message_plugins\" ADD COLUMN IF NOT EXISTS \"intervention\" jsonb;\n"],
791
774
  "bps": true,
792
775
  "folderMillis": 1762911968658,
793
776
  "hash": "552a032cc0e595277232e70b5f9338658585bafe9481ae8346a5f322b673a68b"
777
+ },
778
+ {
779
+ "sql": [
780
+ "ALTER TABLE \"documents\" ALTER COLUMN \"id\" SET DATA TYPE varchar(255);",
781
+ "\nALTER TABLE \"documents\" ADD COLUMN \"parent_id\" varchar(255);",
782
+ "\nALTER TABLE \"files\" ADD COLUMN \"parent_id\" varchar(255);",
783
+ "\nALTER TABLE \"documents\" ADD CONSTRAINT \"documents_parent_id_documents_id_fk\" FOREIGN KEY (\"parent_id\") REFERENCES \"public\".\"documents\"(\"id\") ON DELETE set null ON UPDATE no action;",
784
+ "\nALTER TABLE \"files\" ADD CONSTRAINT \"files_parent_id_documents_id_fk\" FOREIGN KEY (\"parent_id\") REFERENCES \"public\".\"documents\"(\"id\") ON DELETE set null ON UPDATE no action;",
785
+ "\nCREATE INDEX \"documents_parent_id_idx\" ON \"documents\" USING btree (\"parent_id\");",
786
+ "\nCREATE INDEX \"files_parent_id_idx\" ON \"files\" USING btree (\"parent_id\");"
787
+ ],
788
+ "bps": true,
789
+ "folderMillis": 1763453175961,
790
+ "hash": "6cfc00744de6a8f4d60b793673911bb740f9a50661663e28b843e5adae08f94a"
794
791
  }
795
- ]
792
+ ]
@@ -1,8 +1,7 @@
1
1
  import { and, desc, eq } from 'drizzle-orm';
2
2
 
3
- import { LobeChatDatabase } from '../type';
4
-
5
3
  import { DocumentItem, NewDocument, documents } from '../schemas';
4
+ import { LobeChatDatabase } from '../type';
6
5
 
7
6
  export class DocumentModel {
8
7
  private userId: string;
@@ -13,13 +12,13 @@ export class DocumentModel {
13
12
  this.db = db;
14
13
  }
15
14
 
16
- create = async (params: Omit<NewDocument, 'userId'>) => {
17
- const [result] = await this.db
15
+ create = async (params: Omit<NewDocument, 'userId'>): Promise<DocumentItem> => {
16
+ const result = (await this.db
18
17
  .insert(documents)
19
18
  .values({ ...params, userId: this.userId })
20
- .returning();
19
+ .returning()) as DocumentItem[];
21
20
 
22
- return result;
21
+ return result[0]!;
23
22
  };
24
23
 
25
24
  delete = async (id: string) => {
@@ -43,8 +43,8 @@ export class FileModel {
43
43
  params: Omit<NewFile, 'id' | 'userId'> & { id?: string; knowledgeBaseId?: string },
44
44
  insertToGlobalFiles?: boolean,
45
45
  trx?: Transaction,
46
- ) => {
47
- const executeInTransaction = async (tx: Transaction) => {
46
+ ): Promise<{ id: string }> => {
47
+ const executeInTransaction = async (tx: Transaction): Promise<FileItem> => {
48
48
  if (insertToGlobalFiles) {
49
49
  await tx.insert(globalFiles).values({
50
50
  creator: this.userId,
@@ -56,12 +56,12 @@ export class FileModel {
56
56
  });
57
57
  }
58
58
 
59
- const result = await tx
59
+ const result = (await tx
60
60
  .insert(files)
61
61
  .values({ ...params, userId: this.userId })
62
- .returning();
62
+ .returning()) as FileItem[];
63
63
 
64
- const item = result[0];
64
+ const item = result[0]!;
65
65
 
66
66
  if (params.knowledgeBaseId) {
67
67
  await tx.insert(knowledgeBaseFiles).values({
@@ -3,7 +3,7 @@ import { FilesTabs } from '@lobechat/types';
3
3
  import { beforeEach, describe, expect, it } from 'vitest';
4
4
 
5
5
  import { getTestDB } from '../../models/__tests__/_util';
6
- import { NewDocument, documents } from '../../schemas/document';
6
+ import { NewDocument, documents } from '../../schemas/file';
7
7
  import { NewFile, files } from '../../schemas/file';
8
8
  import { users } from '../../schemas/user';
9
9
  import { LobeChatDatabase } from '../../type';
@@ -1,5 +1,4 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix */
2
- import { FileSource } from '@lobechat/types';
3
2
  import {
4
3
  boolean,
5
4
  index,
@@ -14,6 +13,9 @@ import {
14
13
  } from 'drizzle-orm/pg-core';
15
14
  import { createInsertSchema } from 'drizzle-zod';
16
15
 
16
+ import { LobeDocumentPage } from '@/types/document';
17
+ import { FileSource } from '@/types/files';
18
+
17
19
  import { idGenerator } from '../utils/idGenerator';
18
20
  import { accessedAt, createdAt, timestamps } from './_helpers';
19
21
  import { asyncTasks } from './asyncTask';
@@ -35,6 +37,77 @@ export const globalFiles = pgTable('global_files', {
35
37
  export type NewGlobalFile = typeof globalFiles.$inferInsert;
36
38
  export type GlobalFileItem = typeof globalFiles.$inferSelect;
37
39
 
40
+ /**
41
+ * 文档表 - 存储文件内容或网页搜索结果
42
+ */
43
+ // @ts-ignore
44
+ export const documents = pgTable(
45
+ 'documents',
46
+ {
47
+ id: varchar('id', { length: 255 })
48
+ .$defaultFn(() => idGenerator('documents', 16))
49
+ .primaryKey(),
50
+
51
+ // 基本信息
52
+ title: text('title'),
53
+ content: text('content'),
54
+
55
+ // Special type: custom/folder
56
+ fileType: varchar('file_type', { length: 255 }).notNull(),
57
+ filename: text('filename'),
58
+
59
+ // 统计信息
60
+ totalCharCount: integer('total_char_count').notNull(),
61
+ totalLineCount: integer('total_line_count').notNull(),
62
+
63
+ // 元数据
64
+ metadata: jsonb('metadata').$type<Record<string, any>>(),
65
+
66
+ // 页面/块数据
67
+ pages: jsonb('pages').$type<LobeDocumentPage[]>(),
68
+
69
+ // 来源类型
70
+ sourceType: text('source_type', { enum: ['file', 'web', 'api'] }).notNull(),
71
+ source: text('source').notNull(), // 文件路径或网页URL
72
+
73
+ // 关联文件(可选)
74
+ // Forward reference to files table defined below
75
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
76
+ // @ts-expect-error - files is defined later in this file, forward reference is valid at runtime
77
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
78
+ fileId: text('file_id').references(() => files.id, { onDelete: 'set null' }),
79
+
80
+ // 父文档(用于文件夹层级结构)
81
+ // @ts-ignore
82
+ parentId: varchar('parent_id', { length: 255 }).references(() => documents.id, {
83
+ onDelete: 'set null',
84
+ }),
85
+
86
+ // 用户关联
87
+ userId: text('user_id')
88
+ .references(() => users.id, { onDelete: 'cascade' })
89
+ .notNull(),
90
+ clientId: text('client_id'),
91
+
92
+ editorData: jsonb('editor_data').$type<Record<string, any>>(),
93
+
94
+ // 时间戳
95
+ ...timestamps,
96
+ },
97
+ (table) => [
98
+ index('documents_source_idx').on(table.source),
99
+ index('documents_file_type_idx').on(table.fileType),
100
+ index('documents_file_id_idx').on(table.fileId),
101
+ index('documents_parent_id_idx').on(table.parentId),
102
+ uniqueIndex('documents_client_id_user_id_unique').on(table.clientId, table.userId),
103
+ ],
104
+ );
105
+
106
+ export type NewDocument = typeof documents.$inferInsert;
107
+ export type DocumentItem = typeof documents.$inferSelect;
108
+ export const insertDocumentSchema = createInsertSchema(documents);
109
+
110
+ // @ts-ignore
38
111
  export const files = pgTable(
39
112
  'files',
40
113
  {
@@ -60,6 +133,12 @@ export const files = pgTable(
60
133
  url: text('url').notNull(),
61
134
  source: text('source').$type<FileSource>(),
62
135
 
136
+ // 父文档(用于文件夹层级结构)
137
+ // @ts-ignore
138
+ parentId: varchar('parent_id', { length: 255 }).references(() => documents.id, {
139
+ onDelete: 'set null',
140
+ }),
141
+
63
142
  clientId: text('client_id'),
64
143
  metadata: jsonb('metadata'),
65
144
  chunkTaskId: uuid('chunk_task_id').references(() => asyncTasks.id, { onDelete: 'set null' }),
@@ -72,6 +151,7 @@ export const files = pgTable(
72
151
  (table) => {
73
152
  return {
74
153
  fileHashIdx: index('file_hash_idx').on(table.fileHash),
154
+ parentIdIdx: index('files_parent_id_idx').on(table.parentId),
75
155
  clientIdUnique: uniqueIndex('files_client_id_user_id_unique').on(
76
156
  table.clientId,
77
157
  table.userId,
@@ -3,7 +3,6 @@ export * from './aiInfra';
3
3
  export * from './apiKey';
4
4
  export * from './asyncTask';
5
5
  export * from './chatGroup';
6
- export * from './document';
7
6
  export * from './file';
8
7
  export * from './generation';
9
8
  export * from './message';
@@ -4,6 +4,7 @@ import {
4
4
  integer,
5
5
  jsonb,
6
6
  pgTable,
7
+ primaryKey,
7
8
  text,
8
9
  uniqueIndex,
9
10
  uuid,
@@ -11,8 +12,8 @@ import {
11
12
  vector,
12
13
  } from 'drizzle-orm/pg-core';
13
14
 
14
- import { timestamps } from './_helpers';
15
- import { files } from './file';
15
+ import { createdAt, timestamps } from './_helpers';
16
+ import { documents, files } from './file';
16
17
  import { users } from './user';
17
18
 
18
19
  export const chunks = pgTable(
@@ -86,3 +87,32 @@ export const embeddings = pgTable(
86
87
 
87
88
  export type NewEmbeddingsItem = typeof embeddings.$inferInsert;
88
89
  export type EmbeddingsSelectItem = typeof embeddings.$inferSelect;
90
+
91
+ /**
92
+ * 文档块表 - 将文档内容分割成块并关联到 chunks 表,用于向量检索
93
+ * 注意:此表可选,如果已经使用 pages 字段存储了文档块,可以不需要此表
94
+ */
95
+ export const documentChunks = pgTable(
96
+ 'document_chunks',
97
+ {
98
+ documentId: varchar('document_id', { length: 30 })
99
+ .references(() => documents.id, { onDelete: 'cascade' })
100
+ .notNull(),
101
+
102
+ chunkId: uuid('chunk_id')
103
+ .references(() => chunks.id, { onDelete: 'cascade' })
104
+ .notNull(),
105
+
106
+ pageIndex: integer('page_index'),
107
+
108
+ userId: text('user_id')
109
+ .references(() => users.id, { onDelete: 'cascade' })
110
+ .notNull(),
111
+
112
+ createdAt: createdAt(),
113
+ },
114
+ (t) => [primaryKey({ columns: [t.documentId, t.chunkId] })],
115
+ );
116
+
117
+ export type NewDocumentChunk = typeof documentChunks.$inferInsert;
118
+ export type DocumentChunkItem = typeof documentChunks.$inferSelect;
@@ -6,11 +6,10 @@ import { createdAt } from './_helpers';
6
6
  import { agents, agentsFiles, agentsKnowledgeBases } from './agent';
7
7
  import { asyncTasks } from './asyncTask';
8
8
  import { chatGroups, chatGroupsAgents } from './chatGroup';
9
- import { documentChunks, documents } from './document';
10
- import { files, knowledgeBases } from './file';
9
+ import { documents, files, knowledgeBases } from './file';
11
10
  import { generationBatches, generationTopics, generations } from './generation';
12
11
  import { messageGroups, messages, messagesFiles } from './message';
13
- import { chunks, unstructuredChunks } from './rag';
12
+ import { chunks, documentChunks, unstructuredChunks } from './rag';
14
13
  import { sessionGroups, sessions } from './session';
15
14
  import { threads, topicDocuments, topics } from './topic';
16
15
  import { users } from './user';
@@ -6,7 +6,7 @@ import { createInsertSchema } from 'drizzle-zod';
6
6
  import { idGenerator } from '../utils/idGenerator';
7
7
  import { createdAt, timestamps, timestamptz } from './_helpers';
8
8
  import { chatGroups } from './chatGroup';
9
- import { documents } from './document';
9
+ import { documents } from './file';
10
10
  import { sessions } from './session';
11
11
  import { users } from './user';
12
12
 
@@ -66,7 +66,23 @@ export const fileRouter = router({
66
66
  const item = await ctx.fileModel.findById(input.id);
67
67
  if (!item) throw new TRPCError({ code: 'BAD_REQUEST', message: 'File not found' });
68
68
 
69
- return { ...item, url: await ctx.fileService.getFullFileUrl(item?.url) };
69
+ return {
70
+ chunkTaskId: item.chunkTaskId,
71
+ clientId: item.clientId,
72
+ createdAt: item.createdAt,
73
+ embeddingTaskId: item.embeddingTaskId,
74
+ fileHash: item.fileHash,
75
+ fileType: item.fileType,
76
+ id: item.id,
77
+ metadata: item.metadata,
78
+ name: item.name,
79
+ parentId: item.parentId,
80
+ size: item.size,
81
+ source: item.source,
82
+ updatedAt: item.updatedAt,
83
+ url: await ctx.fileService.getFullFileUrl(item.url),
84
+ userId: item.userId,
85
+ };
70
86
  }),
71
87
 
72
88
  getFileItemById: fileProcedure
@@ -92,15 +108,20 @@ export const fileRouter = router({
92
108
  const chunkCount = await ctx.chunkModel.countByFileId(input.id);
93
109
 
94
110
  return {
95
- ...item,
96
111
  chunkCount,
97
112
  chunkingError: chunkingTask?.error,
98
113
  chunkingStatus: chunkingTask?.status as AsyncTaskStatus,
114
+ createdAt: item.createdAt,
99
115
  embeddingError: embeddingTask?.error,
100
116
  embeddingStatus: embeddingTask?.status as AsyncTaskStatus,
117
+ fileType: item.fileType,
101
118
  finishEmbedding: embeddingTask?.status === AsyncTaskStatus.Success,
119
+ id: item.id,
102
120
  metadata: item.metadata as Record<string, any> | null | undefined,
121
+ name: item.name,
122
+ size: item.size,
103
123
  sourceType: 'file' as const,
124
+ updatedAt: item.updatedAt,
104
125
  url: await ctx.fileService.getFullFileUrl(item.url!),
105
126
  };
106
127
  }),
@@ -27,7 +27,16 @@ export class FileService {
27
27
  throw new Error('file not found');
28
28
  }
29
29
 
30
- return { ...item, type: item.fileType };
30
+ return {
31
+ createdAt: item.createdAt,
32
+ id: item.id,
33
+ name: item.name,
34
+ size: item.size,
35
+ source: item.source,
36
+ type: item.fileType,
37
+ updatedAt: item.updatedAt,
38
+ url: item.url,
39
+ };
31
40
  };
32
41
 
33
42
  removeFile = async (id: string): Promise<void> => {
@@ -1,105 +0,0 @@
1
- /* eslint-disable sort-keys-fix/sort-keys-fix */
2
- import type { LobeDocumentPage } from '@lobechat/types';
3
- import {
4
- index,
5
- integer,
6
- jsonb,
7
- pgTable,
8
- primaryKey,
9
- text,
10
- uniqueIndex,
11
- uuid,
12
- varchar,
13
- } from 'drizzle-orm/pg-core';
14
- import { createInsertSchema } from 'drizzle-zod';
15
-
16
- import { idGenerator } from '../utils/idGenerator';
17
- import { createdAt, timestamps } from './_helpers';
18
- import { files } from './file';
19
- import { chunks } from './rag';
20
- import { users } from './user';
21
-
22
- /**
23
- * 文档表 - 存储文件内容或网页搜索结果
24
- */
25
- export const documents = pgTable(
26
- 'documents',
27
- {
28
- id: varchar('id', { length: 30 })
29
- .$defaultFn(() => idGenerator('documents', 16))
30
- .primaryKey(),
31
-
32
- // 基本信息
33
- title: text('title'),
34
- content: text('content'),
35
- fileType: varchar('file_type', { length: 255 }).notNull(),
36
- filename: text('filename'),
37
-
38
- // 统计信息
39
- totalCharCount: integer('total_char_count').notNull(),
40
- totalLineCount: integer('total_line_count').notNull(),
41
-
42
- // 元数据
43
- metadata: jsonb('metadata').$type<Record<string, any>>(),
44
-
45
- // 页面/块数据
46
- pages: jsonb('pages').$type<LobeDocumentPage[]>(),
47
-
48
- // 来源类型
49
- sourceType: text('source_type', { enum: ['file', 'web', 'api'] }).notNull(),
50
- source: text('source').notNull(), // 文件路径或网页URL
51
-
52
- // 关联文件(可选)
53
- fileId: text('file_id').references(() => files.id, { onDelete: 'set null' }),
54
-
55
- // 用户关联
56
- userId: text('user_id')
57
- .references(() => users.id, { onDelete: 'cascade' })
58
- .notNull(),
59
- clientId: text('client_id'),
60
-
61
- editorData: jsonb('editor_data').$type<Record<string, any>>(),
62
-
63
- // 时间戳
64
- ...timestamps,
65
- },
66
- (table) => [
67
- index('documents_source_idx').on(table.source),
68
- index('documents_file_type_idx').on(table.fileType),
69
- index('documents_file_id_idx').on(table.fileId),
70
- uniqueIndex('documents_client_id_user_id_unique').on(table.clientId, table.userId),
71
- ],
72
- );
73
-
74
- export type NewDocument = typeof documents.$inferInsert;
75
- export type DocumentItem = typeof documents.$inferSelect;
76
- export const insertDocumentSchema = createInsertSchema(documents);
77
-
78
- /**
79
- * 文档块表 - 将文档内容分割成块并关联到 chunks 表,用于向量检索
80
- * 注意:此表可选,如果已经使用 pages 字段存储了文档块,可以不需要此表
81
- */
82
- export const documentChunks = pgTable(
83
- 'document_chunks',
84
- {
85
- documentId: varchar('document_id', { length: 30 })
86
- .references(() => documents.id, { onDelete: 'cascade' })
87
- .notNull(),
88
-
89
- chunkId: uuid('chunk_id')
90
- .references(() => chunks.id, { onDelete: 'cascade' })
91
- .notNull(),
92
-
93
- pageIndex: integer('page_index'),
94
-
95
- userId: text('user_id')
96
- .references(() => users.id, { onDelete: 'cascade' })
97
- .notNull(),
98
-
99
- createdAt: createdAt(),
100
- },
101
- (t) => [primaryKey({ columns: [t.documentId, t.chunkId] })],
102
- );
103
-
104
- export type NewDocumentChunk = typeof documentChunks.$inferInsert;
105
- export type DocumentChunkItem = typeof documentChunks.$inferSelect;