@lobehub/chat 1.21.10 → 1.21.12

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 (36) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/package.json +2 -2
  3. package/src/app/(backend)/{api/openai → _deprecated}/createBizOpenAI/index.ts +1 -1
  4. package/src/app/(backend)/api/chat/[provider]/route.test.ts +7 -3
  5. package/src/app/(backend)/api/chat/[provider]/route.ts +3 -4
  6. package/src/app/(backend)/api/chat/models/[provider]/route.ts +3 -4
  7. package/src/app/(backend)/{api/middleware → middleware}/auth/index.test.ts +7 -4
  8. package/src/app/(backend)/{api/middleware → middleware}/auth/index.ts +3 -2
  9. package/src/app/(backend)/{api/middleware → middleware}/auth/utils.test.ts +1 -38
  10. package/src/app/(backend)/{api/middleware → middleware}/auth/utils.ts +1 -33
  11. package/src/app/(backend)/webapi/plugin/gateway/route.ts +2 -2
  12. package/src/app/(backend)/webapi/stt/openai/route.ts +1 -1
  13. package/src/app/(backend)/webapi/text-to-image/[provider]/route.ts +3 -3
  14. package/src/app/(backend)/webapi/tts/openai/route.ts +1 -1
  15. package/src/libs/agent-runtime/AgentRuntime.test.ts +1 -1
  16. package/src/libs/trpc/middleware/jwtPayload.test.ts +1 -1
  17. package/src/libs/trpc/middleware/jwtPayload.ts +1 -1
  18. package/src/libs/trpc/middleware/keyVaults.ts +1 -1
  19. package/src/{app/(backend)/api/chat/agentRuntime.test.ts → server/modules/AgentRuntime/index.test.ts} +1 -1
  20. package/src/server/routers/async/file.ts +1 -1
  21. package/src/server/routers/async/ragEval.ts +1 -1
  22. package/src/server/routers/lambda/chunk.ts +1 -1
  23. package/src/services/chat.ts +1 -1
  24. package/src/services/ollama.ts +1 -1
  25. package/src/store/chat/slices/message/actions/rag.ts +1 -1
  26. package/src/utils/server/jwt.test.ts +62 -0
  27. package/src/utils/server/jwt.ts +32 -0
  28. /package/src/app/(backend)/{api/openai → _deprecated}/createBizOpenAI/auth.test.ts +0 -0
  29. /package/src/app/(backend)/{api/openai → _deprecated}/createBizOpenAI/auth.ts +0 -0
  30. /package/src/app/(backend)/{api/openai → _deprecated}/createBizOpenAI/createAzureOpenai.ts +0 -0
  31. /package/src/app/(backend)/{api/openai → _deprecated}/createBizOpenAI/createOpenai.ts +0 -0
  32. /package/src/{app/(backend)/api/chat → server/modules/AgentRuntime}/apiKeyManager.test.ts +0 -0
  33. /package/src/{app/(backend)/api/chat → server/modules/AgentRuntime}/apiKeyManager.ts +0 -0
  34. /package/src/{app/(backend)/api/chat/agentRuntime.ts → server/modules/AgentRuntime/index.ts} +0 -0
  35. /package/src/{app/(backend)/api → utils}/errorResponse.test.ts +0 -0
  36. /package/src/{app/(backend)/api → utils}/errorResponse.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.21.12](https://github.com/lobehub/lobe-chat/compare/v1.21.11...v1.21.12)
6
+
7
+ <sup>Released on **2024-10-11**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Refactor the jwt code.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Code refactoring
19
+
20
+ - **misc**: Refactor the jwt code, closes [#4322](https://github.com/lobehub/lobe-chat/issues/4322) ([b7258b9](https://github.com/lobehub/lobe-chat/commit/b7258b9))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
30
+ ### [Version 1.21.11](https://github.com/lobehub/lobe-chat/compare/v1.21.10...v1.21.11)
31
+
32
+ <sup>Released on **2024-10-11**</sup>
33
+
34
+ #### ♻ Code Refactoring
35
+
36
+ - **misc**: Refactor the backend code for better organization.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### Code refactoring
44
+
45
+ - **misc**: Refactor the backend code for better organization, closes [#4287](https://github.com/lobehub/lobe-chat/issues/4287) ([9a369ac](https://github.com/lobehub/lobe-chat/commit/9a369ac))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ### [Version 1.21.10](https://github.com/lobehub/lobe-chat/compare/v1.21.9...v1.21.10)
6
56
 
7
57
  <sup>Released on **2024-10-11**</sup>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.21.10",
3
+ "version": "1.21.12",
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",
@@ -101,7 +101,7 @@
101
101
  "dependencies": {
102
102
  "@ant-design/icons": "^5.4.0",
103
103
  "@ant-design/pro-components": "^2.7.10",
104
- "@anthropic-ai/sdk": "^0.27.0",
104
+ "@anthropic-ai/sdk": "^0.29.0",
105
105
  "@auth/core": "^0.34.2",
106
106
  "@aws-sdk/client-bedrock-runtime": "^3.637.0",
107
107
  "@aws-sdk/client-s3": "^3.637.0",
@@ -2,8 +2,8 @@ import OpenAI from 'openai';
2
2
 
3
3
  import { getOpenAIAuthFromRequest } from '@/const/fetch';
4
4
  import { ChatErrorType, ErrorType } from '@/types/fetch';
5
+ import { createErrorResponse } from '@/utils/errorResponse';
5
6
 
6
- import { createErrorResponse } from '../../errorResponse';
7
7
  import { checkAuth } from './auth';
8
8
  import { createOpenai } from './createOpenai';
9
9
 
@@ -2,10 +2,11 @@
2
2
  import { getAuth } from '@clerk/nextjs/server';
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
- import { checkAuthMethod, getJWTPayload } from '@/app/(backend)/api/middleware/auth/utils';
5
+ import { checkAuthMethod } from '@/app/(backend)/middleware/auth/utils';
6
6
  import { LOBE_CHAT_AUTH_HEADER, OAUTH_AUTHORIZED } from '@/const/auth';
7
7
  import { AgentRuntime, LobeRuntimeAI } from '@/libs/agent-runtime';
8
8
  import { ChatErrorType } from '@/types/fetch';
9
+ import { getJWTPayload } from '@/utils/server/jwt';
9
10
 
10
11
  import { POST } from './route';
11
12
 
@@ -13,11 +14,14 @@ vi.mock('@clerk/nextjs/server', () => ({
13
14
  getAuth: vi.fn(),
14
15
  }));
15
16
 
16
- vi.mock('../../middleware/auth/utils', () => ({
17
- getJWTPayload: vi.fn(),
17
+ vi.mock('@/app/(backend)/middleware/auth/utils', () => ({
18
18
  checkAuthMethod: vi.fn(),
19
19
  }));
20
20
 
21
+ vi.mock('@/utils/server/jwt', () => ({
22
+ getJWTPayload: vi.fn(),
23
+ }));
24
+
21
25
  // 定义一个变量来存储 enableAuth 的值
22
26
  let enableClerk = false;
23
27
 
@@ -1,12 +1,11 @@
1
- import { createErrorResponse } from '@/app/(backend)/api/errorResponse';
1
+ import { checkAuth } from '@/app/(backend)/middleware/auth';
2
2
  import { AgentRuntime, ChatCompletionErrorPayload } from '@/libs/agent-runtime';
3
+ import { createTraceOptions, initAgentRuntimeWithUserPayload } from '@/server/modules/AgentRuntime';
3
4
  import { ChatErrorType } from '@/types/fetch';
4
5
  import { ChatStreamPayload } from '@/types/openai/chat';
6
+ import { createErrorResponse } from '@/utils/errorResponse';
5
7
  import { getTracePayload } from '@/utils/trace';
6
8
 
7
- import { checkAuth } from '../../middleware/auth';
8
- import { createTraceOptions, initAgentRuntimeWithUserPayload } from '../agentRuntime';
9
-
10
9
  export const runtime = 'edge';
11
10
 
12
11
  export const POST = checkAuth(async (req: Request, { params, jwtPayload, createRuntime }) => {
@@ -1,11 +1,10 @@
1
1
  import { NextResponse } from 'next/server';
2
2
 
3
- import { createErrorResponse } from '@/app/(backend)/api/errorResponse';
3
+ import { checkAuth } from '@/app/(backend)/middleware/auth';
4
4
  import { ChatCompletionErrorPayload, ModelProvider } from '@/libs/agent-runtime';
5
+ import { initAgentRuntimeWithUserPayload } from '@/server/modules/AgentRuntime';
5
6
  import { ChatErrorType } from '@/types/fetch';
6
-
7
- import { checkAuth } from '../../../middleware/auth';
8
- import { initAgentRuntimeWithUserPayload } from '../../agentRuntime';
7
+ import { createErrorResponse } from '@/utils/errorResponse';
9
8
 
10
9
  export const runtime = 'edge';
11
10
 
@@ -1,23 +1,26 @@
1
- import { getAuth } from '@clerk/nextjs/server';
2
1
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
2
 
4
- import { createErrorResponse } from '@/app/(backend)/api/errorResponse';
5
3
  import { AgentRuntimeError } from '@/libs/agent-runtime';
6
4
  import { ChatErrorType } from '@/types/fetch';
5
+ import { createErrorResponse } from '@/utils/errorResponse';
6
+ import { getJWTPayload } from '@/utils/server/jwt';
7
7
 
8
8
  import { RequestHandler, checkAuth } from './index';
9
- import { checkAuthMethod, getJWTPayload } from './utils';
9
+ import { checkAuthMethod } from './utils';
10
10
 
11
11
  vi.mock('@clerk/nextjs/server', () => ({
12
12
  getAuth: vi.fn(),
13
13
  }));
14
14
 
15
- vi.mock('@/app/(backend)/api/errorResponse', () => ({
15
+ vi.mock('@/utils/errorResponse', () => ({
16
16
  createErrorResponse: vi.fn(),
17
17
  }));
18
18
 
19
19
  vi.mock('./utils', () => ({
20
20
  checkAuthMethod: vi.fn(),
21
+ }));
22
+
23
+ vi.mock('@/utils/server/jwt', () => ({
21
24
  getJWTPayload: vi.fn(),
22
25
  }));
23
26
 
@@ -2,12 +2,13 @@ import { AuthObject } from '@clerk/backend';
2
2
  import { getAuth } from '@clerk/nextjs/server';
3
3
  import { NextRequest } from 'next/server';
4
4
 
5
- import { createErrorResponse } from '@/app/(backend)/api/errorResponse';
6
5
  import { JWTPayload, LOBE_CHAT_AUTH_HEADER, OAUTH_AUTHORIZED, enableClerk } from '@/const/auth';
7
6
  import { AgentRuntime, AgentRuntimeError, ChatCompletionErrorPayload } from '@/libs/agent-runtime';
8
7
  import { ChatErrorType } from '@/types/fetch';
8
+ import { createErrorResponse } from '@/utils/errorResponse';
9
+ import { getJWTPayload } from '@/utils/server/jwt';
9
10
 
10
- import { checkAuthMethod, getJWTPayload } from './utils';
11
+ import { checkAuthMethod } from './utils';
11
12
 
12
13
  type CreateRuntime = (jwtPayload: JWTPayload) => AgentRuntime;
13
14
  type RequestOptions = { createRuntime?: CreateRuntime; params: { provider: string } };
@@ -2,9 +2,8 @@ import { type AuthObject } from '@clerk/backend';
2
2
  import { beforeEach, describe, expect, it, vi } from 'vitest';
3
3
 
4
4
  import { getAppConfig } from '@/config/app';
5
- import { NON_HTTP_PREFIX } from '@/const/auth';
6
5
 
7
- import { checkAuthMethod, getJWTPayload } from './utils';
6
+ import { checkAuthMethod } from './utils';
8
7
 
9
8
  let enableClerkMock = false;
10
9
  let enableNextAuthMock = false;
@@ -27,42 +26,6 @@ vi.mock('@/config/app', () => ({
27
26
  getAppConfig: vi.fn(),
28
27
  }));
29
28
 
30
- describe('getJWTPayload', () => {
31
- it('should parse JWT payload for non-HTTPS token', async () => {
32
- const token = `${NON_HTTP_PREFIX}.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ`;
33
- const payload = await getJWTPayload(token);
34
- expect(payload).toEqual({
35
- sub: '1234567890',
36
- name: 'John Doe',
37
- iat: 1516239022,
38
- });
39
- });
40
-
41
- it('should verify and parse JWT payload for HTTPS token', async () => {
42
- const token =
43
- 'eyJhbGciOiJIUzI1NiJ9.eyJhY2Nlc3NDb2RlIjoiIiwidXNlcklkIjoiMDAxMzYyYzMtNDhjNS00NjM1LWJkM2ItODM3YmZmZjU4ZmMwIiwiYXBpS2V5IjoiYWJjIiwiZW5kcG9pbnQiOiJhYmMiLCJpYXQiOjE3MTY4MDIyMjUsImV4cCI6MTAwMDAwMDAwMDE3MTY4MDIwMDB9.FF0FxsE8Cajs-_hv5GD0TNUDwvekAkI9l_LL_IOPdGQ';
44
- const payload = await getJWTPayload(token);
45
- expect(payload).toEqual({
46
- accessCode: '',
47
- apiKey: 'abc',
48
- endpoint: 'abc',
49
- exp: 10000000001716802000,
50
- iat: 1716802225,
51
- userId: '001362c3-48c5-4635-bd3b-837bfff58fc0',
52
- });
53
- });
54
-
55
- it('should not verify success and parse JWT payload for dated token', async () => {
56
- const token =
57
- 'eyJhbGciOiJIUzI1NiJ9.eyJhY2Nlc3NDb2RlIjoiIiwidXNlcklkIjoiYWY3M2JhODktZjFhMy00YjliLWEwM2QtZGViZmZlMzE4NmQxIiwiYXBpS2V5IjoiYWJjIiwiZW5kcG9pbnQiOiJhYmMiLCJpYXQiOjE3MTY3OTk5ODAsImV4cCI6MTcxNjgwMDA4MH0.8AGFsLcwyrQG82kVUYOGFXHIwihm2n16ctyArKW9100';
58
- try {
59
- await getJWTPayload(token);
60
- } catch (e) {
61
- expect(e).toEqual(new TypeError('"exp" claim timestamp check failed'));
62
- }
63
- });
64
- });
65
-
66
29
  describe('checkAuthMethod', () => {
67
30
  beforeEach(() => {
68
31
  vi.mocked(getAppConfig).mockReturnValue({
@@ -1,42 +1,10 @@
1
1
  import { type AuthObject } from '@clerk/backend';
2
- import { importJWK, jwtVerify } from 'jose';
3
2
 
4
3
  import { getAppConfig } from '@/config/app';
5
- import {
6
- JWTPayload,
7
- JWT_SECRET_KEY,
8
- NON_HTTP_PREFIX,
9
- enableClerk,
10
- enableNextAuth,
11
- } from '@/const/auth';
4
+ import { enableClerk, enableNextAuth } from '@/const/auth';
12
5
  import { AgentRuntimeError } from '@/libs/agent-runtime';
13
6
  import { ChatErrorType } from '@/types/fetch';
14
7
 
15
- export const getJWTPayload = async (token: string): Promise<JWTPayload> => {
16
- //如果是 HTTP 协议发起的请求,直接解析 token
17
- // 这是一个非常 hack 的解决方案,未来要找更好的解决方案来处理这个问题
18
- // refs: https://github.com/lobehub/lobe-chat/pull/1238
19
- if (token.startsWith(NON_HTTP_PREFIX)) {
20
- const jwtParts = token.split('.');
21
-
22
- const payload = jwtParts[1];
23
-
24
- return JSON.parse(atob(payload));
25
- }
26
-
27
- const encoder = new TextEncoder();
28
- const secretKey = await crypto.subtle.digest('SHA-256', encoder.encode(JWT_SECRET_KEY));
29
-
30
- const jwkSecretKey = await importJWK(
31
- { k: Buffer.from(secretKey).toString('base64'), kty: 'oct' },
32
- 'HS256',
33
- );
34
-
35
- const { payload } = await jwtVerify(token, jwkSecretKey);
36
-
37
- return payload as JWTPayload;
38
- };
39
-
40
8
  interface CheckAuthParams {
41
9
  accessCode?: string;
42
10
  apiKey?: string;
@@ -1,14 +1,14 @@
1
1
  import { PluginRequestPayload } from '@lobehub/chat-plugin-sdk';
2
2
  import { createGatewayOnEdgeRuntime } from '@lobehub/chat-plugins-gateway';
3
3
 
4
- import { createErrorResponse } from '@/app/(backend)/api/errorResponse';
5
- import { getJWTPayload } from '@/app/(backend)/api/middleware/auth/utils';
6
4
  import { getAppConfig } from '@/config/app';
7
5
  import { LOBE_CHAT_AUTH_HEADER, OAUTH_AUTHORIZED, enableNextAuth } from '@/const/auth';
8
6
  import { LOBE_CHAT_TRACE_ID, TraceNameMap } from '@/const/trace';
9
7
  import { AgentRuntimeError } from '@/libs/agent-runtime';
10
8
  import { TraceClient } from '@/libs/traces';
11
9
  import { ChatErrorType, ErrorType } from '@/types/fetch';
10
+ import { createErrorResponse } from '@/utils/errorResponse';
11
+ import { getJWTPayload } from '@/utils/server/jwt';
12
12
  import { getTracePayload } from '@/utils/trace';
13
13
 
14
14
  import { parserPluginSettings } from './settings';
@@ -1,7 +1,7 @@
1
1
  import { OpenAISTTPayload } from '@lobehub/tts';
2
2
  import { createOpenaiAudioTranscriptions } from '@lobehub/tts/server';
3
3
 
4
- import { createBizOpenAI } from '@/app/(backend)/api/openai/createBizOpenAI';
4
+ import { createBizOpenAI } from '@/app/(backend)/_deprecated/createBizOpenAI';
5
5
 
6
6
  export const runtime = 'edge';
7
7
 
@@ -1,11 +1,11 @@
1
1
  import { NextResponse } from 'next/server';
2
2
 
3
- import { initAgentRuntimeWithUserPayload } from '@/app/(backend)/api/chat/agentRuntime';
4
- import { createErrorResponse } from '@/app/(backend)/api/errorResponse';
5
- import { checkAuth } from '@/app/(backend)/api/middleware/auth';
3
+ import { checkAuth } from '@/app/(backend)/middleware/auth';
6
4
  import { ChatCompletionErrorPayload } from '@/libs/agent-runtime';
7
5
  import { TextToImagePayload } from '@/libs/agent-runtime/types';
6
+ import { initAgentRuntimeWithUserPayload } from '@/server/modules/AgentRuntime';
8
7
  import { ChatErrorType } from '@/types/fetch';
8
+ import { createErrorResponse } from '@/utils/errorResponse';
9
9
 
10
10
  export const runtime = 'edge';
11
11
 
@@ -1,7 +1,7 @@
1
1
  import { OpenAITTSPayload } from '@lobehub/tts';
2
2
  import { createOpenaiAudioSpeech } from '@lobehub/tts/server';
3
3
 
4
- import { createBizOpenAI } from '@/app/(backend)/api/openai/createBizOpenAI';
4
+ import { createBizOpenAI } from '@/app/(backend)/_deprecated/createBizOpenAI';
5
5
 
6
6
  export const runtime = 'edge';
7
7
 
@@ -4,7 +4,6 @@ import { LangfuseGenerationClient, LangfuseTraceClient } from 'langfuse-core';
4
4
  import { ClientOptions } from 'openai';
5
5
  import { beforeEach, describe, expect, it, vi } from 'vitest';
6
6
 
7
- import { createTraceOptions } from '@/app/(backend)/api/chat/agentRuntime';
8
7
  import * as langfuseCfg from '@/config/langfuse';
9
8
  import { JWTPayload } from '@/const/auth';
10
9
  import { TraceNameMap } from '@/const/trace';
@@ -28,6 +27,7 @@ import {
28
27
  } from '@/libs/agent-runtime';
29
28
  import { LobeStepfunAI } from '@/libs/agent-runtime/stepfun';
30
29
  import LobeWenxinAI from '@/libs/agent-runtime/wenxin';
30
+ import { createTraceOptions } from '@/server/modules/AgentRuntime';
31
31
 
32
32
  import { AgentChatOptions } from './AgentRuntime';
33
33
  import { LobeBedrockAIParams } from './bedrock';
@@ -2,10 +2,10 @@
2
2
  import { TRPCError } from '@trpc/server';
3
3
  import { beforeEach, describe, expect, it, vi } from 'vitest';
4
4
 
5
- import * as utils from '@/app/(backend)/api/middleware/auth/utils';
6
5
  import { createCallerFactory } from '@/libs/trpc';
7
6
  import { trpc } from '@/libs/trpc/init';
8
7
  import { AuthContext, createContextInner } from '@/server/context';
8
+ import * as utils from '@/utils/server/jwt';
9
9
 
10
10
  import { jwtPayloadChecker } from './jwtPayload';
11
11
 
@@ -1,7 +1,7 @@
1
1
  import { TRPCError } from '@trpc/server';
2
2
 
3
- import { getJWTPayload } from '@/app/(backend)/api/middleware/auth/utils';
4
3
  import { trpc } from '@/libs/trpc/init';
4
+ import { getJWTPayload } from '@/utils/server/jwt';
5
5
 
6
6
  export const jwtPayloadChecker = trpc.middleware(async (opts) => {
7
7
  const { ctx } = opts;
@@ -1,7 +1,7 @@
1
1
  import { TRPCError } from '@trpc/server';
2
2
 
3
- import { getJWTPayload } from '@/app/(backend)/api/middleware/auth/utils';
4
3
  import { trpc } from '@/libs/trpc/init';
4
+ import { getJWTPayload } from '@/utils/server/jwt';
5
5
 
6
6
  export const keyVaults = trpc.middleware(async (opts) => {
7
7
  const { ctx } = opts;
@@ -27,7 +27,7 @@ import { AgentRuntime } from '@/libs/agent-runtime';
27
27
  import { LobeStepfunAI } from '@/libs/agent-runtime/stepfun';
28
28
  import LobeWenxinAI from '@/libs/agent-runtime/wenxin';
29
29
 
30
- import { initAgentRuntimeWithUserPayload } from './agentRuntime';
30
+ import { initAgentRuntimeWithUserPayload } from './index';
31
31
 
32
32
  // 模拟依赖项
33
33
  vi.mock('@/config/llm', () => ({
@@ -3,7 +3,6 @@ import { chunk } from 'lodash-es';
3
3
  import pMap from 'p-map';
4
4
  import { z } from 'zod';
5
5
 
6
- import { initAgentRuntimeWithUserPayload } from '@/app/(backend)/api/chat/agentRuntime';
7
6
  import { fileEnv } from '@/config/file';
8
7
  import { DEFAULT_EMBEDDING_MODEL } from '@/const/settings';
9
8
  import { ASYNC_TASK_TIMEOUT, AsyncTaskModel } from '@/database/server/models/asyncTask';
@@ -13,6 +12,7 @@ import { FileModel } from '@/database/server/models/file';
13
12
  import { NewChunkItem, NewEmbeddingsItem } from '@/database/server/schemas/lobechat';
14
13
  import { ModelProvider } from '@/libs/agent-runtime';
15
14
  import { asyncAuthedProcedure, asyncRouter as router } from '@/libs/trpc/async';
15
+ import { initAgentRuntimeWithUserPayload } from '@/server/modules/AgentRuntime';
16
16
  import { S3 } from '@/server/modules/S3';
17
17
  import { ChunkService } from '@/server/services/chunk';
18
18
  import {
@@ -2,7 +2,6 @@ import { TRPCError } from '@trpc/server';
2
2
  import OpenAI from 'openai';
3
3
  import { z } from 'zod';
4
4
 
5
- import { initAgentRuntimeWithUserPayload } from '@/app/(backend)/api/chat/agentRuntime';
6
5
  import { chainAnswerWithContext } from '@/chains/answerWithContext';
7
6
  import { DEFAULT_EMBEDDING_MODEL, DEFAULT_MODEL } from '@/const/settings';
8
7
  import { ChunkModel } from '@/database/server/models/chunk';
@@ -15,6 +14,7 @@ import {
15
14
  } from '@/database/server/models/ragEval';
16
15
  import { ModelProvider } from '@/libs/agent-runtime';
17
16
  import { asyncAuthedProcedure, asyncRouter as router } from '@/libs/trpc/async';
17
+ import { initAgentRuntimeWithUserPayload } from '@/server/modules/AgentRuntime';
18
18
  import { ChunkService } from '@/server/services/chunk';
19
19
  import { AsyncTaskError } from '@/types/asyncTask';
20
20
  import { EvalEvaluationStatus } from '@/types/eval';
@@ -1,7 +1,6 @@
1
1
  import { inArray } from 'drizzle-orm';
2
2
  import { z } from 'zod';
3
3
 
4
- import { initAgentRuntimeWithUserPayload } from '@/app/(backend)/api/chat/agentRuntime';
5
4
  import { DEFAULT_EMBEDDING_MODEL } from '@/const/settings';
6
5
  import { serverDB } from '@/database/server';
7
6
  import { AsyncTaskModel } from '@/database/server/models/asyncTask';
@@ -13,6 +12,7 @@ import { knowledgeBaseFiles } from '@/database/server/schemas/lobechat';
13
12
  import { ModelProvider } from '@/libs/agent-runtime';
14
13
  import { authedProcedure, router } from '@/libs/trpc';
15
14
  import { keyVaults } from '@/libs/trpc/middleware/keyVaults';
15
+ import { initAgentRuntimeWithUserPayload } from '@/server/modules/AgentRuntime';
16
16
  import { ChunkService } from '@/server/services/chunk';
17
17
  import { SemanticSearchSchema } from '@/types/rag';
18
18
 
@@ -2,7 +2,6 @@ import { PluginRequestPayload, createHeadersWithPluginSettings } from '@lobehub/
2
2
  import { produce } from 'immer';
3
3
  import { merge } from 'lodash-es';
4
4
 
5
- import { createErrorResponse } from '@/app/(backend)/api/errorResponse';
6
5
  import { DEFAULT_MODEL_PROVIDER_LIST } from '@/config/modelProviders';
7
6
  import { INBOX_GUIDE_SYSTEMROLE } from '@/const/guide';
8
7
  import { INBOX_SESSION_ID } from '@/const/session';
@@ -24,6 +23,7 @@ import { ChatErrorType } from '@/types/fetch';
24
23
  import { ChatMessage, MessageToolCall } from '@/types/message';
25
24
  import type { ChatStreamPayload, OpenAIChatMessage } from '@/types/openai/chat';
26
25
  import { UserMessageContentPart } from '@/types/openai/chat';
26
+ import { createErrorResponse } from '@/utils/errorResponse';
27
27
  import { FetchSSEOptions, fetchSSE, getMessageError } from '@/utils/fetch';
28
28
  import { genToolCallingName } from '@/utils/toolCall';
29
29
  import { createTraceHeader, getTraceId } from '@/utils/trace';
@@ -1,10 +1,10 @@
1
1
  import { ListResponse, Ollama as OllamaBrowser, ProgressResponse } from 'ollama/browser';
2
2
 
3
- import { createErrorResponse } from '@/app/(backend)/api/errorResponse';
4
3
  import { ModelProvider } from '@/libs/agent-runtime';
5
4
  import { useUserStore } from '@/store/user';
6
5
  import { keyVaultsConfigSelectors } from '@/store/user/selectors';
7
6
  import { ChatErrorType } from '@/types/fetch';
7
+ import { createErrorResponse } from '@/utils/errorResponse';
8
8
  import { getMessageError } from '@/utils/fetch';
9
9
 
10
10
  const DEFAULT_BASE_URL = 'http://127.0.0.1:11434';
@@ -67,7 +67,7 @@ export const chatRag: StateCreator<ChatStore, [['zustand/devtools', never]], [],
67
67
  // 1. get the rewrite query
68
68
  let rewriteQuery = message?.ragQuery || userQuery;
69
69
 
70
- // only rewrite query length is less than 10 characters
70
+ // only rewrite query length is less than 10 characters, refs: https://github.com/lobehub/lobe-chat/pull/4288
71
71
  // if there is no ragQuery and there is a chat history
72
72
  // we need to rewrite the user message to get better results
73
73
  if (rewriteQuery.length < 10 && !message?.ragQuery && messages.length > 0) {
@@ -0,0 +1,62 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+
3
+ import { NON_HTTP_PREFIX } from '@/const/auth';
4
+
5
+ import { getJWTPayload } from './jwt';
6
+
7
+ let enableClerkMock = false;
8
+ let enableNextAuthMock = false;
9
+
10
+ vi.mock('@/const/auth', async (importOriginal) => {
11
+ const data = await importOriginal();
12
+
13
+ return {
14
+ ...(data as any),
15
+ get enableClerk() {
16
+ return enableClerkMock;
17
+ },
18
+ get enableNextAuth() {
19
+ return enableNextAuthMock;
20
+ },
21
+ };
22
+ });
23
+
24
+ vi.mock('@/config/app', () => ({
25
+ getAppConfig: vi.fn(),
26
+ }));
27
+
28
+ describe('getJWTPayload', () => {
29
+ it('should parse JWT payload for non-HTTPS token', async () => {
30
+ const token = `${NON_HTTP_PREFIX}.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ`;
31
+ const payload = await getJWTPayload(token);
32
+ expect(payload).toEqual({
33
+ sub: '1234567890',
34
+ name: 'John Doe',
35
+ iat: 1516239022,
36
+ });
37
+ });
38
+
39
+ it('should verify and parse JWT payload for HTTPS token', async () => {
40
+ const token =
41
+ 'eyJhbGciOiJIUzI1NiJ9.eyJhY2Nlc3NDb2RlIjoiIiwidXNlcklkIjoiMDAxMzYyYzMtNDhjNS00NjM1LWJkM2ItODM3YmZmZjU4ZmMwIiwiYXBpS2V5IjoiYWJjIiwiZW5kcG9pbnQiOiJhYmMiLCJpYXQiOjE3MTY4MDIyMjUsImV4cCI6MTAwMDAwMDAwMDE3MTY4MDIwMDB9.FF0FxsE8Cajs-_hv5GD0TNUDwvekAkI9l_LL_IOPdGQ';
42
+ const payload = await getJWTPayload(token);
43
+ expect(payload).toEqual({
44
+ accessCode: '',
45
+ apiKey: 'abc',
46
+ endpoint: 'abc',
47
+ exp: 10000000001716802000,
48
+ iat: 1716802225,
49
+ userId: '001362c3-48c5-4635-bd3b-837bfff58fc0',
50
+ });
51
+ });
52
+
53
+ it('should not verify success and parse JWT payload for dated token', async () => {
54
+ const token =
55
+ 'eyJhbGciOiJIUzI1NiJ9.eyJhY2Nlc3NDb2RlIjoiIiwidXNlcklkIjoiYWY3M2JhODktZjFhMy00YjliLWEwM2QtZGViZmZlMzE4NmQxIiwiYXBpS2V5IjoiYWJjIiwiZW5kcG9pbnQiOiJhYmMiLCJpYXQiOjE3MTY3OTk5ODAsImV4cCI6MTcxNjgwMDA4MH0.8AGFsLcwyrQG82kVUYOGFXHIwihm2n16ctyArKW9100';
56
+ try {
57
+ await getJWTPayload(token);
58
+ } catch (e) {
59
+ expect(e).toEqual(new TypeError('"exp" claim timestamp check failed'));
60
+ }
61
+ });
62
+ });
@@ -0,0 +1,32 @@
1
+ import { importJWK, jwtVerify } from 'jose';
2
+
3
+ import {
4
+ JWTPayload,
5
+ JWT_SECRET_KEY,
6
+ NON_HTTP_PREFIX,
7
+ } from '@/const/auth';
8
+
9
+ export const getJWTPayload = async (token: string): Promise<JWTPayload> => {
10
+ //如果是 HTTP 协议发起的请求,直接解析 token
11
+ // 这是一个非常 hack 的解决方案,未来要找更好的解决方案来处理这个问题
12
+ // refs: https://github.com/lobehub/lobe-chat/pull/1238
13
+ if (token.startsWith(NON_HTTP_PREFIX)) {
14
+ const jwtParts = token.split('.');
15
+
16
+ const payload = jwtParts[1];
17
+
18
+ return JSON.parse(atob(payload));
19
+ }
20
+
21
+ const encoder = new TextEncoder();
22
+ const secretKey = await crypto.subtle.digest('SHA-256', encoder.encode(JWT_SECRET_KEY));
23
+
24
+ const jwkSecretKey = await importJWK(
25
+ { k: Buffer.from(secretKey).toString('base64'), kty: 'oct' },
26
+ 'HS256',
27
+ );
28
+
29
+ const { payload } = await jwtVerify(token, jwkSecretKey);
30
+
31
+ return payload as JWTPayload;
32
+ };