@lobehub/chat 0.115.1 → 0.115.3
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/.env.example +1 -1
- package/CHANGELOG.md +50 -0
- package/Dockerfile +1 -1
- package/README.md +6 -6
- package/README.zh-CN.md +6 -6
- package/docs/Deployment/Environment-Variable.md +2 -2
- package/docs/Deployment/Environment-Variable.zh-CN.md +2 -2
- package/next.config.mjs +0 -4
- package/package.json +1 -1
- package/src/app/api/config/route.ts +15 -0
- package/src/app/api/market/AgentMarket.ts +25 -0
- package/src/app/api/market/[id]/route.ts +6 -3
- package/src/app/api/market/route.ts +6 -3
- package/src/app/chat/features/SessionListContent/DefaultMode.tsx +2 -1
- package/src/app/chat/features/SessionListContent/List/Item/index.tsx +2 -1
- package/src/app/settings/agent/Agent.tsx +2 -1
- package/src/app/settings/common/Common.tsx +2 -1
- package/src/app/settings/llm/LLM/index.tsx +2 -1
- package/src/app/settings/tts/TTS/index.tsx +2 -1
- package/src/components/FileList/EditableFileList.tsx +1 -1
- package/src/components/FileList/index.tsx +3 -45
- package/src/components/FileList/style.ts +0 -23
- package/src/config/__tests__/client.test.ts +0 -23
- package/src/config/__tests__/server.test.ts +26 -1
- package/src/config/client.ts +4 -15
- package/src/config/server.ts +14 -1
- package/src/const/settings.ts +0 -3
- package/src/const/url.ts +1 -18
- package/src/features/AgentSetting/AgentConfig/index.tsx +2 -1
- package/src/features/AgentSetting/AgentMeta/index.tsx +2 -1
- package/src/features/AgentSetting/AgentTTS/index.tsx +3 -2
- package/src/features/ChatInput/ActionBar/ModelSwitch.tsx +2 -1
- package/src/features/Conversation/ChatList/Error/ApiKeyForm.tsx +2 -1
- package/src/features/Conversation/ChatList/Extras/TTS/index.tsx +3 -2
- package/src/features/Conversation/index.tsx +2 -1
- package/src/features/PluginDevModal/LocalForm.tsx +3 -2
- package/src/hooks/useSTT.ts +2 -1
- package/src/hooks/useTTS.ts +2 -1
- package/src/layout/GlobalLayout/StoreHydration.tsx +5 -0
- package/src/services/__tests__/chat.test.ts +1 -1
- package/src/services/__tests__/global.test.ts +49 -32
- package/src/services/_header.ts +2 -2
- package/src/services/_url.ts +1 -0
- package/src/services/config.ts +2 -1
- package/src/services/global.ts +9 -0
- package/src/services/market.ts +21 -0
- package/src/store/chat/initialState.ts +9 -47
- package/src/store/chat/selectors.ts +3 -0
- package/src/store/chat/{actions/enhance.test.ts → slices/enchance/action.test.ts} +2 -2
- package/src/store/chat/{actions/message.test.ts → slices/message/action.test.ts} +1 -1
- package/src/store/chat/{actions/message.ts → slices/message/action.ts} +2 -2
- package/src/store/chat/slices/message/initialState.ts +29 -0
- package/src/store/chat/{reducers/message.test.ts → slices/message/reducer.test.ts} +2 -2
- package/src/store/chat/{selectors/__tests__/chat.test.ts → slices/message/selectors.test.ts} +1 -1
- package/src/store/chat/{selectors/chat.ts → slices/message/selectors.ts} +2 -2
- package/src/store/chat/{actions/share.ts → slices/share/action.ts} +2 -2
- package/src/store/chat/slices/share/initialState.ts +7 -0
- package/src/store/chat/{actions/plugin.ts → slices/tool/action.ts} +1 -3
- package/src/store/chat/slices/tool/initialState.ts +7 -0
- package/src/store/chat/{actions/topic.test.ts → slices/topic/action.test.ts} +1 -1
- package/src/store/chat/{actions/topic.ts → slices/topic/action.ts} +2 -1
- package/src/store/chat/slices/topic/initialState.ts +23 -0
- package/src/store/chat/{selectors/__tests__/topic.test.ts → slices/topic/selectors.test.ts} +1 -1
- package/src/store/chat/{selectors/topic.ts → slices/topic/selectors.ts} +1 -1
- package/src/store/chat/store.ts +5 -5
- package/src/store/global/helpers.ts +1 -1
- package/src/store/global/index.ts +0 -1
- package/src/store/global/initialState.ts +6 -59
- package/src/store/global/selectors.ts +2 -2
- package/src/store/global/slices/{common.ts → common/action.ts} +12 -3
- package/src/store/global/slices/common/initialState.ts +55 -0
- package/src/store/global/{selectors/preference.ts → slices/common/selectors.ts} +1 -1
- package/src/store/global/{selectors/__snapshots__/settings.test.ts.snap → slices/settings/__snapshots__/selectors.test.ts.snap} +0 -1
- package/src/store/global/slices/{settings.ts → settings/action.ts} +12 -4
- package/src/store/global/slices/settings/initialState.ts +15 -0
- package/src/store/global/{selectors/settings.test.ts → slices/settings/selectors.test.ts} +9 -6
- package/src/store/global/{selectors/settings.ts → slices/settings/selectors.ts} +4 -4
- package/src/store/global/store.ts +4 -18
- package/src/store/market/action.ts +14 -10
- package/src/store/session/slices/agent/selectors.ts +2 -1
- package/src/store/session/slices/session/action.ts +2 -1
- package/src/tools/dalle/Render/ToolBar.tsx +2 -1
- package/src/types/settings.ts +4 -29
- package/src/components/FileList/FileGrid.tsx +0 -36
- package/src/services/agentMarket.ts +0 -21
- package/src/store/chat/selectors/index.ts +0 -3
- package/src/store/global/slices/agent.ts +0 -34
- /package/src/store/chat/{actions/enhance.ts → slices/enchance/action.ts} +0 -0
- /package/src/store/chat/{selectors/enchance.ts → slices/enchance/selectors.ts} +0 -0
- /package/src/store/chat/{reducers/message.ts → slices/message/reducer.ts} +0 -0
- /package/src/store/chat/{actions/plugin.test.ts → slices/tool/action.test.ts} +0 -0
package/src/const/url.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import urlJoin from 'url-join';
|
|
2
2
|
|
|
3
|
-
import { getClientConfig } from '@/config/client';
|
|
4
3
|
import { Locales } from '@/locales/resources';
|
|
5
4
|
|
|
6
5
|
import pkg from '../../package.json';
|
|
@@ -15,7 +14,7 @@ export const ABOUT = pkg.homepage;
|
|
|
15
14
|
export const FEEDBACK = pkg.bugs.url;
|
|
16
15
|
export const DISCORD = 'https://discord.gg/AYFPHvv2jT';
|
|
17
16
|
|
|
18
|
-
export const
|
|
17
|
+
export const PLUGINS_INDEX_URL = 'https://chat-plugins.lobehub.com';
|
|
19
18
|
|
|
20
19
|
export const getPluginIndexJSON = (lang: Locales = DEFAULT_LANG, baseUrl = PLUGINS_INDEX_URL) => {
|
|
21
20
|
if (checkLang(lang)) return baseUrl;
|
|
@@ -23,22 +22,6 @@ export const getPluginIndexJSON = (lang: Locales = DEFAULT_LANG, baseUrl = PLUGI
|
|
|
23
22
|
return urlJoin(baseUrl, `index.${lang}.json`);
|
|
24
23
|
};
|
|
25
24
|
|
|
26
|
-
export const getAgentIndexJSON = (lang: Locales = DEFAULT_LANG, baseUrl = AGENTS_INDEX_URL) => {
|
|
27
|
-
if (checkLang(lang)) return baseUrl;
|
|
28
|
-
|
|
29
|
-
return urlJoin(baseUrl, `index.${lang}.json`);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export const getAgentJSON = (
|
|
33
|
-
identifier: string,
|
|
34
|
-
lang: Locales = DEFAULT_LANG,
|
|
35
|
-
baseUrl = AGENTS_INDEX_URL,
|
|
36
|
-
) => {
|
|
37
|
-
if (checkLang(lang)) return urlJoin(baseUrl, `${identifier}.json`);
|
|
38
|
-
|
|
39
|
-
return urlJoin(baseUrl, `${identifier}.${lang}.json`);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
25
|
export const AGENTS_INDEX_GITHUB = 'https://github.com/lobehub/lobe-chat-agents';
|
|
43
26
|
export const AGENTS_INDEX_GITHUB_ISSUE = urlJoin(AGENTS_INDEX_GITHUB, 'issues/new');
|
|
44
27
|
|
|
@@ -8,7 +8,8 @@ import { memo, useEffect } from 'react';
|
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
9
9
|
|
|
10
10
|
import { FORM_STYLE } from '@/const/layoutTokens';
|
|
11
|
-
import {
|
|
11
|
+
import { useGlobalStore } from '@/store/global';
|
|
12
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
12
13
|
|
|
13
14
|
import { useStore } from '../store';
|
|
14
15
|
|
|
@@ -8,7 +8,8 @@ import { memo, useMemo } from 'react';
|
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
9
9
|
|
|
10
10
|
import { FORM_STYLE } from '@/const/layoutTokens';
|
|
11
|
-
import {
|
|
11
|
+
import { useGlobalStore } from '@/store/global';
|
|
12
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
12
13
|
|
|
13
14
|
import { useStore } from '../store';
|
|
14
15
|
import { SessionLoadingState } from '../store/initialState';
|
|
@@ -8,10 +8,11 @@ import { memo, useEffect } from 'react';
|
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
9
9
|
|
|
10
10
|
import { FORM_STYLE } from '@/const/layoutTokens';
|
|
11
|
-
import
|
|
12
|
-
import { settingsSelectors
|
|
11
|
+
import { useGlobalStore } from '@/store/global';
|
|
12
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
13
13
|
|
|
14
14
|
import { useStore } from '../store';
|
|
15
|
+
import SelectWithTTSPreview from './SelectWithTTSPreview';
|
|
15
16
|
import { ttsOptions } from './options';
|
|
16
17
|
|
|
17
18
|
const TTS_SETTING_KEY = 'tts';
|
|
@@ -5,7 +5,8 @@ import { BrainCog } from 'lucide-react';
|
|
|
5
5
|
import { memo } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { useGlobalStore } from '@/store/global';
|
|
9
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
9
10
|
import { useSessionStore } from '@/store/session';
|
|
10
11
|
import { agentSelectors } from '@/store/session/selectors';
|
|
11
12
|
import { LanguageModel } from '@/types/llm';
|
|
@@ -6,7 +6,8 @@ import { useTranslation } from 'react-i18next';
|
|
|
6
6
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
7
7
|
|
|
8
8
|
import { useChatStore } from '@/store/chat';
|
|
9
|
-
import {
|
|
9
|
+
import { useGlobalStore } from '@/store/global';
|
|
10
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
10
11
|
|
|
11
12
|
import { FormAction } from './style';
|
|
12
13
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { memo, useMemo } from 'react';
|
|
2
2
|
import { Md5 } from 'ts-md5';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { useGlobalStore } from '@/store/global';
|
|
5
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
5
6
|
import { useSessionStore } from '@/store/session';
|
|
6
|
-
import { agentSelectors } from '@/store/session/
|
|
7
|
+
import { agentSelectors } from '@/store/session/selectors';
|
|
7
8
|
|
|
8
9
|
import FilePlayer from './FilePlayer';
|
|
9
10
|
import InitPlayer, { TTSProps } from './InitPlayer';
|
|
@@ -5,7 +5,8 @@ import { useTranslation } from 'react-i18next';
|
|
|
5
5
|
import { Flexbox } from 'react-layout-kit';
|
|
6
6
|
|
|
7
7
|
import SafeSpacing from '@/components/SafeSpacing';
|
|
8
|
-
import {
|
|
8
|
+
import { useGlobalStore } from '@/store/global';
|
|
9
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
9
10
|
|
|
10
11
|
import ChatList from './ChatList';
|
|
11
12
|
import ChatScrollAnchor from './ScrollAnchor';
|
|
@@ -4,9 +4,10 @@ import dynamic from 'next/dynamic';
|
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { useGlobalStore } from '@/store/global';
|
|
8
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
8
9
|
import { useToolStore } from '@/store/tool';
|
|
9
|
-
import { pluginSelectors } from '@/store/tool/
|
|
10
|
+
import { pluginSelectors } from '@/store/tool/selectors';
|
|
10
11
|
|
|
11
12
|
const EmojiPicker = dynamic(() => import('@lobehub/ui/es/EmojiPicker'), { ssr: false });
|
|
12
13
|
|
package/src/hooks/useSTT.ts
CHANGED
|
@@ -10,7 +10,8 @@ import { SWRConfiguration } from 'swr';
|
|
|
10
10
|
|
|
11
11
|
import { createHeaderWithOpenAI } from '@/services/_header';
|
|
12
12
|
import { OPENAI_URLS } from '@/services/_url';
|
|
13
|
-
import {
|
|
13
|
+
import { useGlobalStore } from '@/store/global';
|
|
14
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
14
15
|
import { useSessionStore } from '@/store/session';
|
|
15
16
|
import { agentSelectors } from '@/store/session/selectors';
|
|
16
17
|
|
package/src/hooks/useTTS.ts
CHANGED
|
@@ -11,7 +11,8 @@ import isEqual from 'fast-deep-equal';
|
|
|
11
11
|
|
|
12
12
|
import { createHeaderWithOpenAI } from '@/services/_header';
|
|
13
13
|
import { OPENAI_URLS, TTS_URL } from '@/services/_url';
|
|
14
|
-
import {
|
|
14
|
+
import { useGlobalStore } from '@/store/global';
|
|
15
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
15
16
|
import { useSessionStore } from '@/store/session';
|
|
16
17
|
import { agentSelectors } from '@/store/session/selectors';
|
|
17
18
|
import { TTSServer } from '@/types/agent';
|
|
@@ -8,12 +8,16 @@ import { useEffectAfterSessionHydrated, useSessionStore } from '@/store/session'
|
|
|
8
8
|
const StoreHydration = memo(() => {
|
|
9
9
|
const router = useRouter();
|
|
10
10
|
|
|
11
|
+
const useFetchGlobalConfig = useGlobalStore((s) => s.useFetchGlobalConfig);
|
|
12
|
+
|
|
11
13
|
useEffect(() => {
|
|
12
14
|
// refs: https://github.com/pmndrs/zustand/blob/main/docs/integrations/persisting-store-data.md#hashydrated
|
|
13
15
|
useSessionStore.persist.rehydrate();
|
|
14
16
|
useGlobalStore.persist.rehydrate();
|
|
15
17
|
}, []);
|
|
16
18
|
|
|
19
|
+
useFetchGlobalConfig();
|
|
20
|
+
|
|
17
21
|
const { mobile } = useResponsive();
|
|
18
22
|
|
|
19
23
|
useEffectAfterSessionHydrated(
|
|
@@ -29,6 +33,7 @@ const StoreHydration = memo(() => {
|
|
|
29
33
|
},
|
|
30
34
|
[router],
|
|
31
35
|
);
|
|
36
|
+
|
|
32
37
|
useEffect(() => {
|
|
33
38
|
router.prefetch('/chat');
|
|
34
39
|
router.prefetch('/market');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
|
|
2
2
|
import { act } from '@testing-library/react';
|
|
3
|
-
import {
|
|
3
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
4
4
|
|
|
5
5
|
import { VISION_MODEL_WHITE_LIST } from '@/const/llm';
|
|
6
6
|
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
@@ -9,49 +9,66 @@ beforeEach(() => {
|
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
describe('GlobalService', () => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
describe('getLatestVersion', () => {
|
|
13
|
+
it('should return the latest version when fetch is successful', async () => {
|
|
14
|
+
// Arrange
|
|
15
|
+
const mockVersion = '1.0.0';
|
|
16
|
+
(fetch as Mock).mockResolvedValue({
|
|
17
|
+
json: () => Promise.resolve({ 'dist-tags': { latest: mockVersion } }),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// Act
|
|
21
|
+
const version = await globalService.getLatestVersion();
|
|
22
|
+
|
|
23
|
+
// Assert
|
|
24
|
+
expect(fetch).toHaveBeenCalledWith('https://registry.npmmirror.com/@lobehub/chat');
|
|
25
|
+
expect(version).toBe(mockVersion);
|
|
17
26
|
});
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
|
|
28
|
+
it('should return undefined if the latest version is not found in the response', async () => {
|
|
29
|
+
// Arrange
|
|
30
|
+
(fetch as Mock).mockResolvedValue({
|
|
31
|
+
json: () => Promise.resolve({}),
|
|
32
|
+
});
|
|
21
33
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
expect(version).toBe(mockVersion);
|
|
25
|
-
});
|
|
34
|
+
// Act
|
|
35
|
+
const version = await globalService.getLatestVersion();
|
|
26
36
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
(fetch as Mock).mockResolvedValue({
|
|
30
|
-
json: () => Promise.resolve({}),
|
|
37
|
+
// Assert
|
|
38
|
+
expect(version).toBeUndefined();
|
|
31
39
|
});
|
|
32
40
|
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
it('should throw an error when the fetch call fails', async () => {
|
|
42
|
+
// Arrange
|
|
43
|
+
(fetch as Mock).mockRejectedValue(new Error('Network error'));
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
45
|
+
// Act & Assert
|
|
46
|
+
await expect(globalService.getLatestVersion()).rejects.toThrow('Network error');
|
|
47
|
+
});
|
|
39
48
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
it('should handle non-JSON responses gracefully', async () => {
|
|
50
|
+
// Arrange
|
|
51
|
+
(fetch as Mock).mockResolvedValue({
|
|
52
|
+
json: () => Promise.reject(new SyntaxError('Unexpected token < in JSON at position 0')),
|
|
53
|
+
});
|
|
43
54
|
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
// Act & Assert
|
|
56
|
+
await expect(globalService.getLatestVersion()).rejects.toThrow(SyntaxError);
|
|
57
|
+
});
|
|
46
58
|
});
|
|
47
59
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
describe('ServerConfig', () => {
|
|
61
|
+
it('should return the serverConfig when fetch is successful', async () => {
|
|
62
|
+
// Arrange
|
|
63
|
+
(fetch as Mock).mockResolvedValue({
|
|
64
|
+
json: () => Promise.resolve({ customModelName: 'abc' }),
|
|
65
|
+
});
|
|
53
66
|
|
|
54
|
-
|
|
55
|
-
|
|
67
|
+
// Act
|
|
68
|
+
const config = await globalService.getGlobalConfig();
|
|
69
|
+
|
|
70
|
+
// Assert
|
|
71
|
+
expect(config).toEqual({ customModelName: 'abc' });
|
|
72
|
+
});
|
|
56
73
|
});
|
|
57
74
|
});
|
package/src/services/_header.ts
CHANGED
|
@@ -11,8 +11,8 @@ import { useGlobalStore } from '@/store/global';
|
|
|
11
11
|
export const createHeaderWithOpenAI = (header?: HeadersInit): HeadersInit => {
|
|
12
12
|
const openai = useGlobalStore.getState().settings.languageModel.openAI;
|
|
13
13
|
|
|
14
|
-
const apiKey = openai.OPENAI_API_KEY ||
|
|
15
|
-
const endpoint = openai.endpoint ||
|
|
14
|
+
const apiKey = openai.OPENAI_API_KEY || '';
|
|
15
|
+
const endpoint = openai.endpoint || '';
|
|
16
16
|
|
|
17
17
|
// eslint-disable-next-line no-undef
|
|
18
18
|
const result: HeadersInit = {
|
package/src/services/_url.ts
CHANGED
package/src/services/config.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { messageService } from '@/services/message';
|
|
2
2
|
import { sessionService } from '@/services/session';
|
|
3
3
|
import { topicService } from '@/services/topic';
|
|
4
|
-
import {
|
|
4
|
+
import { useGlobalStore } from '@/store/global';
|
|
5
|
+
import { settingsSelectors } from '@/store/global/selectors';
|
|
5
6
|
import { useSessionStore } from '@/store/session';
|
|
6
7
|
import { sessionExportSelectors, sessionSelectors } from '@/store/session/selectors';
|
|
7
8
|
import { ChatMessage } from '@/types/chatMessage';
|
package/src/services/global.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { URLS } from '@/services/_url';
|
|
2
|
+
import { GlobalServerConfig } from '@/types/settings';
|
|
3
|
+
|
|
1
4
|
const VERSION_URL = 'https://registry.npmmirror.com/@lobehub/chat';
|
|
2
5
|
|
|
3
6
|
class GlobalService {
|
|
@@ -10,6 +13,12 @@ class GlobalService {
|
|
|
10
13
|
|
|
11
14
|
return data['dist-tags']?.latest;
|
|
12
15
|
};
|
|
16
|
+
|
|
17
|
+
getGlobalConfig = async (): Promise<GlobalServerConfig> => {
|
|
18
|
+
const res = await fetch(URLS.config);
|
|
19
|
+
|
|
20
|
+
return res.json();
|
|
21
|
+
};
|
|
13
22
|
}
|
|
14
23
|
|
|
15
24
|
export const globalService = new GlobalService();
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { URLS } from '@/services/_url';
|
|
2
|
+
import { LobeChatAgentsMarketIndex } from '@/types/market';
|
|
3
|
+
|
|
4
|
+
class MarketService {
|
|
5
|
+
getAgentList = async (locale: string): Promise<LobeChatAgentsMarketIndex> => {
|
|
6
|
+
const res = await fetch(`${URLS.market}?locale=${locale}`);
|
|
7
|
+
|
|
8
|
+
return res.json();
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 请求助手 manifest
|
|
13
|
+
*/
|
|
14
|
+
getAgentManifest = async (identifier: string, locale: string) => {
|
|
15
|
+
if (!identifier) return;
|
|
16
|
+
const res = await fetch(`${URLS.market}/${identifier}?locale=${locale}`);
|
|
17
|
+
|
|
18
|
+
return res.json();
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export const marketService = new MarketService();
|
|
@@ -1,51 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ChatMessageState, initialMessageState } from './slices/message/initialState';
|
|
2
|
+
import { ChatShareState, initialShareState } from './slices/share/initialState';
|
|
3
|
+
import { ChatToolState, initialToolState } from './slices/tool/initialState';
|
|
4
|
+
import { ChatTopicState, initialTopicState } from './slices/topic/initialState';
|
|
3
5
|
|
|
4
|
-
export
|
|
5
|
-
abortController?: AbortController;
|
|
6
|
-
/**
|
|
7
|
-
* @title 当前活动的会话
|
|
8
|
-
* @description 当前正在编辑或查看的会话
|
|
9
|
-
*/
|
|
10
|
-
activeId: string;
|
|
11
|
-
activeTopicId?: string;
|
|
12
|
-
/**
|
|
13
|
-
* @deprecated
|
|
14
|
-
*/
|
|
15
|
-
chatLoadingId?: string;
|
|
16
|
-
dalleImageLoading: Record<string, boolean>;
|
|
17
|
-
|
|
18
|
-
inputMessage: string;
|
|
19
|
-
isSearchingTopic: boolean;
|
|
20
|
-
messageLoadingIds: [];
|
|
21
|
-
messages: ChatMessage[];
|
|
22
|
-
/**
|
|
23
|
-
* whether messages have fetched
|
|
24
|
-
*/
|
|
25
|
-
messagesInit: boolean;
|
|
26
|
-
|
|
27
|
-
searchTopics: ChatTopic[];
|
|
28
|
-
shareLoading?: boolean;
|
|
29
|
-
topicLoadingId?: string;
|
|
30
|
-
topicRenamingId?: string;
|
|
31
|
-
topicSearchKeywords: string;
|
|
32
|
-
topics: ChatTopic[];
|
|
33
|
-
/**
|
|
34
|
-
* whether topics have fetched
|
|
35
|
-
*/
|
|
36
|
-
topicsInit: boolean;
|
|
37
|
-
}
|
|
6
|
+
export type ChatStoreState = ChatTopicState & ChatMessageState & ChatToolState & ChatShareState;
|
|
38
7
|
|
|
39
8
|
export const initialState: ChatStoreState = {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
messageLoadingIds: [],
|
|
45
|
-
messages: [],
|
|
46
|
-
messagesInit: false,
|
|
47
|
-
searchTopics: [],
|
|
48
|
-
topicSearchKeywords: '',
|
|
49
|
-
topics: [],
|
|
50
|
-
topicsInit: false,
|
|
9
|
+
...initialMessageState,
|
|
10
|
+
...initialTopicState,
|
|
11
|
+
...initialToolState,
|
|
12
|
+
...initialShareState,
|
|
51
13
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { act, renderHook
|
|
1
|
+
import { act, renderHook } from '@testing-library/react';
|
|
2
2
|
import { Mock, afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
|
|
4
4
|
import { chainLangDetect } from '@/chains/langDetect';
|
|
@@ -6,7 +6,7 @@ import { chainTranslate } from '@/chains/translate';
|
|
|
6
6
|
import { chatService } from '@/services/chat';
|
|
7
7
|
import { messageService } from '@/services/message';
|
|
8
8
|
|
|
9
|
-
import { useChatStore } from '
|
|
9
|
+
import { useChatStore } from '../../store';
|
|
10
10
|
|
|
11
11
|
// Mock messageService 和 chatService
|
|
12
12
|
vi.mock('@/services/message', () => ({
|
|
@@ -9,7 +9,7 @@ import { topicService } from '@/services/topic';
|
|
|
9
9
|
import { chatSelectors } from '@/store/chat/selectors';
|
|
10
10
|
import { ChatMessage } from '@/types/chatMessage';
|
|
11
11
|
|
|
12
|
-
import { useChatStore } from '
|
|
12
|
+
import { useChatStore } from '../../store';
|
|
13
13
|
|
|
14
14
|
// Mock service
|
|
15
15
|
vi.mock('@/services/message', () => ({
|
|
@@ -22,8 +22,8 @@ import { fetchSSE } from '@/utils/fetch';
|
|
|
22
22
|
import { isFunctionMessageAtStart, testFunctionMessageAtEnd } from '@/utils/message';
|
|
23
23
|
import { setNamespace } from '@/utils/storeDebug';
|
|
24
24
|
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
25
|
+
import { chatSelectors } from '../../selectors';
|
|
26
|
+
import { MessageDispatch, messagesReducer } from './reducer';
|
|
27
27
|
|
|
28
28
|
const n = setNamespace('message');
|
|
29
29
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ChatMessage } from '@/types/chatMessage';
|
|
2
|
+
|
|
3
|
+
export interface ChatMessageState {
|
|
4
|
+
abortController?: AbortController;
|
|
5
|
+
/**
|
|
6
|
+
* @title 当前活动的会话
|
|
7
|
+
* @description 当前正在编辑或查看的会话
|
|
8
|
+
*/
|
|
9
|
+
activeId: string;
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated
|
|
12
|
+
*/
|
|
13
|
+
chatLoadingId?: string;
|
|
14
|
+
inputMessage: string;
|
|
15
|
+
messageLoadingIds: [];
|
|
16
|
+
messages: ChatMessage[];
|
|
17
|
+
/**
|
|
18
|
+
* whether messages have fetched
|
|
19
|
+
*/
|
|
20
|
+
messagesInit: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const initialMessageState: ChatMessageState = {
|
|
24
|
+
activeId: 'inbox',
|
|
25
|
+
inputMessage: '',
|
|
26
|
+
messageLoadingIds: [],
|
|
27
|
+
messages: [],
|
|
28
|
+
messagesInit: false,
|
|
29
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ChatMessage
|
|
1
|
+
import { ChatMessage } from '@/types/chatMessage';
|
|
2
2
|
|
|
3
|
-
import { MessageDispatch, messagesReducer } from './
|
|
3
|
+
import { MessageDispatch, messagesReducer } from './reducer';
|
|
4
4
|
|
|
5
5
|
describe('messagesReducer', () => {
|
|
6
6
|
let initialState: ChatMessage[];
|
package/src/store/chat/{selectors/__tests__/chat.test.ts → slices/message/selectors.test.ts}
RENAMED
|
@@ -9,7 +9,7 @@ import { ChatMessage } from '@/types/chatMessage';
|
|
|
9
9
|
import { MetaData } from '@/types/meta';
|
|
10
10
|
import { merge } from '@/utils/merge';
|
|
11
11
|
|
|
12
|
-
import { chatSelectors } from '
|
|
12
|
+
import { chatSelectors } from './selectors';
|
|
13
13
|
|
|
14
14
|
vi.mock('i18next', () => ({
|
|
15
15
|
t: vi.fn((key) => key), // Simplified mock return value
|
|
@@ -10,8 +10,8 @@ import { ChatMessage } from '@/types/chatMessage';
|
|
|
10
10
|
import { MetaData } from '@/types/meta';
|
|
11
11
|
import { merge } from '@/utils/merge';
|
|
12
12
|
|
|
13
|
-
import { chatHelpers } from '
|
|
14
|
-
import type { ChatStore } from '
|
|
13
|
+
import { chatHelpers } from '../../helpers';
|
|
14
|
+
import type { ChatStore } from '../../store';
|
|
15
15
|
|
|
16
16
|
const getMeta = (message: ChatMessage) => {
|
|
17
17
|
switch (message.role) {
|
|
@@ -8,8 +8,8 @@ import { useSessionStore } from '@/store/session';
|
|
|
8
8
|
import { agentSelectors } from '@/store/session/selectors';
|
|
9
9
|
import { ShareGPTConversation } from '@/types/share';
|
|
10
10
|
|
|
11
|
-
import { chatSelectors } from '
|
|
12
|
-
import { ChatStore } from '
|
|
11
|
+
import { chatSelectors } from '../../selectors';
|
|
12
|
+
import { ChatStore } from '../../store';
|
|
13
13
|
|
|
14
14
|
interface ShareMessage {
|
|
15
15
|
from: 'human' | 'gpt';
|
|
@@ -11,7 +11,7 @@ import { ChatPluginPayload } from '@/types/chatMessage';
|
|
|
11
11
|
import { OpenAIFunctionCall } from '@/types/openai/functionCall';
|
|
12
12
|
import { setNamespace } from '@/utils/storeDebug';
|
|
13
13
|
|
|
14
|
-
import { chatSelectors } from '
|
|
14
|
+
import { chatSelectors } from '../../selectors';
|
|
15
15
|
|
|
16
16
|
const n = setNamespace('plugin');
|
|
17
17
|
|
|
@@ -85,7 +85,6 @@ export const chatPlugin: StateCreator<
|
|
|
85
85
|
const chats = chatSelectors.currentChats(get());
|
|
86
86
|
await coreProcessMessage(chats, id);
|
|
87
87
|
},
|
|
88
|
-
|
|
89
88
|
triggerFunctionCall: async (id) => {
|
|
90
89
|
const { invokeDefaultTypePlugin, invokeBuiltinTool, refreshMessages } = get();
|
|
91
90
|
|
|
@@ -146,7 +145,6 @@ export const chatPlugin: StateCreator<
|
|
|
146
145
|
}
|
|
147
146
|
}
|
|
148
147
|
},
|
|
149
|
-
|
|
150
148
|
updatePluginState: async (id, key, value) => {
|
|
151
149
|
const { refreshMessages } = get();
|
|
152
150
|
|
|
@@ -9,7 +9,7 @@ import { topicService } from '@/services/topic';
|
|
|
9
9
|
import { ChatMessage } from '@/types/chatMessage';
|
|
10
10
|
import { ChatTopic } from '@/types/topic';
|
|
11
11
|
|
|
12
|
-
import { useChatStore } from '
|
|
12
|
+
import { useChatStore } from '../../store';
|
|
13
13
|
|
|
14
14
|
// Mock topicService 和 messageService
|
|
15
15
|
vi.mock('@/services/topic', () => ({
|
|
@@ -16,7 +16,8 @@ import { ChatMessage } from '@/types/chatMessage';
|
|
|
16
16
|
import { ChatTopic } from '@/types/topic';
|
|
17
17
|
import { setNamespace } from '@/utils/storeDebug';
|
|
18
18
|
|
|
19
|
-
import { chatSelectors
|
|
19
|
+
import { chatSelectors } from '../message/selectors';
|
|
20
|
+
import { topicSelectors } from './selectors';
|
|
20
21
|
|
|
21
22
|
const n = setNamespace('topic');
|
|
22
23
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ChatTopic } from '@/types/topic';
|
|
2
|
+
|
|
3
|
+
export interface ChatTopicState {
|
|
4
|
+
activeTopicId?: string;
|
|
5
|
+
isSearchingTopic: boolean;
|
|
6
|
+
searchTopics: ChatTopic[];
|
|
7
|
+
topicLoadingId?: string;
|
|
8
|
+
topicRenamingId?: string;
|
|
9
|
+
topicSearchKeywords: string;
|
|
10
|
+
topics: ChatTopic[];
|
|
11
|
+
/**
|
|
12
|
+
* whether topics have fetched
|
|
13
|
+
*/
|
|
14
|
+
topicsInit: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const initialTopicState: ChatTopicState = {
|
|
18
|
+
isSearchingTopic: false,
|
|
19
|
+
searchTopics: [],
|
|
20
|
+
topicSearchKeywords: '',
|
|
21
|
+
topics: [],
|
|
22
|
+
topicsInit: false,
|
|
23
|
+
};
|
|
@@ -4,7 +4,7 @@ import { ChatStore } from '@/store/chat';
|
|
|
4
4
|
import { initialState } from '@/store/chat/initialState';
|
|
5
5
|
import { merge } from '@/utils/merge';
|
|
6
6
|
|
|
7
|
-
import { topicSelectors } from '
|
|
7
|
+
import { topicSelectors } from '../../selectors';
|
|
8
8
|
|
|
9
9
|
const initialStore = initialState as ChatStore;
|
|
10
10
|
|