@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.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +14 -0
- package/locales/ar/chat.json +2 -0
- package/locales/ar/file.json +2 -0
- package/locales/ar/models.json +17 -2
- package/locales/ar/tool.json +8 -0
- package/locales/bg-BG/chat.json +2 -0
- package/locales/bg-BG/file.json +2 -0
- package/locales/bg-BG/models.json +17 -2
- package/locales/bg-BG/tool.json +8 -0
- package/locales/de-DE/chat.json +2 -0
- package/locales/de-DE/file.json +2 -0
- package/locales/de-DE/models.json +17 -2
- package/locales/de-DE/tool.json +8 -0
- package/locales/en-US/chat.json +2 -0
- package/locales/en-US/file.json +2 -0
- package/locales/en-US/models.json +17 -2
- package/locales/en-US/tool.json +8 -0
- package/locales/es-ES/chat.json +2 -0
- package/locales/es-ES/file.json +2 -0
- package/locales/es-ES/models.json +17 -2
- package/locales/es-ES/tool.json +8 -0
- package/locales/fa-IR/chat.json +2 -0
- package/locales/fa-IR/file.json +2 -0
- package/locales/fa-IR/models.json +17 -2
- package/locales/fa-IR/tool.json +8 -0
- package/locales/fr-FR/chat.json +2 -0
- package/locales/fr-FR/file.json +2 -0
- package/locales/fr-FR/models.json +17 -2
- package/locales/fr-FR/tool.json +8 -0
- package/locales/it-IT/chat.json +2 -0
- package/locales/it-IT/file.json +2 -0
- package/locales/it-IT/models.json +17 -2
- package/locales/it-IT/tool.json +8 -0
- package/locales/ja-JP/chat.json +2 -0
- package/locales/ja-JP/file.json +2 -0
- package/locales/ja-JP/models.json +17 -2
- package/locales/ja-JP/tool.json +8 -0
- package/locales/ko-KR/chat.json +2 -0
- package/locales/ko-KR/file.json +2 -0
- package/locales/ko-KR/models.json +17 -2
- package/locales/ko-KR/tool.json +8 -0
- package/locales/nl-NL/chat.json +2 -0
- package/locales/nl-NL/file.json +2 -0
- package/locales/nl-NL/models.json +17 -2
- package/locales/nl-NL/tool.json +8 -0
- package/locales/pl-PL/chat.json +2 -0
- package/locales/pl-PL/file.json +2 -0
- package/locales/pl-PL/models.json +17 -2
- package/locales/pl-PL/tool.json +8 -0
- package/locales/pt-BR/chat.json +2 -0
- package/locales/pt-BR/file.json +2 -0
- package/locales/pt-BR/models.json +17 -2
- package/locales/pt-BR/tool.json +8 -0
- package/locales/ru-RU/chat.json +2 -0
- package/locales/ru-RU/file.json +2 -0
- package/locales/ru-RU/models.json +17 -2
- package/locales/ru-RU/tool.json +8 -0
- package/locales/tr-TR/chat.json +2 -0
- package/locales/tr-TR/file.json +2 -0
- package/locales/tr-TR/models.json +17 -2
- package/locales/tr-TR/tool.json +8 -0
- package/locales/vi-VN/chat.json +2 -0
- package/locales/vi-VN/file.json +2 -0
- package/locales/vi-VN/models.json +17 -2
- package/locales/vi-VN/tool.json +8 -0
- package/locales/zh-CN/chat.json +2 -0
- package/locales/zh-CN/file.json +2 -0
- package/locales/zh-CN/models.json +17 -2
- package/locales/zh-CN/tool.json +8 -0
- package/locales/zh-TW/chat.json +2 -0
- package/locales/zh-TW/file.json +2 -0
- package/locales/zh-TW/models.json +17 -2
- package/locales/zh-TW/tool.json +8 -0
- package/package.json +1 -1
- package/packages/database/src/models/apiKey.ts +2 -2
- package/packages/database/src/models/chunk.ts +1 -1
- package/packages/database/src/models/drizzleMigration.ts +1 -1
- package/packages/database/src/models/oauthHandoff.ts +19 -19
- package/packages/database/src/models/session.ts +10 -10
- package/packages/database/src/models/topic.ts +10 -10
- package/src/app/(backend)/middleware/auth/index.ts +7 -2
- package/src/app/(backend)/trpc/async/[trpc]/route.ts +9 -3
- package/src/app/(backend)/trpc/desktop/[trpc]/route.ts +9 -3
- package/src/app/(backend)/trpc/lambda/[trpc]/route.ts +9 -3
- package/src/app/(backend)/trpc/mobile/[trpc]/route.ts +9 -3
- package/src/app/(backend)/trpc/tools/[trpc]/route.ts +9 -3
- 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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|