@lobehub/chat 1.123.3 → 1.123.4
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 +25 -0
- package/changelog/v1.json +9 -0
- package/package.json +1 -1
- package/src/app/(backend)/webapi/chat/[provider]/route.ts +1 -1
- package/src/app/(backend)/webapi/chat/vertexai/route.ts +1 -0
- package/src/libs/trpc/client/lambda.ts +76 -63
- package/src/app/(backend)/webapi/chat/anthropic/route.test.ts +0 -30
- package/src/app/(backend)/webapi/chat/anthropic/route.ts +0 -21
- package/src/app/(backend)/webapi/chat/google/route.test.ts +0 -35
- package/src/app/(backend)/webapi/chat/google/route.ts +0 -25
- package/src/app/(backend)/webapi/chat/groq/route.test.ts +0 -29
- package/src/app/(backend)/webapi/chat/groq/route.ts +0 -21
- package/src/app/(backend)/webapi/chat/openai/route.test.ts +0 -30
- package/src/app/(backend)/webapi/chat/openai/route.ts +0 -26
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.123.4](https://github.com/lobehub/lobe-chat/compare/v1.123.3...v1.123.4)
|
6
|
+
|
7
|
+
<sup>Released on **2025-09-05**</sup>
|
8
|
+
|
9
|
+
#### ♻ Code Refactoring
|
10
|
+
|
11
|
+
- **misc**: Remove edge runtime.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### Code refactoring
|
19
|
+
|
20
|
+
- **misc**: Remove edge runtime, closes [#9085](https://github.com/lobehub/lobe-chat/issues/9085) ([d3544f9](https://github.com/lobehub/lobe-chat/commit/d3544f9))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
5
30
|
### [Version 1.123.3](https://github.com/lobehub/lobe-chat/compare/v1.123.2...v1.123.3)
|
6
31
|
|
7
32
|
<sup>Released on **2025-09-05**</sup>
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.123.
|
3
|
+
"version": "1.123.4",
|
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",
|
@@ -11,7 +11,7 @@ import { ChatStreamPayload } from '@/types/openai/chat';
|
|
11
11
|
import { createErrorResponse } from '@/utils/errorResponse';
|
12
12
|
import { getTracePayload } from '@/utils/trace';
|
13
13
|
|
14
|
-
export const
|
14
|
+
export const maxDuration = 300;
|
15
15
|
|
16
16
|
export const POST = checkAuth(async (req: Request, { params, jwtPayload, createRuntime }) => {
|
17
17
|
const { provider } = await params;
|
@@ -6,6 +6,7 @@ import { safeParseJSON } from '@/utils/safeParseJSON';
|
|
6
6
|
|
7
7
|
import { POST as UniverseRoute } from '../[provider]/route';
|
8
8
|
|
9
|
+
export const maxDuration = 300;
|
9
10
|
// due to the Chinese region does not support accessing Google
|
10
11
|
// we need to use proxy to access it
|
11
12
|
// refs: https://github.com/google/generative-ai-js/issues/29#issuecomment-1866246513
|
@@ -1,81 +1,94 @@
|
|
1
1
|
import { ModelProvider } from '@lobechat/model-runtime';
|
2
|
-
import { createTRPCClient, httpBatchLink } from '@trpc/client';
|
2
|
+
import { TRPCLink, createTRPCClient, httpBatchLink } from '@trpc/client';
|
3
3
|
import { createTRPCReact } from '@trpc/react-query';
|
4
|
+
import { observable } from '@trpc/server/observable';
|
4
5
|
import debug from 'debug';
|
5
6
|
import superjson from 'superjson';
|
6
7
|
|
7
8
|
import { isDesktop } from '@/const/version';
|
8
9
|
import type { LambdaRouter } from '@/server/routers/lambda';
|
9
10
|
|
10
|
-
import { ErrorResponse } from './types';
|
11
|
-
|
12
11
|
const log = debug('lobe-image:lambda-client');
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
// handle error
|
14
|
+
const errorHandlingLink: TRPCLink<LambdaRouter> = () => {
|
15
|
+
return ({ op, next }) =>
|
16
|
+
observable((observer) =>
|
17
|
+
next(op).subscribe({
|
18
|
+
complete: () => observer.complete(),
|
19
|
+
error: async (err) => {
|
20
|
+
const showError = (op.context?.showNotification as boolean) ?? true;
|
21
|
+
|
22
|
+
if (showError) {
|
23
|
+
const status = err.data?.httpStatus as number;
|
24
|
+
|
25
|
+
const { loginRequired } = await import('@/components/Error/loginRequiredNotification');
|
26
|
+
const { fetchErrorNotification } = await import(
|
27
|
+
'@/components/Error/fetchErrorNotification'
|
28
|
+
);
|
29
|
+
|
30
|
+
switch (status) {
|
31
|
+
case 401: {
|
32
|
+
loginRequired.redirect();
|
33
|
+
break;
|
34
|
+
}
|
35
|
+
|
36
|
+
default: {
|
37
|
+
fetchErrorNotification.error({ errorMessage: err.message, status });
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
19
41
|
|
20
|
-
|
21
|
-
|
42
|
+
observer.error(err);
|
43
|
+
},
|
44
|
+
next: (value) => observer.next(value),
|
45
|
+
}),
|
46
|
+
);
|
47
|
+
};
|
22
48
|
|
23
|
-
|
24
|
-
|
49
|
+
// 2. httpBatchLink
|
50
|
+
const customHttpBatchLink = httpBatchLink({
|
51
|
+
fetch: async (input, init) => {
|
52
|
+
if (isDesktop) {
|
53
|
+
const { desktopRemoteRPCFetch } = await import('@/utils/electron/desktopRemoteRPCFetch');
|
25
54
|
|
26
55
|
// eslint-disable-next-line no-undef
|
27
|
-
const
|
28
|
-
|
29
|
-
if (
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
56
|
+
const res = await desktopRemoteRPCFetch(input as string, init as RequestInit);
|
57
|
+
|
58
|
+
if (res) return res;
|
59
|
+
}
|
60
|
+
|
61
|
+
// eslint-disable-next-line no-undef
|
62
|
+
return await fetch(input, init as RequestInit);
|
63
|
+
},
|
64
|
+
headers: async () => {
|
65
|
+
// dynamic import to avoid circular dependency
|
66
|
+
const { createHeaderWithAuth } = await import('@/services/_auth');
|
67
|
+
|
68
|
+
let provider: ModelProvider = ModelProvider.OpenAI;
|
69
|
+
// for image page, we need to get the provider from the store
|
70
|
+
log('Getting provider from store for image page: %s', location.pathname);
|
71
|
+
if (location.pathname === '/image') {
|
72
|
+
const { getImageStoreState } = await import('@/store/image');
|
73
|
+
const { imageGenerationConfigSelectors } = await import(
|
74
|
+
'@/store/image/slices/generationConfig/selectors'
|
75
|
+
);
|
76
|
+
provider = imageGenerationConfigSelectors.provider(getImageStoreState()) as ModelProvider;
|
77
|
+
log('Getting provider from store for image page: %s', provider);
|
78
|
+
}
|
79
|
+
|
80
|
+
// TODO: we need to support provider select for chat page
|
81
|
+
const headers = await createHeaderWithAuth({ provider });
|
82
|
+
log('Headers: %O', headers);
|
83
|
+
return headers;
|
84
|
+
},
|
85
|
+
maxURLLength: 2083,
|
86
|
+
transformer: superjson,
|
87
|
+
url: '/trpc/lambda',
|
88
|
+
});
|
39
89
|
|
40
|
-
|
41
|
-
|
42
|
-
loginRequired.redirect();
|
43
|
-
break;
|
44
|
-
}
|
45
|
-
default: {
|
46
|
-
fetchErrorNotification.error({ errorMessage: errorData.message, status });
|
47
|
-
}
|
48
|
-
}
|
49
|
-
});
|
50
|
-
|
51
|
-
return response;
|
52
|
-
},
|
53
|
-
headers: async () => {
|
54
|
-
// dynamic import to avoid circular dependency
|
55
|
-
const { createHeaderWithAuth } = await import('@/services/_auth');
|
56
|
-
|
57
|
-
let provider: ModelProvider = ModelProvider.OpenAI;
|
58
|
-
// for image page, we need to get the provider from the store
|
59
|
-
log('Getting provider from store for image page: %s', location.pathname);
|
60
|
-
if (location.pathname === '/image') {
|
61
|
-
const { getImageStoreState } = await import('@/store/image');
|
62
|
-
const { imageGenerationConfigSelectors } = await import(
|
63
|
-
'@/store/image/slices/generationConfig/selectors'
|
64
|
-
);
|
65
|
-
provider = imageGenerationConfigSelectors.provider(getImageStoreState()) as ModelProvider;
|
66
|
-
log('Getting provider from store for image page: %s', provider);
|
67
|
-
}
|
68
|
-
|
69
|
-
// TODO: we need to support provider select for chat page
|
70
|
-
const headers = await createHeaderWithAuth({ provider });
|
71
|
-
log('Headers: %O', headers);
|
72
|
-
return headers;
|
73
|
-
},
|
74
|
-
maxURLLength: 2083,
|
75
|
-
transformer: superjson,
|
76
|
-
url: '/trpc/lambda',
|
77
|
-
}),
|
78
|
-
];
|
90
|
+
// 3. assembly links
|
91
|
+
const links = [errorHandlingLink, customHttpBatchLink];
|
79
92
|
|
80
93
|
export const lambdaClient = createTRPCClient<LambdaRouter>({
|
81
94
|
links,
|
@@ -1,30 +0,0 @@
|
|
1
|
-
// @vitest-environment edge-runtime
|
2
|
-
import { describe, expect, it, vi } from 'vitest';
|
3
|
-
|
4
|
-
import { POST as UniverseRoute } from '../[provider]/route';
|
5
|
-
import { POST, preferredRegion, runtime } from './route';
|
6
|
-
|
7
|
-
// 模拟 '../[provider]/route'
|
8
|
-
vi.mock('../[provider]/route', () => ({
|
9
|
-
POST: vi.fn().mockResolvedValue('mocked response'),
|
10
|
-
}));
|
11
|
-
|
12
|
-
describe('Configuration tests', () => {
|
13
|
-
it('should have runtime set to "edge"', () => {
|
14
|
-
expect(runtime).toBe('edge');
|
15
|
-
});
|
16
|
-
|
17
|
-
it('should contain specific regions in preferredRegion', () => {
|
18
|
-
expect(preferredRegion).not.contain(['hk1']);
|
19
|
-
});
|
20
|
-
});
|
21
|
-
|
22
|
-
describe('Anthropic POST function tests', () => {
|
23
|
-
it('should call UniverseRoute with correct parameters', async () => {
|
24
|
-
const mockRequest = new Request('https://example.com', { method: 'POST' });
|
25
|
-
await POST(mockRequest);
|
26
|
-
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, {
|
27
|
-
params: Promise.resolve({ provider: 'anthropic' }),
|
28
|
-
});
|
29
|
-
});
|
30
|
-
});
|
@@ -1,21 +0,0 @@
|
|
1
|
-
import { POST as UniverseRoute } from '../[provider]/route';
|
2
|
-
|
3
|
-
export const runtime = 'edge';
|
4
|
-
|
5
|
-
export const preferredRegion = [
|
6
|
-
'bom1',
|
7
|
-
'cle1',
|
8
|
-
'cpt1',
|
9
|
-
'gru1',
|
10
|
-
'hnd1',
|
11
|
-
'iad1',
|
12
|
-
'icn1',
|
13
|
-
'kix1',
|
14
|
-
'pdx1',
|
15
|
-
'sfo1',
|
16
|
-
'sin1',
|
17
|
-
'syd1',
|
18
|
-
];
|
19
|
-
|
20
|
-
export const POST = async (req: Request) =>
|
21
|
-
UniverseRoute(req, { params: Promise.resolve({ provider: 'anthropic' }) });
|
@@ -1,35 +0,0 @@
|
|
1
|
-
// @vitest-environment edge-runtime
|
2
|
-
import { describe, expect, it, vi } from 'vitest';
|
3
|
-
|
4
|
-
import { POST as UniverseRoute } from '../[provider]/route';
|
5
|
-
import { POST, preferredRegion, runtime } from './route';
|
6
|
-
|
7
|
-
// 模拟 '../[provider]/route'
|
8
|
-
vi.mock('../[provider]/route', () => ({
|
9
|
-
POST: vi.fn().mockResolvedValue('mocked response'),
|
10
|
-
}));
|
11
|
-
|
12
|
-
describe('Configuration tests', () => {
|
13
|
-
it('should have runtime set to "edge"', () => {
|
14
|
-
expect(runtime).toBe('edge');
|
15
|
-
});
|
16
|
-
|
17
|
-
it('should contain specific regions in preferredRegion', () => {
|
18
|
-
expect(preferredRegion).not.contain(['hkg1']);
|
19
|
-
expect(preferredRegion).not.contain(['dub1']);
|
20
|
-
expect(preferredRegion).not.contain(['cdg1']);
|
21
|
-
expect(preferredRegion).not.contain(['fra1']);
|
22
|
-
expect(preferredRegion).not.contain(['lhr1']);
|
23
|
-
expect(preferredRegion).not.contain(['arn1']);
|
24
|
-
});
|
25
|
-
});
|
26
|
-
|
27
|
-
describe('Google POST function tests', () => {
|
28
|
-
it('should call UniverseRoute with correct parameters', async () => {
|
29
|
-
const mockRequest = new Request('https://example.com', { method: 'POST' });
|
30
|
-
await POST(mockRequest);
|
31
|
-
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, {
|
32
|
-
params: Promise.resolve({ provider: 'google' }),
|
33
|
-
});
|
34
|
-
});
|
35
|
-
});
|
@@ -1,25 +0,0 @@
|
|
1
|
-
import { POST as UniverseRoute } from '../[provider]/route';
|
2
|
-
|
3
|
-
export const runtime = 'edge';
|
4
|
-
|
5
|
-
// due to Gemini-1.5-pro is not available in Hong Kong, we need to set the preferred region to exclude "Hong Kong (hkg1)".
|
6
|
-
// the paid service of the Gemini API is required in the following regions until 8 July 2024. The free service is not available. Therefore, the regions is temporarily disabled.
|
7
|
-
// regions include Dublin (dub1, Ireland), Paris (cdg1, France), Frankfurt (fra1, Germany), London (lhr1, UK), and Stockholm (arn1, Sweden).
|
8
|
-
// refs: https://ai.google.dev/gemini-api/docs/available-regions
|
9
|
-
export const preferredRegion = [
|
10
|
-
'icn1',
|
11
|
-
'sin1',
|
12
|
-
'hnd1',
|
13
|
-
'kix1',
|
14
|
-
'bom1',
|
15
|
-
'cpt1',
|
16
|
-
'pdx1',
|
17
|
-
'cle1',
|
18
|
-
'syd1',
|
19
|
-
'iad1',
|
20
|
-
'sfo1',
|
21
|
-
'gru1',
|
22
|
-
];
|
23
|
-
|
24
|
-
export const POST = async (req: Request) =>
|
25
|
-
UniverseRoute(req, { params: Promise.resolve({ provider: 'google' }) });
|
@@ -1,29 +0,0 @@
|
|
1
|
-
// @vitest-environment edge-runtime
|
2
|
-
import { describe, expect, it, vi } from 'vitest';
|
3
|
-
|
4
|
-
import { POST as UniverseRoute } from '../[provider]/route';
|
5
|
-
import { POST, preferredRegion, runtime } from './route';
|
6
|
-
|
7
|
-
vi.mock('../[provider]/route', () => ({
|
8
|
-
POST: vi.fn().mockResolvedValue('mocked response'),
|
9
|
-
}));
|
10
|
-
|
11
|
-
describe('Configuration tests', () => {
|
12
|
-
it('should have runtime set to "edge"', () => {
|
13
|
-
expect(runtime).toBe('edge');
|
14
|
-
});
|
15
|
-
|
16
|
-
it('should contain specific regions in preferredRegion', () => {
|
17
|
-
expect(preferredRegion).not.contain(['hk1']);
|
18
|
-
});
|
19
|
-
});
|
20
|
-
|
21
|
-
describe('Groq POST function tests', () => {
|
22
|
-
it('should call UniverseRoute with correct parameters', async () => {
|
23
|
-
const mockRequest = new Request('https://example.com', { method: 'POST' });
|
24
|
-
await POST(mockRequest);
|
25
|
-
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, {
|
26
|
-
params: Promise.resolve({ provider: 'groq' }),
|
27
|
-
});
|
28
|
-
});
|
29
|
-
});
|
@@ -1,21 +0,0 @@
|
|
1
|
-
import { POST as UniverseRoute } from '../[provider]/route';
|
2
|
-
|
3
|
-
export const runtime = 'edge';
|
4
|
-
|
5
|
-
export const preferredRegion = [
|
6
|
-
'bom1',
|
7
|
-
'cle1',
|
8
|
-
'cpt1',
|
9
|
-
'gru1',
|
10
|
-
'hnd1',
|
11
|
-
'iad1',
|
12
|
-
'icn1',
|
13
|
-
'kix1',
|
14
|
-
'pdx1',
|
15
|
-
'sfo1',
|
16
|
-
'sin1',
|
17
|
-
'syd1',
|
18
|
-
];
|
19
|
-
|
20
|
-
export const POST = async (req: Request) =>
|
21
|
-
UniverseRoute(req, { params: Promise.resolve({ provider: 'groq' }) });
|
@@ -1,30 +0,0 @@
|
|
1
|
-
// @vitest-environment edge-runtime
|
2
|
-
import { describe, expect, it, vi } from 'vitest';
|
3
|
-
|
4
|
-
import { POST as UniverseRoute } from '../[provider]/route';
|
5
|
-
import { POST, preferredRegion, runtime } from './route';
|
6
|
-
|
7
|
-
// 模拟 '../[provider]/route'
|
8
|
-
vi.mock('../[provider]/route', () => ({
|
9
|
-
POST: vi.fn().mockResolvedValue('mocked response'),
|
10
|
-
}));
|
11
|
-
|
12
|
-
describe('Configuration tests', () => {
|
13
|
-
it('should have runtime set to "edge"', () => {
|
14
|
-
expect(runtime).toBe('edge');
|
15
|
-
});
|
16
|
-
|
17
|
-
it('should contain specific regions in preferredRegion', () => {
|
18
|
-
expect(preferredRegion).not.contain(['hkg1']);
|
19
|
-
});
|
20
|
-
});
|
21
|
-
|
22
|
-
describe('OpenAI POST function tests', () => {
|
23
|
-
it('should call UniverseRoute with correct parameters', async () => {
|
24
|
-
const mockRequest = new Request('https://example.com', { method: 'POST' });
|
25
|
-
await POST(mockRequest);
|
26
|
-
expect(UniverseRoute).toHaveBeenCalledWith(mockRequest, {
|
27
|
-
params: Promise.resolve({ provider: 'openai' }),
|
28
|
-
});
|
29
|
-
});
|
30
|
-
});
|
@@ -1,26 +0,0 @@
|
|
1
|
-
import { POST as UniverseRoute } from '../[provider]/route';
|
2
|
-
|
3
|
-
export const runtime = 'edge';
|
4
|
-
|
5
|
-
export const preferredRegion = [
|
6
|
-
'arn1',
|
7
|
-
'bom1',
|
8
|
-
'cdg1',
|
9
|
-
'cle1',
|
10
|
-
'cpt1',
|
11
|
-
'dub1',
|
12
|
-
'fra1',
|
13
|
-
'gru1',
|
14
|
-
'hnd1',
|
15
|
-
'iad1',
|
16
|
-
'icn1',
|
17
|
-
'kix1',
|
18
|
-
'lhr1',
|
19
|
-
'pdx1',
|
20
|
-
'sfo1',
|
21
|
-
'sin1',
|
22
|
-
'syd1',
|
23
|
-
];
|
24
|
-
|
25
|
-
export const POST = async (req: Request) =>
|
26
|
-
UniverseRoute(req, { params: Promise.resolve({ provider: 'openai' }) });
|