@lobehub/chat 0.151.10 → 0.151.11
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/package.json +1 -1
- package/src/app/(main)/chat/features/TelemetryNotification/index.tsx +3 -1
- package/src/app/(main)/settings/agent/Agent.tsx +1 -3
- package/src/features/ChatInput/ActionBar/Temperature.tsx +1 -1
- package/src/services/session/client.test.ts +26 -0
- package/src/services/session/client.ts +1 -1
- package/src/store/global/action.test.ts +38 -0
- package/src/store/global/action.ts +6 -3
- package/src/store/user/slices/preference/action.test.ts +22 -1
- package/src/store/user/slices/preference/action.ts +1 -3
- package/src/store/user/slices/preference/initialState.ts +2 -0
- package/src/store/user/slices/preference/selectors.ts +2 -0
- package/src/store/user/slices/settings/actions/llm.test.ts +3 -9
- package/src/store/user/slices/settings/selectors/settings.ts +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 0.151.11](https://github.com/lobehub/lobe-chat/compare/v0.151.10...v0.151.11)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-04-30**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Fix telemetry preference modal and default agent config error.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Fix telemetry preference modal and default agent config error, closes [#2312](https://github.com/lobehub/lobe-chat/issues/2312) ([8900445](https://github.com/lobehub/lobe-chat/commit/8900445))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
5
30
|
### [Version 0.151.10](https://github.com/lobehub/lobe-chat/compare/v0.151.9...v0.151.10)
|
|
6
31
|
|
|
7
32
|
<sup>Released on **2024-04-30**</sup>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.151.
|
|
3
|
+
"version": "0.151.11",
|
|
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",
|
|
@@ -12,6 +12,7 @@ import { PRIVACY_URL } from '@/const/url';
|
|
|
12
12
|
import { useServerConfigStore } from '@/store/serverConfig';
|
|
13
13
|
import { serverConfigSelectors } from '@/store/serverConfig/selectors';
|
|
14
14
|
import { useUserStore } from '@/store/user';
|
|
15
|
+
import { preferenceSelectors } from '@/store/user/selectors';
|
|
15
16
|
|
|
16
17
|
const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
17
18
|
container: css`
|
|
@@ -57,13 +58,14 @@ const TelemetryNotification = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
57
58
|
|
|
58
59
|
const { t } = useTranslation('common');
|
|
59
60
|
const shouldCheck = useServerConfigStore(serverConfigSelectors.enabledTelemetryChat);
|
|
61
|
+
const isPreferenceInit = useUserStore(preferenceSelectors.isPreferenceInit);
|
|
60
62
|
|
|
61
63
|
const [useCheckTrace, updatePreference] = useUserStore((s) => [
|
|
62
64
|
s.useCheckTrace,
|
|
63
65
|
s.updatePreference,
|
|
64
66
|
]);
|
|
65
67
|
|
|
66
|
-
const { data: showModal, mutate } = useCheckTrace(shouldCheck);
|
|
68
|
+
const { data: showModal, mutate } = useCheckTrace(shouldCheck && isPreferenceInit);
|
|
67
69
|
|
|
68
70
|
const updateTelemetry = (telemetry: boolean) => {
|
|
69
71
|
updatePreference({ telemetry });
|
|
@@ -3,13 +3,11 @@ import { memo } from 'react';
|
|
|
3
3
|
|
|
4
4
|
import { INBOX_SESSION_ID } from '@/const/session';
|
|
5
5
|
import AgentSetting from '@/features/AgentSetting';
|
|
6
|
-
import { useAgentStore } from '@/store/agent';
|
|
7
|
-
import { agentSelectors } from '@/store/agent/selectors';
|
|
8
6
|
import { useUserStore } from '@/store/user';
|
|
9
7
|
import { settingsSelectors } from '@/store/user/selectors';
|
|
10
8
|
|
|
11
9
|
const Agent = memo(() => {
|
|
12
|
-
const config =
|
|
10
|
+
const config = useUserStore(settingsSelectors.defaultAgentConfig, isEqual);
|
|
13
11
|
const meta = useUserStore(settingsSelectors.defaultAgentMeta, isEqual);
|
|
14
12
|
const [updateAgent] = useUserStore((s) => [s.updateDefaultAgent]);
|
|
15
13
|
|
|
@@ -12,7 +12,7 @@ const Temperature = memo(() => {
|
|
|
12
12
|
|
|
13
13
|
const [temperature, updateAgentConfig] = useAgentStore((s) => {
|
|
14
14
|
const config = agentSelectors.currentAgentConfig(s);
|
|
15
|
-
return [config.params
|
|
15
|
+
return [config.params?.temperature, s.updateAgentConfig];
|
|
16
16
|
});
|
|
17
17
|
|
|
18
18
|
return (
|
|
@@ -243,6 +243,32 @@ describe('SessionService', () => {
|
|
|
243
243
|
});
|
|
244
244
|
});
|
|
245
245
|
|
|
246
|
+
describe('hasSessions', () => {
|
|
247
|
+
it('should return false if no sessions exist', async () => {
|
|
248
|
+
// Setup
|
|
249
|
+
(SessionModel.count as Mock).mockResolvedValue(0);
|
|
250
|
+
|
|
251
|
+
// Execute
|
|
252
|
+
const result = await sessionService.hasSessions();
|
|
253
|
+
|
|
254
|
+
// Assert
|
|
255
|
+
expect(SessionModel.count).toHaveBeenCalled();
|
|
256
|
+
expect(result).toBe(false);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should return true if sessions exist', async () => {
|
|
260
|
+
// Setup
|
|
261
|
+
(SessionModel.count as Mock).mockResolvedValue(1);
|
|
262
|
+
|
|
263
|
+
// Execute
|
|
264
|
+
const result = await sessionService.hasSessions();
|
|
265
|
+
|
|
266
|
+
// Assert
|
|
267
|
+
expect(SessionModel.count).toHaveBeenCalled();
|
|
268
|
+
expect(result).toBe(true);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
246
272
|
describe('searchSessions', () => {
|
|
247
273
|
it('should return sessions that match the keyword', async () => {
|
|
248
274
|
// Setup
|
|
@@ -80,7 +80,7 @@ export class ClientService implements ISessionService {
|
|
|
80
80
|
return SessionModel.count();
|
|
81
81
|
}
|
|
82
82
|
async hasSessions() {
|
|
83
|
-
return (await this.countSessions())
|
|
83
|
+
return (await this.countSessions()) !== 0;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
async searchSessions(keyword: string) {
|
|
@@ -4,6 +4,7 @@ import { withSWR } from '~test-utils';
|
|
|
4
4
|
|
|
5
5
|
import { globalService } from '@/services/global';
|
|
6
6
|
import { useGlobalStore } from '@/store/global/index';
|
|
7
|
+
import { initialState } from '@/store/global/initialState';
|
|
7
8
|
|
|
8
9
|
vi.mock('zustand/traditional');
|
|
9
10
|
|
|
@@ -141,4 +142,41 @@ describe('createPreferenceSlice', () => {
|
|
|
141
142
|
expect(useGlobalStore.getState().latestVersion).toBe(latestVersion);
|
|
142
143
|
});
|
|
143
144
|
});
|
|
145
|
+
|
|
146
|
+
describe('useInitGlobalPreference', () => {
|
|
147
|
+
it('should init global preference if there is empty object', async () => {
|
|
148
|
+
vi.spyOn(
|
|
149
|
+
useGlobalStore.getState().preferenceStorage,
|
|
150
|
+
'getFromLocalStorage',
|
|
151
|
+
).mockReturnValueOnce({} as any);
|
|
152
|
+
|
|
153
|
+
const { result } = renderHook(() => useGlobalStore().useInitGlobalPreference(), {
|
|
154
|
+
wrapper: withSWR,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
await waitFor(() => {
|
|
158
|
+
expect(result.current.data).toEqual({});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
expect(useGlobalStore.getState().preference).toEqual(initialState.preference);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should update with data', async () => {
|
|
165
|
+
const { result } = renderHook(() => useGlobalStore());
|
|
166
|
+
vi.spyOn(
|
|
167
|
+
useGlobalStore.getState().preferenceStorage,
|
|
168
|
+
'getFromLocalStorage',
|
|
169
|
+
).mockReturnValueOnce({ inputHeight: 300 } as any);
|
|
170
|
+
|
|
171
|
+
const { result: hooks } = renderHook(() => result.current.useInitGlobalPreference(), {
|
|
172
|
+
wrapper: withSWR,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
await waitFor(() => {
|
|
176
|
+
expect(hooks.current.data).toEqual({ inputHeight: 300 });
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
expect(result.current.preference.inputHeight).toEqual(300);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
144
182
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import isEqual from 'fast-deep-equal';
|
|
1
2
|
import { produce } from 'immer';
|
|
2
3
|
import { gt } from 'semver';
|
|
3
4
|
import useSWR, { SWRResponse } from 'swr';
|
|
@@ -94,9 +95,11 @@ export const globalActionSlice: StateCreator<
|
|
|
94
95
|
() => get().preferenceStorage.getFromLocalStorage(),
|
|
95
96
|
{
|
|
96
97
|
onSuccess: (preference) => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
const nextPreference = merge(get().preference, preference);
|
|
99
|
+
|
|
100
|
+
if (isEqual(get().preference, nextPreference)) return;
|
|
101
|
+
|
|
102
|
+
set({ preference: nextPreference }, false, n('initPreference'));
|
|
100
103
|
},
|
|
101
104
|
},
|
|
102
105
|
),
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { act, renderHook } from '@testing-library/react';
|
|
1
|
+
import { act, renderHook, waitFor } from '@testing-library/react';
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { withSWR } from '~test-utils';
|
|
3
4
|
|
|
5
|
+
import { globalService } from '@/services/global';
|
|
4
6
|
import { useUserStore } from '@/store/user';
|
|
5
7
|
|
|
6
8
|
import { type Guide } from './initialState';
|
|
@@ -38,4 +40,23 @@ describe('createPreferenceSlice', () => {
|
|
|
38
40
|
expect(result.current.preference.hideSyncAlert).toEqual(true);
|
|
39
41
|
});
|
|
40
42
|
});
|
|
43
|
+
|
|
44
|
+
describe('useInitPreference', () => {
|
|
45
|
+
it('should return false when userId is empty', async () => {
|
|
46
|
+
const { result } = renderHook(() => useUserStore());
|
|
47
|
+
|
|
48
|
+
vi.spyOn(result.current.preferenceStorage, 'getFromLocalStorage').mockResolvedValueOnce(
|
|
49
|
+
{} as any,
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const { result: prefernce } = renderHook(() => result.current.useInitPreference(), {
|
|
53
|
+
wrapper: withSWR,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
await waitFor(() => {
|
|
57
|
+
expect(prefernce.current.data).toEqual({});
|
|
58
|
+
expect(result.current.isPreferenceInit).toBeTruthy();
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
41
62
|
});
|
|
@@ -41,9 +41,7 @@ export const createPreferenceSlice: StateCreator<
|
|
|
41
41
|
() => get().preferenceStorage.getFromLocalStorage(),
|
|
42
42
|
{
|
|
43
43
|
onSuccess: (preference) => {
|
|
44
|
-
|
|
45
|
-
set({ preference }, false, n('initPreference'));
|
|
46
|
-
}
|
|
44
|
+
set({ isPreferenceInit: true, preference }, false, n('initPreference'));
|
|
47
45
|
},
|
|
48
46
|
},
|
|
49
47
|
),
|
|
@@ -16,6 +16,7 @@ export interface UserPreference {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export interface UserPreferenceState {
|
|
19
|
+
isPreferenceInit: boolean;
|
|
19
20
|
/**
|
|
20
21
|
* the user preference, which only store in local storage
|
|
21
22
|
*/
|
|
@@ -24,6 +25,7 @@ export interface UserPreferenceState {
|
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export const initialPreferenceState: UserPreferenceState = {
|
|
28
|
+
isPreferenceInit: false,
|
|
27
29
|
preference: {
|
|
28
30
|
guide: {},
|
|
29
31
|
telemetry: null,
|
|
@@ -5,9 +5,11 @@ const useCmdEnterToSend = (s: UserStore): boolean => s.preference.useCmdEnterToS
|
|
|
5
5
|
const userAllowTrace = (s: UserStore) => s.preference.telemetry;
|
|
6
6
|
|
|
7
7
|
const hideSyncAlert = (s: UserStore) => s.preference.hideSyncAlert;
|
|
8
|
+
const isPreferenceInit = (s: UserStore) => s.isPreferenceInit;
|
|
8
9
|
|
|
9
10
|
export const preferenceSelectors = {
|
|
10
11
|
hideSyncAlert,
|
|
12
|
+
isPreferenceInit,
|
|
11
13
|
useCmdEnterToSend,
|
|
12
14
|
userAllowTrace,
|
|
13
15
|
};
|
|
@@ -2,17 +2,11 @@ import { act, renderHook } from '@testing-library/react';
|
|
|
2
2
|
import { describe, expect, it, vi } from 'vitest';
|
|
3
3
|
|
|
4
4
|
import { userService } from '@/services/user';
|
|
5
|
-
import {
|
|
6
|
-
import { UserSettingsState, initialSettingsState } from '@/store/user/slices/settings/initialState';
|
|
7
|
-
import {
|
|
8
|
-
modelConfigSelectors,
|
|
9
|
-
modelProviderSelectors,
|
|
10
|
-
settingsSelectors,
|
|
11
|
-
} from '@/store/user/slices/settings/selectors';
|
|
5
|
+
import { useUserStore } from '@/store/user';
|
|
12
6
|
import { GeneralModelProviderConfig } from '@/types/settings';
|
|
13
|
-
import { merge } from '@/utils/merge';
|
|
14
7
|
|
|
15
|
-
import { CustomModelCardDispatch
|
|
8
|
+
import { CustomModelCardDispatch } from '../reducers/customModelCard';
|
|
9
|
+
import { modelProviderSelectors, settingsSelectors } from '../selectors';
|
|
16
10
|
|
|
17
11
|
// Mock userService
|
|
18
12
|
vi.mock('@/services/user', () => ({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_LANG } from '@/const/locale';
|
|
2
2
|
import { DEFAULT_AGENT_META } from '@/const/meta';
|
|
3
|
-
import { DEFAULT_AGENT, DEFAULT_TTS_CONFIG } from '@/const/settings';
|
|
3
|
+
import { DEFAULT_AGENT, DEFAULT_AGENT_CONFIG, DEFAULT_TTS_CONFIG } from '@/const/settings';
|
|
4
4
|
import { Locales } from '@/locales/resources';
|
|
5
5
|
import { GeneralModelProviderConfig, GlobalLLMProviderKey, GlobalSettings } from '@/types/settings';
|
|
6
6
|
import { isOnServerSide } from '@/utils/env';
|
|
@@ -21,6 +21,7 @@ const password = (s: UserStore) => currentSettings(s).password;
|
|
|
21
21
|
const currentTTS = (s: UserStore) => merge(DEFAULT_TTS_CONFIG, currentSettings(s).tts);
|
|
22
22
|
|
|
23
23
|
const defaultAgent = (s: UserStore) => merge(DEFAULT_AGENT, currentSettings(s).defaultAgent);
|
|
24
|
+
const defaultAgentConfig = (s: UserStore) => merge(DEFAULT_AGENT_CONFIG, defaultAgent(s).config);
|
|
24
25
|
|
|
25
26
|
const defaultAgentMeta = (s: UserStore) => merge(DEFAULT_AGENT_META, defaultAgent(s).meta);
|
|
26
27
|
|
|
@@ -53,6 +54,7 @@ export const settingsSelectors = {
|
|
|
53
54
|
currentTTS,
|
|
54
55
|
dalleConfig,
|
|
55
56
|
defaultAgent,
|
|
57
|
+
defaultAgentConfig,
|
|
56
58
|
defaultAgentMeta,
|
|
57
59
|
exportSettings,
|
|
58
60
|
isDalleAutoGenerating,
|