@lobehub/lobehub 2.0.0-next.60 → 2.0.0-next.62

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 (88) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +14 -0
  3. package/locales/ar/chat.json +2 -0
  4. package/locales/ar/file.json +2 -0
  5. package/locales/ar/models.json +17 -2
  6. package/locales/ar/tool.json +8 -0
  7. package/locales/bg-BG/chat.json +2 -0
  8. package/locales/bg-BG/file.json +2 -0
  9. package/locales/bg-BG/models.json +17 -2
  10. package/locales/bg-BG/tool.json +8 -0
  11. package/locales/de-DE/chat.json +2 -0
  12. package/locales/de-DE/file.json +2 -0
  13. package/locales/de-DE/models.json +17 -2
  14. package/locales/de-DE/tool.json +8 -0
  15. package/locales/en-US/chat.json +2 -0
  16. package/locales/en-US/file.json +2 -0
  17. package/locales/en-US/models.json +17 -2
  18. package/locales/en-US/tool.json +8 -0
  19. package/locales/es-ES/chat.json +2 -0
  20. package/locales/es-ES/file.json +2 -0
  21. package/locales/es-ES/models.json +17 -2
  22. package/locales/es-ES/tool.json +8 -0
  23. package/locales/fa-IR/chat.json +2 -0
  24. package/locales/fa-IR/file.json +2 -0
  25. package/locales/fa-IR/models.json +17 -2
  26. package/locales/fa-IR/tool.json +8 -0
  27. package/locales/fr-FR/chat.json +2 -0
  28. package/locales/fr-FR/file.json +2 -0
  29. package/locales/fr-FR/models.json +17 -2
  30. package/locales/fr-FR/tool.json +8 -0
  31. package/locales/it-IT/chat.json +2 -0
  32. package/locales/it-IT/file.json +2 -0
  33. package/locales/it-IT/models.json +17 -2
  34. package/locales/it-IT/tool.json +8 -0
  35. package/locales/ja-JP/chat.json +2 -0
  36. package/locales/ja-JP/file.json +2 -0
  37. package/locales/ja-JP/models.json +17 -2
  38. package/locales/ja-JP/tool.json +8 -0
  39. package/locales/ko-KR/chat.json +2 -0
  40. package/locales/ko-KR/file.json +2 -0
  41. package/locales/ko-KR/models.json +17 -2
  42. package/locales/ko-KR/tool.json +8 -0
  43. package/locales/nl-NL/chat.json +2 -0
  44. package/locales/nl-NL/file.json +2 -0
  45. package/locales/nl-NL/models.json +17 -2
  46. package/locales/nl-NL/tool.json +8 -0
  47. package/locales/pl-PL/chat.json +2 -0
  48. package/locales/pl-PL/file.json +2 -0
  49. package/locales/pl-PL/models.json +17 -2
  50. package/locales/pl-PL/tool.json +8 -0
  51. package/locales/pt-BR/chat.json +2 -0
  52. package/locales/pt-BR/file.json +2 -0
  53. package/locales/pt-BR/models.json +17 -2
  54. package/locales/pt-BR/tool.json +8 -0
  55. package/locales/ru-RU/chat.json +2 -0
  56. package/locales/ru-RU/file.json +2 -0
  57. package/locales/ru-RU/models.json +17 -2
  58. package/locales/ru-RU/tool.json +8 -0
  59. package/locales/tr-TR/chat.json +2 -0
  60. package/locales/tr-TR/file.json +2 -0
  61. package/locales/tr-TR/models.json +17 -2
  62. package/locales/tr-TR/tool.json +8 -0
  63. package/locales/vi-VN/chat.json +2 -0
  64. package/locales/vi-VN/file.json +2 -0
  65. package/locales/vi-VN/models.json +17 -2
  66. package/locales/vi-VN/tool.json +8 -0
  67. package/locales/zh-CN/chat.json +2 -0
  68. package/locales/zh-CN/file.json +2 -0
  69. package/locales/zh-CN/models.json +17 -2
  70. package/locales/zh-CN/tool.json +8 -0
  71. package/locales/zh-TW/chat.json +2 -0
  72. package/locales/zh-TW/file.json +2 -0
  73. package/locales/zh-TW/models.json +17 -2
  74. package/locales/zh-TW/tool.json +8 -0
  75. package/package.json +1 -1
  76. package/packages/database/src/models/apiKey.ts +2 -2
  77. package/packages/database/src/models/chunk.ts +1 -1
  78. package/packages/database/src/models/drizzleMigration.ts +1 -1
  79. package/packages/database/src/models/oauthHandoff.ts +19 -19
  80. package/packages/database/src/models/session.ts +10 -10
  81. package/packages/database/src/models/topic.ts +10 -10
  82. package/src/app/(backend)/middleware/auth/index.ts +7 -2
  83. package/src/app/(backend)/trpc/async/[trpc]/route.ts +9 -3
  84. package/src/app/(backend)/trpc/desktop/[trpc]/route.ts +9 -3
  85. package/src/app/(backend)/trpc/lambda/[trpc]/route.ts +9 -3
  86. package/src/app/(backend)/trpc/mobile/[trpc]/route.ts +9 -3
  87. package/src/app/(backend)/trpc/tools/[trpc]/route.ts +9 -3
  88. package/src/libs/trpc/utils/request-adapter.ts +20 -0
@@ -72,7 +72,7 @@ export class TopicModel {
72
72
 
73
73
  const keywordLowerCase = keyword.toLowerCase();
74
74
 
75
- // 查询标题匹配的主题
75
+ // Query topics matching by title
76
76
  const topicsByTitle = await this.db.query.topics.findMany({
77
77
  orderBy: [desc(topics.updatedAt)],
78
78
  where: and(
@@ -82,7 +82,7 @@ export class TopicModel {
82
82
  ),
83
83
  });
84
84
 
85
- // 查询消息内容匹配的主题ID
85
+ // Query topic IDs matching by message content
86
86
  const topicIdsByMessages = await this.db
87
87
  .select({ topicId: messages.topicId })
88
88
  .from(messages)
@@ -96,19 +96,19 @@ export class TopicModel {
96
96
  ),
97
97
  )
98
98
  .groupBy(messages.topicId);
99
- // 如果没有通过消息内容找到主题,直接返回标题匹配的主题
99
+ // If no topics found by message content, return topics matching by title
100
100
  if (topicIdsByMessages.length === 0) {
101
101
  return topicsByTitle;
102
102
  }
103
103
 
104
- // 查询通过消息内容找到的主题
104
+ // Query topics found by message content
105
105
  const topicIds = topicIdsByMessages.map((t) => t.topicId);
106
106
  const topicsByMessages = await this.db.query.topics.findMany({
107
107
  orderBy: [desc(topics.updatedAt)],
108
108
  where: and(eq(topics.userId, this.userId), inArray(topics.id, topicIds)),
109
109
  });
110
110
 
111
- // 合并结果并去重
111
+ // Merge results and deduplicate
112
112
  const allTopics = [...topicsByTitle];
113
113
  const existingIds = new Set(topicsByTitle.map((t) => t.id));
114
114
 
@@ -118,7 +118,7 @@ export class TopicModel {
118
118
  }
119
119
  }
120
120
 
121
- // 按更新时间排序
121
+ // Sort by update time
122
122
  return allTopics.sort(
123
123
  (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),
124
124
  );
@@ -199,9 +199,9 @@ export class TopicModel {
199
199
  };
200
200
 
201
201
  batchCreate = async (topicParams: (CreateTopicParams & { id?: string })[]) => {
202
- // 开始一个事务
202
+ // Start a transaction
203
203
  return this.db.transaction(async (tx) => {
204
- // topics 表中批量插入新的 topics
204
+ // Batch insert new topics into the topics table
205
205
  const createdTopics = await tx
206
206
  .insert(topics)
207
207
  .values(
@@ -216,7 +216,7 @@ export class TopicModel {
216
216
  )
217
217
  .returning();
218
218
 
219
- // 对每个新创建的 topic,更新关联的 messages topicId
219
+ // For each newly created topic, update the topicId of associated messages
220
220
  await Promise.all(
221
221
  createdTopics.map(async (topic, index) => {
222
222
  const messageIds = topicParams[index].messages;
@@ -255,7 +255,7 @@ export class TopicModel {
255
255
  })
256
256
  .returning();
257
257
 
258
- // 查找与原始 topic 关联的 messages
258
+ // Find messages associated with the original topic
259
259
  const originalMessages = await tx
260
260
  .select()
261
261
  .from(messages)
@@ -33,10 +33,15 @@ export type RequestHandler = (
33
33
 
34
34
  export const checkAuth =
35
35
  (handler: RequestHandler) => async (req: Request, options: RequestOptions) => {
36
+ // Clone the request to avoid "Response body object should not be disturbed or locked" error
37
+ // in Next.js 16 when the body stream has been consumed by Next.js internal mechanisms
38
+ // This ensures the handler can safely read the request body
39
+ const clonedReq = req.clone();
40
+
36
41
  // we have a special header to debug the api endpoint in development mode
37
42
  const isDebugApi = req.headers.get('lobe-auth-dev-backend-api') === '1';
38
43
  if (process.env.NODE_ENV === 'development' && isDebugApi) {
39
- return handler(req, { ...options, jwtPayload: { userId: 'DEV_USER' } });
44
+ return handler(clonedReq, { ...options, jwtPayload: { userId: 'DEV_USER' } });
40
45
  }
41
46
 
42
47
  let jwtPayload: ClientSecretPayload;
@@ -107,5 +112,5 @@ export const checkAuth =
107
112
  return createErrorResponse(errorType, { error, ...res, provider: params?.provider });
108
113
  }
109
114
 
110
- return handler(req, { ...options, jwtPayload });
115
+ return handler(clonedReq, { ...options, jwtPayload });
111
116
  };
@@ -3,10 +3,15 @@ import type { NextRequest } from 'next/server';
3
3
 
4
4
  import { pino } from '@/libs/logger';
5
5
  import { createAsyncRouteContext } from '@/libs/trpc/async/context';
6
+ import { prepareRequestForTRPC } from '@/libs/trpc/utils/request-adapter';
6
7
  import { asyncRouter } from '@/server/routers/async';
7
8
 
8
- const handler = (req: NextRequest) =>
9
- fetchRequestHandler({
9
+ const handler = (req: NextRequest) => {
10
+ // Clone the request to avoid "Response body object should not be disturbed or locked" error
11
+ // in Next.js 16 when the body stream has been consumed by Next.js internal mechanisms
12
+ const preparedReq = prepareRequestForTRPC(req);
13
+
14
+ return fetchRequestHandler({
10
15
  // 避免请求之间互相影响
11
16
  // https://github.com/lobehub/lobe-chat/discussions/7442#discussioncomment-13658563
12
17
  allowBatching: false,
@@ -23,8 +28,9 @@ const handler = (req: NextRequest) =>
23
28
  console.error(error);
24
29
  },
25
30
 
26
- req,
31
+ req: preparedReq,
27
32
  router: asyncRouter,
28
33
  });
34
+ };
29
35
 
30
36
  export { handler as GET, handler as POST };
@@ -3,10 +3,15 @@ import type { NextRequest } from 'next/server';
3
3
 
4
4
  import { pino } from '@/libs/logger';
5
5
  import { createLambdaContext } from '@/libs/trpc/lambda/context';
6
+ import { prepareRequestForTRPC } from '@/libs/trpc/utils/request-adapter';
6
7
  import { desktopRouter } from '@/server/routers/desktop';
7
8
 
8
- const handler = (req: NextRequest) =>
9
- fetchRequestHandler({
9
+ const handler = (req: NextRequest) => {
10
+ // Clone the request to avoid "Response body object should not be disturbed or locked" error
11
+ // in Next.js 16 when the body stream has been consumed by Next.js internal mechanisms
12
+ const preparedReq = prepareRequestForTRPC(req);
13
+
14
+ return fetchRequestHandler({
10
15
  /**
11
16
  * @link https://trpc.io/docs/v11/context
12
17
  */
@@ -19,7 +24,7 @@ const handler = (req: NextRequest) =>
19
24
  console.error(error);
20
25
  },
21
26
 
22
- req,
27
+ req: preparedReq,
23
28
  responseMeta({ ctx }) {
24
29
  const headers = ctx?.resHeaders;
25
30
 
@@ -27,5 +32,6 @@ const handler = (req: NextRequest) =>
27
32
  },
28
33
  router: desktopRouter,
29
34
  });
35
+ };
30
36
 
31
37
  export { handler as GET, handler as POST };
@@ -3,10 +3,15 @@ import type { NextRequest } from 'next/server';
3
3
 
4
4
  import { pino } from '@/libs/logger';
5
5
  import { createLambdaContext } from '@/libs/trpc/lambda/context';
6
+ import { prepareRequestForTRPC } from '@/libs/trpc/utils/request-adapter';
6
7
  import { lambdaRouter } from '@/server/routers/lambda';
7
8
 
8
- const handler = (req: NextRequest) =>
9
- fetchRequestHandler({
9
+ const handler = (req: NextRequest) => {
10
+ // Clone the request to avoid "Response body object should not be disturbed or locked" error
11
+ // in Next.js 16 when the body stream has been consumed by Next.js internal mechanisms
12
+ const preparedReq = prepareRequestForTRPC(req);
13
+
14
+ return fetchRequestHandler({
10
15
  /**
11
16
  * @link https://trpc.io/docs/v11/context
12
17
  */
@@ -19,7 +24,7 @@ const handler = (req: NextRequest) =>
19
24
  console.error(error);
20
25
  },
21
26
 
22
- req,
27
+ req: preparedReq,
23
28
  responseMeta({ ctx }) {
24
29
  const headers = ctx?.resHeaders;
25
30
 
@@ -27,5 +32,6 @@ const handler = (req: NextRequest) =>
27
32
  },
28
33
  router: lambdaRouter,
29
34
  });
35
+ };
30
36
 
31
37
  export { handler as GET, handler as POST };
@@ -3,10 +3,15 @@ import type { NextRequest } from 'next/server';
3
3
 
4
4
  import { pino } from '@/libs/logger';
5
5
  import { createLambdaContext } from '@/libs/trpc/lambda/context';
6
+ import { prepareRequestForTRPC } from '@/libs/trpc/utils/request-adapter';
6
7
  import { mobileRouter } from '@/server/routers/mobile';
7
8
 
8
- const handler = (req: NextRequest) =>
9
- fetchRequestHandler({
9
+ const handler = (req: NextRequest) => {
10
+ // Clone the request to avoid "Response body object should not be disturbed or locked" error
11
+ // in Next.js 16 when the body stream has been consumed by Next.js internal mechanisms
12
+ const preparedReq = prepareRequestForTRPC(req);
13
+
14
+ return fetchRequestHandler({
10
15
  /**
11
16
  * @link https://trpc.io/docs/v11/context
12
17
  */
@@ -19,7 +24,7 @@ const handler = (req: NextRequest) =>
19
24
  console.error(error);
20
25
  },
21
26
 
22
- req,
27
+ req: preparedReq,
23
28
  responseMeta({ ctx }) {
24
29
  const headers = ctx?.resHeaders;
25
30
 
@@ -27,5 +32,6 @@ const handler = (req: NextRequest) =>
27
32
  },
28
33
  router: mobileRouter,
29
34
  });
35
+ };
30
36
 
31
37
  export { handler as GET, handler as POST };
@@ -3,10 +3,15 @@ import type { NextRequest } from 'next/server';
3
3
 
4
4
  import { pino } from '@/libs/logger';
5
5
  import { createLambdaContext } from '@/libs/trpc/lambda/context';
6
+ import { prepareRequestForTRPC } from '@/libs/trpc/utils/request-adapter';
6
7
  import { toolsRouter } from '@/server/routers/tools';
7
8
 
8
- const handler = (req: NextRequest) =>
9
- fetchRequestHandler({
9
+ const handler = (req: NextRequest) => {
10
+ // Clone the request to avoid "Response body object should not be disturbed or locked" error
11
+ // in Next.js 16 when the body stream has been consumed by Next.js internal mechanisms
12
+ const preparedReq = prepareRequestForTRPC(req);
13
+
14
+ return fetchRequestHandler({
10
15
  /**
11
16
  * @link https://trpc.io/docs/v11/context
12
17
  */
@@ -19,8 +24,9 @@ const handler = (req: NextRequest) =>
19
24
  console.error(error);
20
25
  },
21
26
 
22
- req,
27
+ req: preparedReq,
23
28
  router: toolsRouter,
24
29
  });
30
+ };
25
31
 
26
32
  export { handler as GET, handler as POST };
@@ -0,0 +1,20 @@
1
+ import { NextRequest } from 'next/server';
2
+
3
+ /**
4
+ * Prepare Request object for tRPC fetchRequestHandler
5
+ *
6
+ * This function solves the "Response body object should not be disturbed or locked" error
7
+ * that occurs in Next.js 16 when the request body stream has been consumed or locked
8
+ * by Next.js internal mechanisms.
9
+ *
10
+ * By cloning the Request object, we create an independent body stream that tRPC can safely read.
11
+ *
12
+ * @see https://github.com/vercel/next.js/issues/83453
13
+ * @param req - The original NextRequest object
14
+ * @returns A cloned Request object with an independent body stream
15
+ */
16
+ export function prepareRequestForTRPC(req: NextRequest): Request {
17
+ // Clone the Request to create an independent body stream
18
+ // This ensures tRPC can read the body even if the original request's body was disturbed
19
+ return req.clone();
20
+ }