@lobehub/chat 1.12.16 → 1.12.18
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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/package.json +7 -7
- package/src/features/FileManager/FileList/EmptyStatus.tsx +4 -4
- package/src/features/FileManager/Header/UploadFileButton.tsx +4 -4
- package/src/layout/GlobalProvider/Locale.tsx +11 -1
- package/src/libs/trpc/index.ts +2 -2
- package/src/libs/trpc/middleware/{password.test.ts → jwtPayload.test.ts} +3 -22
- package/src/libs/trpc/middleware/jwtPayload.ts +14 -0
- package/src/libs/trpc/middleware/password.ts +0 -26
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 1.12.18](https://github.com/lobehub/lobe-chat/compare/v1.12.17...v1.12.18)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-08-25**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Fix dayjs error in en-US language.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Fix dayjs error in en-US language, closes [#3604](https://github.com/lobehub/lobe-chat/issues/3604) ([174f4df](https://github.com/lobehub/lobe-chat/commit/174f4df))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 1.12.17](https://github.com/lobehub/lobe-chat/compare/v1.12.16...v1.12.17)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2024-08-25**</sup>
|
|
33
|
+
|
|
34
|
+
#### 🐛 Bug Fixes
|
|
35
|
+
|
|
36
|
+
- **misc**: Fix multi file upload dupicate.
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### What's fixed
|
|
44
|
+
|
|
45
|
+
- **misc**: Fix multi file upload dupicate, closes [#3603](https://github.com/lobehub/lobe-chat/issues/3603) ([60dbed7](https://github.com/lobehub/lobe-chat/commit/60dbed7))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
### [Version 1.12.16](https://github.com/lobehub/lobe-chat/compare/v1.12.15...v1.12.16)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2024-08-24**</sup>
|
package/README.md
CHANGED
|
@@ -273,7 +273,7 @@ Our marketplace is not just a showcase platform but also a collaborative space.
|
|
|
273
273
|
| [Prompt Engineering Expert](https://chat-preview.lobehub.com/market?agent=ai-prompts-assistant)<br/><sup>By **[cyicz123](https://github.com/cyicz123)** on **2024-08-12**</sup> | Specializing in prompt optimization and design<br/>`prompt-engineering` `ai-interaction` `writing` `optimization` `consulting` |
|
|
274
274
|
| [Commit Message Generator](https://chat-preview.lobehub.com/market?agent=commit-assistant)<br/><sup>By **[cyicz123](https://github.com/cyicz123)** on **2024-08-12**</sup> | Expert at generating precise Git commit messages<br/>`programming` `git` `commit-message` `code-review` |
|
|
275
275
|
|
|
276
|
-
> 📊 Total agents: [<kbd>**
|
|
276
|
+
> 📊 Total agents: [<kbd>**317**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
|
|
277
277
|
|
|
278
278
|
<!-- AGENT LIST -->
|
|
279
279
|
|
package/README.zh-CN.md
CHANGED
|
@@ -261,7 +261,7 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
|
|
|
261
261
|
| [提示工程专家](https://chat-preview.lobehub.com/market?agent=ai-prompts-assistant)<br/><sup>By **[cyicz123](https://github.com/cyicz123)** on **2024-08-12**</sup> | 专精 Prompt 优化与设计<br/>`提示工程` `ai交互` `写作` `优化` `咨询` |
|
|
262
262
|
| [提交信息生成器](https://chat-preview.lobehub.com/market?agent=commit-assistant)<br/><sup>By **[cyicz123](https://github.com/cyicz123)** on **2024-08-12**</sup> | 擅长生成精准的 Git 提交信息<br/>`编程` `git` `提交信息` `代码审查` |
|
|
263
263
|
|
|
264
|
-
> 📊 Total agents: [<kbd>**
|
|
264
|
+
> 📊 Total agents: [<kbd>**317**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
|
|
265
265
|
|
|
266
266
|
<!-- AGENT LIST -->
|
|
267
267
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.18",
|
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"@aws-sdk/s3-request-presigner": "^3.637.0",
|
|
108
108
|
"@azure/core-rest-pipeline": "1.16.0",
|
|
109
109
|
"@azure/openai": "1.0.0-beta.12",
|
|
110
|
-
"@cfworker/json-schema": "^
|
|
110
|
+
"@cfworker/json-schema": "^2.0.0",
|
|
111
111
|
"@clerk/localizations": "2.0.0",
|
|
112
112
|
"@clerk/nextjs": "^5.3.3",
|
|
113
113
|
"@clerk/themes": "^2.1.21",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"@neondatabase/serverless": "^0.9.4",
|
|
125
125
|
"@next/third-parties": "^14.2.6",
|
|
126
126
|
"@sentry/nextjs": "^7.119.0",
|
|
127
|
-
"@t3-oss/env-nextjs": "^0.
|
|
127
|
+
"@t3-oss/env-nextjs": "^0.11.0",
|
|
128
128
|
"@tanstack/react-query": "^5.52.1",
|
|
129
129
|
"@trpc/client": "next",
|
|
130
130
|
"@trpc/next": "next",
|
|
@@ -143,7 +143,7 @@
|
|
|
143
143
|
"debug": "^4.3.6",
|
|
144
144
|
"dexie": "^3.2.7",
|
|
145
145
|
"diff": "^5.2.0",
|
|
146
|
-
"drizzle-orm": "^0.
|
|
146
|
+
"drizzle-orm": "^0.33.0",
|
|
147
147
|
"drizzle-zod": "^0.5.1",
|
|
148
148
|
"fast-deep-equal": "^3.1.3",
|
|
149
149
|
"file-type": "^19.4.1",
|
|
@@ -255,14 +255,14 @@
|
|
|
255
255
|
"consola": "^3.2.3",
|
|
256
256
|
"dotenv": "^16.4.5",
|
|
257
257
|
"dpdm": "^3.14.0",
|
|
258
|
-
"drizzle-kit": "^0.
|
|
258
|
+
"drizzle-kit": "^0.24.0",
|
|
259
259
|
"eslint": "^8.57.0",
|
|
260
260
|
"eslint-plugin-mdx": "^2.3.4",
|
|
261
261
|
"eslint-plugin-unused-imports": "4.0.1",
|
|
262
262
|
"fake-indexeddb": "^6.0.0",
|
|
263
263
|
"glob": "^11.0.0",
|
|
264
264
|
"gray-matter": "^4.0.3",
|
|
265
|
-
"happy-dom": "^
|
|
265
|
+
"happy-dom": "^15.0.0",
|
|
266
266
|
"husky": "^9.1.5",
|
|
267
267
|
"just-diff": "^6.0.2",
|
|
268
268
|
"lint-staged": "^15.2.9",
|
|
@@ -284,7 +284,7 @@
|
|
|
284
284
|
"vitest": "~1.2.2",
|
|
285
285
|
"vitest-canvas-mock": "^0.3.3"
|
|
286
286
|
},
|
|
287
|
-
"packageManager": "pnpm@9.
|
|
287
|
+
"packageManager": "pnpm@9.8.0",
|
|
288
288
|
"publishConfig": {
|
|
289
289
|
"access": "public",
|
|
290
290
|
"registry": "https://registry.npmjs.org"
|
|
@@ -102,8 +102,8 @@ const EmptyStatus = ({ showKnowledgeBase, knowledgeBaseId }: EmptyStatusProps) =
|
|
|
102
102
|
</Flexbox>
|
|
103
103
|
)}
|
|
104
104
|
<Upload
|
|
105
|
-
beforeUpload={async (
|
|
106
|
-
await pushDockFileList(
|
|
105
|
+
beforeUpload={async (file) => {
|
|
106
|
+
await pushDockFileList([file], knowledgeBaseId);
|
|
107
107
|
|
|
108
108
|
return false;
|
|
109
109
|
}}
|
|
@@ -122,8 +122,8 @@ const EmptyStatus = ({ showKnowledgeBase, knowledgeBaseId }: EmptyStatusProps) =
|
|
|
122
122
|
</Flexbox>
|
|
123
123
|
</Upload>
|
|
124
124
|
<Upload
|
|
125
|
-
beforeUpload={async (
|
|
126
|
-
await pushDockFileList(
|
|
125
|
+
beforeUpload={async (file) => {
|
|
126
|
+
await pushDockFileList([file], knowledgeBaseId);
|
|
127
127
|
|
|
128
128
|
return false;
|
|
129
129
|
}}
|
|
@@ -30,8 +30,8 @@ const UploadFileButton = ({ knowledgeBaseId }: { knowledgeBaseId?: string }) =>
|
|
|
30
30
|
key: 'upload-file',
|
|
31
31
|
label: (
|
|
32
32
|
<Upload
|
|
33
|
-
beforeUpload={async (
|
|
34
|
-
await pushDockFileList(
|
|
33
|
+
beforeUpload={async (file) => {
|
|
34
|
+
await pushDockFileList([file], knowledgeBaseId);
|
|
35
35
|
|
|
36
36
|
return false;
|
|
37
37
|
}}
|
|
@@ -47,8 +47,8 @@ const UploadFileButton = ({ knowledgeBaseId }: { knowledgeBaseId?: string }) =>
|
|
|
47
47
|
key: 'upload-folder',
|
|
48
48
|
label: (
|
|
49
49
|
<Upload
|
|
50
|
-
beforeUpload={async (
|
|
51
|
-
await pushDockFileList(
|
|
50
|
+
beforeUpload={async (file) => {
|
|
51
|
+
await pushDockFileList([file], knowledgeBaseId);
|
|
52
52
|
|
|
53
53
|
return false;
|
|
54
54
|
}}
|
|
@@ -37,7 +37,17 @@ const Locale = memo<LocaleLayoutProps>(({ children, defaultLang, antdLocale }) =
|
|
|
37
37
|
if (!lang) return;
|
|
38
38
|
|
|
39
39
|
// load default lang
|
|
40
|
-
|
|
40
|
+
let dayJSLocale;
|
|
41
|
+
try {
|
|
42
|
+
// dayjs locale is using `en` instead of `en-US`
|
|
43
|
+
// refs: https://github.com/lobehub/lobe-chat/issues/3396
|
|
44
|
+
const locale = lang!.toLowerCase() === 'en-us' ? 'en' : lang!.toLowerCase();
|
|
45
|
+
|
|
46
|
+
dayJSLocale = await import(`dayjs/locale/${locale}.js`);
|
|
47
|
+
} catch {
|
|
48
|
+
console.warn(`dayjs locale for ${lang} not found, fallback to en`);
|
|
49
|
+
dayJSLocale = await import(`dayjs/locale/en.js`);
|
|
50
|
+
}
|
|
41
51
|
|
|
42
52
|
dayjs.locale(dayJSLocale.default);
|
|
43
53
|
});
|
package/src/libs/trpc/index.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @link https://trpc.io/docs/v11/procedures
|
|
9
9
|
*/
|
|
10
10
|
import { trpc } from './init';
|
|
11
|
-
import {
|
|
11
|
+
import { jwtPayloadChecker } from './middleware/jwtPayload';
|
|
12
12
|
import { userAuth } from './middleware/userAuth';
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -27,7 +27,7 @@ export const publicProcedure = trpc.procedure;
|
|
|
27
27
|
export const authedProcedure = trpc.procedure.use(userAuth);
|
|
28
28
|
|
|
29
29
|
// procedure that asserts that the user add the password
|
|
30
|
-
export const passwordProcedure = trpc.procedure.use(
|
|
30
|
+
export const passwordProcedure = trpc.procedure.use(jwtPayloadChecker);
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Merge multiple routers together
|
|
@@ -3,15 +3,14 @@ import { TRPCError } from '@trpc/server';
|
|
|
3
3
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
4
|
|
|
5
5
|
import * as utils from '@/app/api/middleware/auth/utils';
|
|
6
|
-
import * as appConfig from '@/config/app';
|
|
7
6
|
import { createCallerFactory } from '@/libs/trpc';
|
|
8
7
|
import { trpc } from '@/libs/trpc/init';
|
|
9
8
|
import { AuthContext, createContextInner } from '@/server/context';
|
|
10
9
|
|
|
11
|
-
import {
|
|
10
|
+
import { jwtPayloadChecker } from './jwtPayload';
|
|
12
11
|
|
|
13
12
|
const appRouter = trpc.router({
|
|
14
|
-
protectedQuery: trpc.procedure.use(
|
|
13
|
+
protectedQuery: trpc.procedure.use(jwtPayloadChecker).query(async ({ ctx }) => {
|
|
15
14
|
return ctx.jwtPayload;
|
|
16
15
|
}),
|
|
17
16
|
});
|
|
@@ -38,23 +37,9 @@ describe('passwordChecker middleware', () => {
|
|
|
38
37
|
await expect(router.protectedQuery()).rejects.toThrow(new TRPCError({ code: 'UNAUTHORIZED' }));
|
|
39
38
|
});
|
|
40
39
|
|
|
41
|
-
it('should throw UNAUTHORIZED error if access code is not correct', async () => {
|
|
42
|
-
vi.spyOn(appConfig, 'getAppConfig').mockReturnValue({
|
|
43
|
-
ACCESS_CODES: ['123'],
|
|
44
|
-
} as any);
|
|
45
|
-
vi.spyOn(utils, 'getJWTPayload').mockResolvedValue({ accessCode: '456' });
|
|
46
|
-
|
|
47
|
-
ctx = await createContextInner({ authorizationHeader: 'Bearer token' });
|
|
48
|
-
router = createCaller(ctx);
|
|
49
|
-
|
|
50
|
-
await expect(router.protectedQuery()).rejects.toThrow(new TRPCError({ code: 'UNAUTHORIZED' }));
|
|
51
|
-
});
|
|
52
|
-
|
|
53
40
|
it('should call next with jwtPayload in context if access code is correct', async () => {
|
|
54
41
|
const jwtPayload = { accessCode: '123' };
|
|
55
|
-
|
|
56
|
-
ACCESS_CODES: ['123'],
|
|
57
|
-
} as any);
|
|
42
|
+
|
|
58
43
|
vi.spyOn(utils, 'getJWTPayload').mockResolvedValue(jwtPayload);
|
|
59
44
|
|
|
60
45
|
ctx = await createContextInner({ authorizationHeader: 'Bearer token' });
|
|
@@ -67,9 +52,6 @@ describe('passwordChecker middleware', () => {
|
|
|
67
52
|
|
|
68
53
|
it('should call next with jwtPayload in context if no access codes are set', async () => {
|
|
69
54
|
const jwtPayload = {};
|
|
70
|
-
vi.spyOn(appConfig, 'getAppConfig').mockReturnValue({
|
|
71
|
-
ACCESS_CODES: [],
|
|
72
|
-
} as any);
|
|
73
55
|
vi.spyOn(utils, 'getJWTPayload').mockResolvedValue(jwtPayload);
|
|
74
56
|
|
|
75
57
|
ctx = await createContextInner({ authorizationHeader: 'Bearer token' });
|
|
@@ -81,7 +63,6 @@ describe('passwordChecker middleware', () => {
|
|
|
81
63
|
});
|
|
82
64
|
it('should call next with jwtPayload in context if access codes is undefined', async () => {
|
|
83
65
|
const jwtPayload = {};
|
|
84
|
-
vi.spyOn(appConfig, 'getAppConfig').mockReturnValue({} as any);
|
|
85
66
|
vi.spyOn(utils, 'getJWTPayload').mockResolvedValue(jwtPayload);
|
|
86
67
|
|
|
87
68
|
ctx = await createContextInner({ authorizationHeader: 'Bearer token' });
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TRPCError } from '@trpc/server';
|
|
2
|
+
|
|
3
|
+
import { getJWTPayload } from '@/app/api/middleware/auth/utils';
|
|
4
|
+
import { trpc } from '@/libs/trpc/init';
|
|
5
|
+
|
|
6
|
+
export const jwtPayloadChecker = trpc.middleware(async (opts) => {
|
|
7
|
+
const { ctx } = opts;
|
|
8
|
+
|
|
9
|
+
if (!ctx.authorizationHeader) throw new TRPCError({ code: 'UNAUTHORIZED' });
|
|
10
|
+
|
|
11
|
+
const jwtPayload = await getJWTPayload(ctx.authorizationHeader);
|
|
12
|
+
|
|
13
|
+
return opts.next({ ctx: { jwtPayload } });
|
|
14
|
+
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { TRPCError } from '@trpc/server';
|
|
2
|
-
|
|
3
|
-
import { getJWTPayload } from '@/app/api/middleware/auth/utils';
|
|
4
|
-
import { getAppConfig } from '@/config/app';
|
|
5
|
-
import { trpc } from '@/libs/trpc/init';
|
|
6
|
-
|
|
7
|
-
export const passwordChecker = trpc.middleware(async (opts) => {
|
|
8
|
-
const { ACCESS_CODES } = getAppConfig();
|
|
9
|
-
|
|
10
|
-
const { ctx } = opts;
|
|
11
|
-
|
|
12
|
-
if (!ctx.authorizationHeader) throw new TRPCError({ code: 'UNAUTHORIZED' });
|
|
13
|
-
|
|
14
|
-
const jwtPayload = await getJWTPayload(ctx.authorizationHeader);
|
|
15
|
-
|
|
16
|
-
// if there are access codes, check if the user has set correct one
|
|
17
|
-
if (ACCESS_CODES && ACCESS_CODES.length > 0) {
|
|
18
|
-
const accessCode = jwtPayload.accessCode;
|
|
19
|
-
|
|
20
|
-
if (!accessCode || !ACCESS_CODES.includes(accessCode)) {
|
|
21
|
-
throw new TRPCError({ code: 'UNAUTHORIZED' });
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return opts.next({ ctx: { jwtPayload } });
|
|
26
|
-
});
|