@lobehub/lobehub 2.0.0-next.68 → 2.0.0-next.69
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/packages/const/src/version.ts +0 -5
- package/packages/database/src/models/__tests__/chunk.test.ts +38 -0
- package/src/app/(backend)/api/webhooks/clerk/route.ts +1 -2
- package/src/app/[variants]/(main)/(mobile)/me/(home)/__tests__/useCategory.test.tsx +0 -20
- package/src/app/[variants]/(main)/(mobile)/me/(home)/features/useCategory.tsx +4 -33
- package/src/app/[variants]/(main)/(mobile)/me/profile/features/Category.tsx +18 -23
- package/src/app/[variants]/(main)/(mobile)/me/settings/features/useCategory.tsx +5 -15
- package/src/app/[variants]/(main)/discover/(detail)/provider/[...slugs]/features/Sidebar/ActionButton/ProviderConfig.tsx +4 -11
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/ModelSelect/index.tsx +12 -27
- package/src/app/[variants]/(main)/image/layout.tsx +0 -4
- package/src/app/[variants]/(main)/profile/hooks/useCategory.tsx +10 -13
- package/src/app/[variants]/(main)/profile/stats/features/ShareButton/Preview.tsx +2 -14
- package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +2 -3
- package/src/app/[variants]/(main)/settings/_layout/SettingsContent.tsx +1 -12
- package/src/app/[variants]/(main)/settings/_layout/type.ts +0 -1
- package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +8 -16
- package/src/app/[variants]/(main)/settings/page.tsx +3 -7
- package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/index.tsx +2 -4
- package/src/app/[variants]/(main)/settings/storage/index.tsx +1 -9
- package/src/app/[variants]/(main)/settings/system-agent/index.tsx +1 -2
- package/src/components/InvalidAPIKey/APIKeyForm/useApiKey.ts +0 -12
- package/src/config/featureFlags/schema.test.ts +1 -3
- package/src/config/featureFlags/schema.ts +0 -3
- package/src/features/ChatInput/ActionBar/Knowledge/index.tsx +2 -3
- package/src/features/ChatInput/ActionBar/Search/index.tsx +5 -7
- package/src/features/ChatInput/ActionBar/Upload/index.tsx +1 -3
- package/src/features/Conversation/Messages/Assistant/index.tsx +1 -1
- package/src/features/Conversation/components/ShareMessageModal/index.tsx +3 -8
- package/src/features/DevPanel/PostgresViewer/usePgTable.ts +3 -11
- package/src/features/ModelSwitchPanel/index.tsx +9 -24
- package/src/features/ShareModal/index.tsx +7 -13
- package/src/features/User/UserPanel/PanelContent.tsx +6 -8
- package/src/hooks/useCheckPluginsIsInstalled.ts +1 -4
- package/src/hooks/useFetchGroups.ts +1 -4
- package/src/hooks/useFetchInstalledPlugins.ts +1 -4
- package/src/hooks/useFetchMessages.ts +1 -4
- package/src/hooks/useFetchSessions.ts +1 -4
- package/src/hooks/useFetchThreads.ts +1 -5
- package/src/hooks/useFetchTopics.ts +1 -4
- package/src/hooks/useInterceptingRoutes.test.ts +0 -19
- package/src/hooks/useInterceptingRoutes.ts +1 -7
- package/src/layout/GlobalProvider/StoreInitialization.tsx +2 -4
- package/src/services/_auth.ts +2 -11
- package/src/services/_header.ts +2 -10
- package/src/services/chat/chat.test.ts +53 -10
- package/src/services/chat/clientModelRuntime.test.ts +108 -172
- package/src/services/chat/contextEngineering.ts +2 -2
- package/src/services/config.ts +2 -2
- package/src/store/aiInfra/slices/aiProvider/action.ts +3 -4
- package/src/store/chat/slices/thread/action.ts +2 -2
- package/src/store/global/selectors/systemStatus.test.ts +0 -98
- package/src/store/global/selectors/systemStatus.ts +0 -30
- package/src/store/serverConfig/selectors.test.ts +2 -2
- package/src/store/serverConfig/store.test.ts +0 -1
- package/src/app/[variants]/(main)/settings/storage/IndexedDBStorage.tsx +0 -55
- package/src/features/ChatInput/ActionBar/Upload/ClientMode.tsx +0 -62
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
|
|
3
|
-
import { INBOX_SESSION_ID } from '@/const/session';
|
|
4
|
-
import { isDeprecatedEdition } from '@/const/version';
|
|
5
3
|
import { useIsMobile } from '@/hooks/useIsMobile';
|
|
6
4
|
import { useQueryRoute } from '@/hooks/useQueryRoute';
|
|
7
5
|
import { useAgentStore } from '@/store/agent';
|
|
8
|
-
import { ChatSettingsTabs
|
|
6
|
+
import { ChatSettingsTabs } from '@/store/global/initialState';
|
|
9
7
|
import { useSessionStore } from '@/store/session';
|
|
10
8
|
|
|
11
9
|
export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Meta) => {
|
|
@@ -15,10 +13,6 @@ export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Met
|
|
|
15
13
|
const router = useQueryRoute();
|
|
16
14
|
|
|
17
15
|
return useMemo(() => {
|
|
18
|
-
if (isDeprecatedEdition && activeId === INBOX_SESSION_ID) {
|
|
19
|
-
return () => router.push(`/settings?active=${SettingsTabs.Agent}`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
16
|
if (isMobile) return () => router.push('/chat/settings', { query: { session: activeId } });
|
|
23
17
|
|
|
24
18
|
return () => {
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { enableNextAuth } from '@lobechat/const';
|
|
3
4
|
import { useRouter } from 'next/navigation';
|
|
4
5
|
import { memo } from 'react';
|
|
5
6
|
import { useTranslation } from 'react-i18next';
|
|
6
7
|
import { createStoreUpdater } from 'zustand-utils';
|
|
7
8
|
|
|
8
|
-
import { enableNextAuth } from '@/const/auth';
|
|
9
9
|
import { useIsMobile } from '@/hooks/useIsMobile';
|
|
10
10
|
import { useAgentStore } from '@/store/agent';
|
|
11
11
|
import { useAiInfraStore } from '@/store/aiInfra';
|
|
12
12
|
import { useGlobalStore } from '@/store/global';
|
|
13
|
-
import { systemStatusSelectors } from '@/store/global/selectors';
|
|
14
13
|
import { useServerConfigStore } from '@/store/serverConfig';
|
|
15
14
|
import { serverConfigSelectors } from '@/store/serverConfig/selectors';
|
|
16
15
|
import { useUserStore } from '@/store/user';
|
|
@@ -54,8 +53,7 @@ const StoreInitialization = memo(() => {
|
|
|
54
53
|
* IMPORTANT: Explicitly convert to boolean to avoid passing null/undefined downstream,
|
|
55
54
|
* which would cause unnecessary API requests with invalid login state.
|
|
56
55
|
*/
|
|
57
|
-
const
|
|
58
|
-
const isLoginOnInit = isDBInited ? Boolean(enableNextAuth ? isSignedIn : isLogin) : false;
|
|
56
|
+
const isLoginOnInit = Boolean(enableNextAuth ? isSignedIn : isLogin);
|
|
59
57
|
|
|
60
58
|
// init inbox agent and default agent config
|
|
61
59
|
useInitAgentStore(isLoginOnInit, serverConfig.defaultAgent?.config);
|
package/src/services/_auth.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LOBE_CHAT_AUTH_HEADER
|
|
1
|
+
import { LOBE_CHAT_AUTH_HEADER } from '@lobechat/const';
|
|
2
2
|
import {
|
|
3
3
|
AWSBedrockKeyVault,
|
|
4
4
|
AzureOpenAIKeyVault,
|
|
@@ -119,16 +119,7 @@ interface AuthParams {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
export const createPayloadWithKeyVaults = (provider: string) => {
|
|
122
|
-
let keyVaults = {};
|
|
123
|
-
|
|
124
|
-
// TODO: remove this condition in V2.0
|
|
125
|
-
if (isDeprecatedEdition) {
|
|
126
|
-
keyVaults = keyVaultsConfigSelectors.getVaultByProvider(provider as any)(
|
|
127
|
-
useUserStore.getState(),
|
|
128
|
-
);
|
|
129
|
-
} else {
|
|
130
|
-
keyVaults = aiProviderSelectors.providerKeyVaults(provider)(useAiInfraStore.getState()) || {};
|
|
131
|
-
}
|
|
122
|
+
let keyVaults = aiProviderSelectors.providerKeyVaults(provider)(useAiInfraStore.getState()) || {};
|
|
132
123
|
|
|
133
124
|
const runtimeProvider = resolveRuntimeProvider(provider);
|
|
134
125
|
|
package/src/services/_header.ts
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
OPENAI_API_KEY_HEADER_KEY,
|
|
5
5
|
OPENAI_END_POINT,
|
|
6
6
|
} from '@/const/fetch';
|
|
7
|
-
import { isDeprecatedEdition } from '@/const/version';
|
|
8
7
|
import { aiProviderSelectors, useAiInfraStore } from '@/store/aiInfra';
|
|
9
8
|
import { useUserStore } from '@/store/user';
|
|
10
9
|
import { keyVaultsConfigSelectors } from '@/store/user/selectors';
|
|
@@ -17,16 +16,9 @@ import { keyVaultsConfigSelectors } from '@/store/user/selectors';
|
|
|
17
16
|
export const createHeaderWithOpenAI = (header?: HeadersInit): HeadersInit => {
|
|
18
17
|
const state = useUserStore.getState();
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
const keyVaults: Record<string, any> =
|
|
20
|
+
aiProviderSelectors.providerKeyVaults('openai')(useAiInfraStore.getState()) || {};
|
|
21
21
|
|
|
22
|
-
// TODO: remove this condition in V2.0
|
|
23
|
-
if (isDeprecatedEdition) {
|
|
24
|
-
keyVaults = keyVaultsConfigSelectors.getVaultByProvider('openai' as any)(
|
|
25
|
-
useUserStore.getState(),
|
|
26
|
-
);
|
|
27
|
-
} else {
|
|
28
|
-
keyVaults = aiProviderSelectors.providerKeyVaults('openai')(useAiInfraStore.getState()) || {};
|
|
29
|
-
}
|
|
30
22
|
// eslint-disable-next-line no-undef
|
|
31
23
|
return {
|
|
32
24
|
...header,
|
|
@@ -278,15 +278,16 @@ describe('ChatService', () => {
|
|
|
278
278
|
|
|
279
279
|
describe('should handle content correctly for vision models', () => {
|
|
280
280
|
it('should include image content when with vision model', async () => {
|
|
281
|
+
// Mock helpers to return true for vision support (must be first)
|
|
282
|
+
const helpers = await import('./helper');
|
|
283
|
+
vi.spyOn(helpers, 'isCanUseVision').mockReturnValue(true);
|
|
284
|
+
|
|
281
285
|
// Mock utility functions used in processImageList
|
|
282
286
|
const { parseDataUri } = await import('@lobechat/utils/uriParser');
|
|
283
287
|
const { isDesktopLocalStaticServerUrl } = await import('@lobechat/utils/url');
|
|
284
288
|
vi.mocked(parseDataUri).mockReturnValue({ type: 'url', base64: null, mimeType: null });
|
|
285
289
|
vi.mocked(isDesktopLocalStaticServerUrl).mockReturnValue(false); // Not a local URL
|
|
286
290
|
|
|
287
|
-
// Mock aiModelSelectors to return true for vision support
|
|
288
|
-
vi.spyOn(aiModelSelectors, 'isModelSupportVision').mockReturnValue(() => true);
|
|
289
|
-
|
|
290
291
|
const messages = [
|
|
291
292
|
{
|
|
292
293
|
content: 'Hello',
|
|
@@ -315,13 +316,23 @@ describe('ChatService', () => {
|
|
|
315
316
|
{
|
|
316
317
|
content: [
|
|
317
318
|
{
|
|
318
|
-
text:
|
|
319
|
+
text: `Hello
|
|
320
|
+
|
|
321
|
+
<!-- SYSTEM CONTEXT (NOT PART OF USER QUERY) -->
|
|
322
|
+
<context.instruction>following part contains context information injected by the system. Please follow these instructions:
|
|
323
|
+
|
|
324
|
+
1. Always prioritize handling user-visible content.
|
|
325
|
+
2. the context is only required when user's queries rely on it.
|
|
326
|
+
</context.instruction>
|
|
327
|
+
<files_info>
|
|
328
|
+
<images>
|
|
329
|
+
<images_docstring>here are user upload images you can refer to</images_docstring>
|
|
330
|
+
<image name="abc.png" url="http://example.com/image.jpg"></image>
|
|
331
|
+
</images>
|
|
332
|
+
</files_info>
|
|
333
|
+
<!-- END SYSTEM CONTEXT -->`,
|
|
319
334
|
type: 'text',
|
|
320
335
|
},
|
|
321
|
-
{
|
|
322
|
-
image_url: { detail: 'auto', url: 'http://example.com/image.jpg' },
|
|
323
|
-
type: 'image_url',
|
|
324
|
-
},
|
|
325
336
|
],
|
|
326
337
|
role: 'user',
|
|
327
338
|
},
|
|
@@ -417,7 +428,21 @@ describe('ChatService', () => {
|
|
|
417
428
|
{
|
|
418
429
|
content: [
|
|
419
430
|
{
|
|
420
|
-
text:
|
|
431
|
+
text: `Hello
|
|
432
|
+
|
|
433
|
+
<!-- SYSTEM CONTEXT (NOT PART OF USER QUERY) -->
|
|
434
|
+
<context.instruction>following part contains context information injected by the system. Please follow these instructions:
|
|
435
|
+
|
|
436
|
+
1. Always prioritize handling user-visible content.
|
|
437
|
+
2. the context is only required when user's queries rely on it.
|
|
438
|
+
</context.instruction>
|
|
439
|
+
<files_info>
|
|
440
|
+
<images>
|
|
441
|
+
<images_docstring>here are user upload images you can refer to</images_docstring>
|
|
442
|
+
<image name="local-image.png" url="http://127.0.0.1:3000/uploads/image.png"></image>
|
|
443
|
+
</images>
|
|
444
|
+
</files_info>
|
|
445
|
+
<!-- END SYSTEM CONTEXT -->`,
|
|
421
446
|
type: 'text',
|
|
422
447
|
},
|
|
423
448
|
{
|
|
@@ -432,6 +457,8 @@ describe('ChatService', () => {
|
|
|
432
457
|
},
|
|
433
458
|
],
|
|
434
459
|
model: 'gpt-4-vision-preview',
|
|
460
|
+
enabledSearch: undefined,
|
|
461
|
+
tools: undefined,
|
|
435
462
|
},
|
|
436
463
|
undefined,
|
|
437
464
|
);
|
|
@@ -491,7 +518,21 @@ describe('ChatService', () => {
|
|
|
491
518
|
{
|
|
492
519
|
content: [
|
|
493
520
|
{
|
|
494
|
-
text:
|
|
521
|
+
text: `Hello
|
|
522
|
+
|
|
523
|
+
<!-- SYSTEM CONTEXT (NOT PART OF USER QUERY) -->
|
|
524
|
+
<context.instruction>following part contains context information injected by the system. Please follow these instructions:
|
|
525
|
+
|
|
526
|
+
1. Always prioritize handling user-visible content.
|
|
527
|
+
2. the context is only required when user's queries rely on it.
|
|
528
|
+
</context.instruction>
|
|
529
|
+
<files_info>
|
|
530
|
+
<images>
|
|
531
|
+
<images_docstring>here are user upload images you can refer to</images_docstring>
|
|
532
|
+
<image name="remote-image.jpg" url="https://example.com/remote-image.jpg"></image>
|
|
533
|
+
</images>
|
|
534
|
+
</files_info>
|
|
535
|
+
<!-- END SYSTEM CONTEXT -->`,
|
|
495
536
|
type: 'text',
|
|
496
537
|
},
|
|
497
538
|
{
|
|
@@ -503,6 +544,8 @@ describe('ChatService', () => {
|
|
|
503
544
|
},
|
|
504
545
|
],
|
|
505
546
|
model: 'gpt-4-vision-preview',
|
|
547
|
+
enabledSearch: undefined,
|
|
548
|
+
tools: undefined,
|
|
506
549
|
},
|
|
507
550
|
undefined,
|
|
508
551
|
);
|
|
@@ -18,14 +18,10 @@ import {
|
|
|
18
18
|
LobeZhipuAI,
|
|
19
19
|
ModelRuntime,
|
|
20
20
|
} from '@lobechat/model-runtime';
|
|
21
|
-
import { merge } from 'lodash-es';
|
|
22
21
|
import { ModelProvider } from 'model-bank';
|
|
23
22
|
import OpenAI from 'openai';
|
|
24
23
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
25
24
|
|
|
26
|
-
import { UserStore } from '@/store/user';
|
|
27
|
-
import { UserSettingsState, initialSettingsState } from '@/store/user/slices/settings/initialState';
|
|
28
|
-
|
|
29
25
|
import { initializeWithClientStore } from './clientModelRuntime';
|
|
30
26
|
|
|
31
27
|
// Mocking external dependencies
|
|
@@ -62,21 +58,35 @@ vi.mock('@lobechat/model-runtime', async (importOriginal) => {
|
|
|
62
58
|
};
|
|
63
59
|
});
|
|
64
60
|
|
|
65
|
-
|
|
61
|
+
// Mock version constants
|
|
62
|
+
vi.mock('@/const/version', () => ({
|
|
63
|
+
isServerMode: false,
|
|
64
|
+
isDeprecatedEdition: true,
|
|
65
|
+
isDesktop: false,
|
|
66
|
+
}));
|
|
67
|
+
|
|
68
|
+
// Helper function to mock aiInfra store with provider keyVaults
|
|
69
|
+
const mockProviderKeyVaults = async (provider: string, keyVaults: any) => {
|
|
70
|
+
const { useAiInfraStore } = await import('@/store/aiInfra');
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
useAiInfraStore.setState((state) => ({
|
|
73
|
+
aiProviderRuntimeConfig: {
|
|
74
|
+
...state.aiProviderRuntimeConfig,
|
|
75
|
+
[provider]: {
|
|
76
|
+
keyVaults,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
}));
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
afterEach(async () => {
|
|
66
83
|
vi.restoreAllMocks();
|
|
84
|
+
// Clean up store state
|
|
85
|
+
const { useAiInfraStore } = await import('@/store/aiInfra');
|
|
86
|
+
useAiInfraStore.setState({ aiProviderRuntimeConfig: {} } as any);
|
|
67
87
|
});
|
|
68
88
|
|
|
69
89
|
beforeEach(async () => {
|
|
70
|
-
// 清除所有模块的缓存
|
|
71
|
-
vi.resetModules();
|
|
72
|
-
|
|
73
|
-
// 默认设置 isServerMode 为 false
|
|
74
|
-
vi.mock('@/const/version', () => ({
|
|
75
|
-
isServerMode: false,
|
|
76
|
-
isDeprecatedEdition: true,
|
|
77
|
-
isDesktop: false,
|
|
78
|
-
}));
|
|
79
|
-
|
|
80
90
|
// Reset all mocks
|
|
81
91
|
vi.clearAllMocks();
|
|
82
92
|
|
|
@@ -97,17 +107,11 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
97
107
|
describe('initializeWithClientStore', () => {
|
|
98
108
|
describe('should initialize with options correctly', () => {
|
|
99
109
|
it('OpenAI provider: with apikey and endpoint', async () => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
apiKey: 'user-openai-key',
|
|
106
|
-
baseURL: 'user-openai-endpoint',
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
110
|
+
await mockProviderKeyVaults(ModelProvider.OpenAI, {
|
|
111
|
+
apiKey: 'user-openai-key',
|
|
112
|
+
baseURL: 'user-openai-endpoint',
|
|
113
|
+
});
|
|
114
|
+
|
|
111
115
|
const runtime = await initializeWithClientStore({
|
|
112
116
|
payload: {},
|
|
113
117
|
provider: ModelProvider.OpenAI,
|
|
@@ -118,17 +122,11 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
118
122
|
});
|
|
119
123
|
|
|
120
124
|
it('Azure provider: with apiKey, apiVersion, endpoint', async () => {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
endpoint: 'user-azure-endpoint',
|
|
127
|
-
apiVersion: '2024-06-01',
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
125
|
+
await mockProviderKeyVaults(ModelProvider.Azure, {
|
|
126
|
+
apiKey: 'user-azure-key',
|
|
127
|
+
endpoint: 'user-azure-endpoint',
|
|
128
|
+
apiVersion: '2024-06-01',
|
|
129
|
+
});
|
|
132
130
|
|
|
133
131
|
const runtime = await initializeWithClientStore({
|
|
134
132
|
payload: {},
|
|
@@ -139,15 +137,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
139
137
|
});
|
|
140
138
|
|
|
141
139
|
it('Google provider: with apiKey', async () => {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
apiKey: 'user-google-key',
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
140
|
+
await mockProviderKeyVaults(ModelProvider.Google, {
|
|
141
|
+
apiKey: 'user-google-key',
|
|
142
|
+
});
|
|
143
|
+
|
|
151
144
|
const runtime = await initializeWithClientStore({
|
|
152
145
|
payload: {},
|
|
153
146
|
provider: ModelProvider.Google,
|
|
@@ -157,15 +150,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
157
150
|
});
|
|
158
151
|
|
|
159
152
|
it('Moonshot AI provider: with apiKey', async () => {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
apiKey: 'user-moonshot-key',
|
|
165
|
-
},
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
153
|
+
await mockProviderKeyVaults(ModelProvider.Moonshot, {
|
|
154
|
+
apiKey: 'user-moonshot-key',
|
|
155
|
+
});
|
|
156
|
+
|
|
169
157
|
const runtime = await initializeWithClientStore({
|
|
170
158
|
payload: {},
|
|
171
159
|
provider: ModelProvider.Moonshot,
|
|
@@ -175,17 +163,12 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
175
163
|
});
|
|
176
164
|
|
|
177
165
|
it('Bedrock provider: with accessKeyId, region, secretAccessKey', async () => {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
secretAccessKey: 'user-bedrock-secret',
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
166
|
+
await mockProviderKeyVaults(ModelProvider.Bedrock, {
|
|
167
|
+
accessKeyId: 'user-bedrock-access-key',
|
|
168
|
+
region: 'user-bedrock-region',
|
|
169
|
+
secretAccessKey: 'user-bedrock-secret',
|
|
170
|
+
});
|
|
171
|
+
|
|
189
172
|
const runtime = await initializeWithClientStore({
|
|
190
173
|
payload: {},
|
|
191
174
|
provider: ModelProvider.Bedrock,
|
|
@@ -195,15 +178,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
195
178
|
});
|
|
196
179
|
|
|
197
180
|
it('Ollama provider: with endpoint', async () => {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
baseURL: 'http://127.0.0.1:1234',
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
},
|
|
206
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
181
|
+
await mockProviderKeyVaults(ModelProvider.Ollama, {
|
|
182
|
+
baseURL: 'http://127.0.0.1:1234',
|
|
183
|
+
});
|
|
184
|
+
|
|
207
185
|
const runtime = await initializeWithClientStore({
|
|
208
186
|
payload: {},
|
|
209
187
|
provider: ModelProvider.Ollama,
|
|
@@ -213,15 +191,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
213
191
|
});
|
|
214
192
|
|
|
215
193
|
it('Perplexity provider: with apiKey', async () => {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
apiKey: 'user-perplexity-key',
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
},
|
|
224
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
194
|
+
await mockProviderKeyVaults(ModelProvider.Perplexity, {
|
|
195
|
+
apiKey: 'user-perplexity-key',
|
|
196
|
+
});
|
|
197
|
+
|
|
225
198
|
const runtime = await initializeWithClientStore({
|
|
226
199
|
payload: {},
|
|
227
200
|
provider: ModelProvider.Perplexity,
|
|
@@ -231,15 +204,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
231
204
|
});
|
|
232
205
|
|
|
233
206
|
it('Anthropic provider: with apiKey', async () => {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
apiKey: 'user-anthropic-key',
|
|
239
|
-
},
|
|
240
|
-
},
|
|
241
|
-
},
|
|
242
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
207
|
+
await mockProviderKeyVaults(ModelProvider.Anthropic, {
|
|
208
|
+
apiKey: 'user-anthropic-key',
|
|
209
|
+
});
|
|
210
|
+
|
|
243
211
|
const runtime = await initializeWithClientStore({
|
|
244
212
|
payload: {},
|
|
245
213
|
provider: ModelProvider.Anthropic,
|
|
@@ -249,15 +217,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
249
217
|
});
|
|
250
218
|
|
|
251
219
|
it('Mistral provider: with apiKey', async () => {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
apiKey: 'user-mistral-key',
|
|
257
|
-
},
|
|
258
|
-
},
|
|
259
|
-
},
|
|
260
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
220
|
+
await mockProviderKeyVaults(ModelProvider.Mistral, {
|
|
221
|
+
apiKey: 'user-mistral-key',
|
|
222
|
+
});
|
|
223
|
+
|
|
261
224
|
const runtime = await initializeWithClientStore({
|
|
262
225
|
payload: {},
|
|
263
226
|
provider: ModelProvider.Mistral,
|
|
@@ -267,15 +230,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
267
230
|
});
|
|
268
231
|
|
|
269
232
|
it('OpenRouter provider: with apiKey', async () => {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
apiKey: 'user-openrouter-key',
|
|
275
|
-
},
|
|
276
|
-
},
|
|
277
|
-
},
|
|
278
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
233
|
+
await mockProviderKeyVaults(ModelProvider.OpenRouter, {
|
|
234
|
+
apiKey: 'user-openrouter-key',
|
|
235
|
+
});
|
|
236
|
+
|
|
279
237
|
const runtime = await initializeWithClientStore({
|
|
280
238
|
payload: {},
|
|
281
239
|
provider: ModelProvider.OpenRouter,
|
|
@@ -285,15 +243,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
285
243
|
});
|
|
286
244
|
|
|
287
245
|
it('TogetherAI provider: with apiKey', async () => {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
apiKey: 'user-togetherai-key',
|
|
293
|
-
},
|
|
294
|
-
},
|
|
295
|
-
},
|
|
296
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
246
|
+
await mockProviderKeyVaults(ModelProvider.TogetherAI, {
|
|
247
|
+
apiKey: 'user-togetherai-key',
|
|
248
|
+
});
|
|
249
|
+
|
|
297
250
|
const runtime = await initializeWithClientStore({
|
|
298
251
|
payload: {},
|
|
299
252
|
provider: ModelProvider.TogetherAI,
|
|
@@ -303,15 +256,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
303
256
|
});
|
|
304
257
|
|
|
305
258
|
it('ZeroOneAI provider: with apiKey', async () => {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
apiKey: 'user-zeroone-key',
|
|
311
|
-
},
|
|
312
|
-
},
|
|
313
|
-
},
|
|
314
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
259
|
+
await mockProviderKeyVaults(ModelProvider.ZeroOne, {
|
|
260
|
+
apiKey: 'user-zeroone-key',
|
|
261
|
+
});
|
|
262
|
+
|
|
315
263
|
const runtime = await initializeWithClientStore({
|
|
316
264
|
payload: {},
|
|
317
265
|
provider: ModelProvider.ZeroOne,
|
|
@@ -321,16 +269,11 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
321
269
|
});
|
|
322
270
|
|
|
323
271
|
it('Groq provider: with apiKey,endpoint', async () => {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
baseURL: 'user-groq-endpoint',
|
|
330
|
-
},
|
|
331
|
-
},
|
|
332
|
-
},
|
|
333
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
272
|
+
await mockProviderKeyVaults(ModelProvider.Groq, {
|
|
273
|
+
apiKey: 'user-groq-key',
|
|
274
|
+
baseURL: 'user-groq-endpoint',
|
|
275
|
+
});
|
|
276
|
+
|
|
334
277
|
const runtime = await initializeWithClientStore({
|
|
335
278
|
payload: {},
|
|
336
279
|
provider: ModelProvider.Groq,
|
|
@@ -344,15 +287,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
344
287
|
});
|
|
345
288
|
|
|
346
289
|
it('DeepSeek provider: with apiKey', async () => {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
apiKey: 'user-deepseek-key',
|
|
352
|
-
},
|
|
353
|
-
},
|
|
354
|
-
},
|
|
355
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
290
|
+
await mockProviderKeyVaults(ModelProvider.DeepSeek, {
|
|
291
|
+
apiKey: 'user-deepseek-key',
|
|
292
|
+
});
|
|
293
|
+
|
|
356
294
|
const runtime = await initializeWithClientStore({
|
|
357
295
|
payload: {},
|
|
358
296
|
provider: ModelProvider.DeepSeek,
|
|
@@ -362,15 +300,10 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
362
300
|
});
|
|
363
301
|
|
|
364
302
|
it('Qwen provider: with apiKey', async () => {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
apiKey: 'user-qwen-key',
|
|
370
|
-
},
|
|
371
|
-
},
|
|
372
|
-
},
|
|
373
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
303
|
+
await mockProviderKeyVaults(ModelProvider.Qwen, {
|
|
304
|
+
apiKey: 'user-qwen-key',
|
|
305
|
+
});
|
|
306
|
+
|
|
374
307
|
const runtime = await initializeWithClientStore({
|
|
375
308
|
payload: {},
|
|
376
309
|
provider: ModelProvider.Qwen,
|
|
@@ -384,16 +317,23 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
384
317
|
* similar cases in server side
|
|
385
318
|
*/
|
|
386
319
|
it('Unknown provider: with apiKey', async () => {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
320
|
+
const { useAiInfraStore } = await import('@/store/aiInfra');
|
|
321
|
+
// @ts-ignore
|
|
322
|
+
useAiInfraStore.setState((state) => ({
|
|
323
|
+
aiProviderRuntimeConfig: {
|
|
324
|
+
...state.aiProviderRuntimeConfig,
|
|
325
|
+
unknown: {
|
|
326
|
+
keyVaults: {
|
|
391
327
|
apiKey: 'user-unknown-key',
|
|
392
|
-
|
|
328
|
+
baseURL: 'user-unknown-endpoint',
|
|
329
|
+
},
|
|
330
|
+
settings: {
|
|
331
|
+
sdkType: 'openai',
|
|
393
332
|
},
|
|
394
333
|
},
|
|
395
334
|
},
|
|
396
|
-
}
|
|
335
|
+
}));
|
|
336
|
+
|
|
397
337
|
const runtime = await initializeWithClientStore({
|
|
398
338
|
payload: {},
|
|
399
339
|
provider: 'unknown' as ModelProvider,
|
|
@@ -415,15 +355,11 @@ describe('ModelRuntimeOnClient', () => {
|
|
|
415
355
|
'eyJhbGciOiJIUzI1NiIsInNpZ25fdHlwZSI6IlNJR04iLCJ0eXAiOiJKV1QifQ.eyJhcGlfa2V5IjoiemhpcHUiLCJleHAiOjE3MTU5MTc2NzMsImlhdCI6MTcxMzMyNTY3M30.gt8o-hUDvJFPJLYcH4EhrT1LAmTXI8YnybHeQjpD9oM',
|
|
416
356
|
),
|
|
417
357
|
}));
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
},
|
|
424
|
-
},
|
|
425
|
-
},
|
|
426
|
-
} as UserSettingsState) as unknown as UserStore;
|
|
358
|
+
|
|
359
|
+
await mockProviderKeyVaults(ModelProvider.ZhiPu, {
|
|
360
|
+
apiKey: 'zhipu.user-key',
|
|
361
|
+
});
|
|
362
|
+
|
|
427
363
|
const runtime = await initializeWithClientStore({
|
|
428
364
|
payload: {},
|
|
429
365
|
provider: ModelProvider.ZhiPu,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isDesktop
|
|
1
|
+
import { isDesktop } from '@lobechat/const';
|
|
2
2
|
import {
|
|
3
3
|
ContextEngine,
|
|
4
4
|
GroupMessageFlattenProcessor,
|
|
@@ -88,7 +88,7 @@ export const contextEngineering = async ({
|
|
|
88
88
|
|
|
89
89
|
// 8.5 Message content processing
|
|
90
90
|
new MessageContentProcessor({
|
|
91
|
-
fileContext: { enabled:
|
|
91
|
+
fileContext: { enabled: true, includeFileUrl: !isDesktop },
|
|
92
92
|
isCanUseVideo,
|
|
93
93
|
isCanUseVision,
|
|
94
94
|
model,
|
package/src/services/config.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BRANDING_NAME
|
|
1
|
+
import { BRANDING_NAME } from '@lobechat/const';
|
|
2
2
|
import { downloadFile, exportJSONFile } from '@lobechat/utils/client';
|
|
3
3
|
import dayjs from 'dayjs';
|
|
4
4
|
|
|
@@ -19,7 +19,7 @@ class ConfigService {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// or export to file with the data
|
|
22
|
-
const result = await this.createDataStructure(data,
|
|
22
|
+
const result = await this.createDataStructure(data, 'postgres');
|
|
23
23
|
|
|
24
24
|
exportJSONFile(result, filename);
|
|
25
25
|
};
|