@lobehub/chat 0.160.5 → 0.160.7
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 +65 -0
- package/locales/ar/error.json +2 -0
- package/locales/bg-BG/error.json +2 -0
- package/locales/de-DE/error.json +2 -0
- package/locales/en-US/error.json +2 -0
- package/locales/es-ES/error.json +2 -0
- package/locales/fr-FR/error.json +2 -0
- package/locales/it-IT/error.json +2 -0
- package/locales/ja-JP/error.json +2 -0
- package/locales/ko-KR/error.json +2 -0
- package/locales/nl-NL/error.json +2 -0
- package/locales/pl-PL/error.json +2 -0
- package/locales/pt-BR/error.json +2 -0
- package/locales/ru-RU/error.json +2 -0
- package/locales/tr-TR/error.json +2 -0
- package/locales/vi-VN/error.json +2 -0
- package/locales/zh-CN/error.json +2 -0
- package/locales/zh-TW/error.json +2 -0
- package/package.json +2 -2
- package/src/app/(loading)/Redirect.tsx +8 -0
- package/src/app/(main)/chat/(workspace)/features/TelemetryNotification.tsx +42 -75
- package/src/app/(main)/market/_layout/Desktop/index.tsx +24 -20
- package/src/app/(main)/settings/llm/Azure/index.tsx +1 -0
- package/src/app/(main)/settings/llm/OpenAI/index.tsx +0 -1
- package/src/app/trpc/edge/[trpc]/route.ts +1 -1
- package/src/components/FetchErrorNotification/Description.tsx +48 -0
- package/src/components/FetchErrorNotification/index.tsx +15 -0
- package/src/components/ModelProviderIcon/index.tsx +6 -1
- package/src/components/Notification/index.tsx +95 -0
- package/src/config/server/provider.ts +1 -0
- package/src/database/client/models/__tests__/message.test.ts +2 -2
- package/src/database/client/models/message.ts +2 -2
- package/src/features/ModelSwitchPanel/index.tsx +6 -3
- package/src/features/User/UserAvatar.tsx +4 -3
- package/src/locales/default/error.ts +3 -1
- package/src/middleware.ts +10 -1
- package/src/server/globalConfig/index.ts +2 -0
- package/src/server/routers/edge/config/__snapshots__/index.test.ts.snap +1 -0
- package/src/services/file/type.ts +2 -3
- package/src/services/message/client.test.ts +151 -23
- package/src/services/message/client.ts +9 -5
- package/src/services/message/type.ts +10 -3
- package/src/services/upload.ts +4 -4
- package/src/services/user/client.ts +17 -1
- package/src/services/user/type.ts +14 -0
- package/src/store/agent/slices/chat/selectors.test.ts +2 -2
- package/src/store/agent/slices/chat/selectors.ts +1 -1
- package/src/store/chat/slices/enchance/action.test.ts +4 -3
- package/src/store/chat/slices/enchance/action.ts +3 -2
- package/src/store/chat/slices/plugin/action.test.ts +3 -5
- package/src/store/chat/slices/plugin/action.ts +1 -1
- package/src/store/market/action.ts +7 -0
- package/src/store/user/slices/auth/selectors.ts +1 -1
- package/src/store/user/slices/preference/action.test.ts +4 -9
- package/src/store/user/slices/preference/action.ts +17 -20
- package/src/store/user/slices/settings/selectors/modelConfig.test.ts +29 -1
- package/src/store/user/slices/settings/selectors/modelConfig.ts +1 -1
- package/src/tools/dalle/Render/Item/Error.tsx +1 -1
- package/src/types/files.ts +33 -0
- /package/src/types/{user.ts → user/index.ts} +0 -0
|
@@ -105,12 +105,13 @@ export const chatEnhance: StateCreator<
|
|
|
105
105
|
},
|
|
106
106
|
|
|
107
107
|
updateMessageTTS: async (id, data) => {
|
|
108
|
-
await messageService.
|
|
108
|
+
await messageService.updateMessageTTS(id, data);
|
|
109
109
|
await get().refreshMessages();
|
|
110
110
|
},
|
|
111
111
|
|
|
112
112
|
updateMessageTranslate: async (id, data) => {
|
|
113
|
-
await messageService.
|
|
113
|
+
await messageService.updateMessageTranslate(id, data);
|
|
114
|
+
|
|
114
115
|
await get().refreshMessages();
|
|
115
116
|
},
|
|
116
117
|
});
|
|
@@ -372,11 +372,9 @@ describe('ChatPluginAction', () => {
|
|
|
372
372
|
await result.current.updatePluginState(messageId, pluginStateKey, pluginStateValue);
|
|
373
373
|
});
|
|
374
374
|
|
|
375
|
-
expect(messageService.updateMessagePluginState).toHaveBeenCalledWith(
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
pluginStateValue,
|
|
379
|
-
);
|
|
375
|
+
expect(messageService.updateMessagePluginState).toHaveBeenCalledWith(messageId, {
|
|
376
|
+
[pluginStateKey]: pluginStateValue,
|
|
377
|
+
});
|
|
380
378
|
expect(initialState.refreshMessages).toHaveBeenCalled();
|
|
381
379
|
});
|
|
382
380
|
});
|
|
@@ -298,7 +298,7 @@ export const chatPlugin: StateCreator<
|
|
|
298
298
|
updatePluginState: async (id, key, value) => {
|
|
299
299
|
const { refreshMessages } = get();
|
|
300
300
|
|
|
301
|
-
await messageService.updateMessagePluginState(id, key
|
|
301
|
+
await messageService.updateMessagePluginState(id, { [key]: value });
|
|
302
302
|
await refreshMessages();
|
|
303
303
|
},
|
|
304
304
|
});
|
|
@@ -12,6 +12,7 @@ import type { Store } from './store';
|
|
|
12
12
|
export interface StoreAction {
|
|
13
13
|
activateAgent: (identifier: string) => void;
|
|
14
14
|
deactivateAgent: () => void;
|
|
15
|
+
getAgentById: (identifiers: string) => Promise<AgentsMarketItem>;
|
|
15
16
|
setSearchKeywords: (keywords: string) => void;
|
|
16
17
|
updateAgentMap: (key: string, value: AgentsMarketItem) => void;
|
|
17
18
|
useFetchAgent: (identifier: string) => SWRResponse<AgentsMarketItem>;
|
|
@@ -30,6 +31,12 @@ export const createMarketAction: StateCreator<
|
|
|
30
31
|
deactivateAgent: () => {
|
|
31
32
|
set({ currentIdentifier: '' }, false, 'deactivateAgent');
|
|
32
33
|
},
|
|
34
|
+
|
|
35
|
+
getAgentById: async (identifier) => {
|
|
36
|
+
const locale = globalHelpers.getCurrentLanguage();
|
|
37
|
+
return marketService.getAgentManifest(identifier, locale as string);
|
|
38
|
+
},
|
|
39
|
+
|
|
33
40
|
setSearchKeywords: (keywords) => {
|
|
34
41
|
set({ searchKeywords: keywords });
|
|
35
42
|
},
|
|
@@ -43,5 +43,5 @@ const isLogin = (s: UserStore) => {
|
|
|
43
43
|
export const authSelectors = {
|
|
44
44
|
isLogin,
|
|
45
45
|
isLoginWithAuth: (s: UserStore) => s.isSignedIn,
|
|
46
|
-
isLoginWithClerk: (s: UserStore) => s.isSignedIn && enableClerk,
|
|
46
|
+
isLoginWithClerk: (s: UserStore): boolean => (s.isSignedIn && enableClerk) || false,
|
|
47
47
|
};
|
|
@@ -3,6 +3,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
3
3
|
import { withSWR } from '~test-utils';
|
|
4
4
|
|
|
5
5
|
import { DEFAULT_PREFERENCE } from '@/const/user';
|
|
6
|
+
import { userService } from '@/services/user';
|
|
6
7
|
import { useUserStore } from '@/store/user';
|
|
7
8
|
import { UserGuide, UserPreference } from '@/types/user';
|
|
8
9
|
|
|
@@ -44,9 +45,7 @@ describe('createPreferenceSlice', () => {
|
|
|
44
45
|
it('should return false when userId is empty', async () => {
|
|
45
46
|
const { result } = renderHook(() => useUserStore());
|
|
46
47
|
|
|
47
|
-
vi.spyOn(
|
|
48
|
-
{} as any,
|
|
49
|
-
);
|
|
48
|
+
vi.spyOn(userService, 'getPreference').mockResolvedValueOnce({} as any);
|
|
50
49
|
|
|
51
50
|
const { result: prefernce } = renderHook(() => result.current.useInitPreference(), {
|
|
52
51
|
wrapper: withSWR,
|
|
@@ -60,9 +59,7 @@ describe('createPreferenceSlice', () => {
|
|
|
60
59
|
it('should return default preference when local storage is empty', async () => {
|
|
61
60
|
const { result } = renderHook(() => useUserStore());
|
|
62
61
|
|
|
63
|
-
vi.spyOn(
|
|
64
|
-
{} as any,
|
|
65
|
-
);
|
|
62
|
+
vi.spyOn(userService, 'getPreference').mockResolvedValueOnce({} as any);
|
|
66
63
|
|
|
67
64
|
renderHook(() => result.current.useInitPreference(), {
|
|
68
65
|
wrapper: withSWR,
|
|
@@ -82,9 +79,7 @@ describe('createPreferenceSlice', () => {
|
|
|
82
79
|
guide: { topic: false, moveSettingsToAvatar: true },
|
|
83
80
|
};
|
|
84
81
|
|
|
85
|
-
vi.spyOn(
|
|
86
|
-
savedPreference,
|
|
87
|
-
);
|
|
82
|
+
vi.spyOn(userService, 'getPreference').mockResolvedValueOnce(savedPreference);
|
|
88
83
|
|
|
89
84
|
const { result: prefernce } = renderHook(() => result.current.useInitPreference(), {
|
|
90
85
|
wrapper: withSWR,
|
|
@@ -3,6 +3,7 @@ import type { StateCreator } from 'zustand/vanilla';
|
|
|
3
3
|
|
|
4
4
|
import { DEFAULT_PREFERENCE } from '@/const/user';
|
|
5
5
|
import { useClientDataSWR } from '@/libs/swr';
|
|
6
|
+
import { userService } from '@/services/user';
|
|
6
7
|
import type { UserStore } from '@/store/user';
|
|
7
8
|
import { UserGuide, UserPreference } from '@/types/user';
|
|
8
9
|
import { merge } from '@/utils/merge';
|
|
@@ -11,8 +12,8 @@ import { setNamespace } from '@/utils/storeDebug';
|
|
|
11
12
|
const n = setNamespace('preference');
|
|
12
13
|
|
|
13
14
|
export interface PreferenceAction {
|
|
14
|
-
updateGuideState: (guide: Partial<UserGuide>) => void
|
|
15
|
-
updatePreference: (preference: Partial<UserPreference>, action?: any) => void
|
|
15
|
+
updateGuideState: (guide: Partial<UserGuide>) => Promise<void>;
|
|
16
|
+
updatePreference: (preference: Partial<UserPreference>, action?: any) => Promise<void>;
|
|
16
17
|
useInitPreference: () => SWRResponse;
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -22,33 +23,29 @@ export const createPreferenceSlice: StateCreator<
|
|
|
22
23
|
[],
|
|
23
24
|
PreferenceAction
|
|
24
25
|
> = (set, get) => ({
|
|
25
|
-
updateGuideState: (guide) => {
|
|
26
|
+
updateGuideState: async (guide) => {
|
|
26
27
|
const { updatePreference } = get();
|
|
27
28
|
const nextGuide = merge(get().preference.guide, guide);
|
|
28
|
-
updatePreference({ guide: nextGuide });
|
|
29
|
+
await updatePreference({ guide: nextGuide });
|
|
29
30
|
},
|
|
30
|
-
updatePreference: (preference, action) => {
|
|
31
|
+
updatePreference: async (preference, action) => {
|
|
31
32
|
const nextPreference = merge(get().preference, preference);
|
|
32
33
|
|
|
33
34
|
set({ preference: nextPreference }, false, action || n('updatePreference'));
|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
await userService.updatePreference(nextPreference);
|
|
36
37
|
},
|
|
37
38
|
|
|
38
39
|
useInitPreference: () =>
|
|
39
|
-
useClientDataSWR<UserPreference>(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
false,
|
|
49
|
-
n('initPreference'),
|
|
50
|
-
);
|
|
51
|
-
},
|
|
40
|
+
useClientDataSWR<UserPreference>('initUserPreference', userService.getPreference, {
|
|
41
|
+
onSuccess: (preference) => {
|
|
42
|
+
const isEmpty = Object.keys(preference).length === 0;
|
|
43
|
+
|
|
44
|
+
set(
|
|
45
|
+
{ isPreferenceInit: true, preference: isEmpty ? DEFAULT_PREFERENCE : preference },
|
|
46
|
+
false,
|
|
47
|
+
n('initPreference'),
|
|
48
|
+
);
|
|
52
49
|
},
|
|
53
|
-
),
|
|
50
|
+
}),
|
|
54
51
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
|
|
3
|
+
import { UserStore } from '@/store/user';
|
|
3
4
|
import { merge } from '@/utils/merge';
|
|
4
5
|
|
|
5
|
-
import { UserStore, useUserStore } from '../../../store';
|
|
6
6
|
import { UserSettingsState, initialSettingsState } from '../initialState';
|
|
7
7
|
import { modelConfigSelectors } from './modelConfig';
|
|
8
8
|
|
|
@@ -33,6 +33,34 @@ describe('modelConfigSelectors', () => {
|
|
|
33
33
|
});
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
+
describe('isProviderFetchOnClient', () => {
|
|
37
|
+
it('client fetch should disabled on default', () => {
|
|
38
|
+
const s = merge(initialSettingsState, {
|
|
39
|
+
settings: {
|
|
40
|
+
languageModel: {
|
|
41
|
+
azure: {
|
|
42
|
+
endpoint: 'endpoint',
|
|
43
|
+
apiKey: 'apikey',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
} as UserSettingsState) as unknown as UserStore;
|
|
48
|
+
|
|
49
|
+
expect(modelConfigSelectors.isProviderFetchOnClient('azure')(s)).toBe(false);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('client fetch should enabled if user set it enabled', () => {
|
|
53
|
+
const s = merge(initialSettingsState, {
|
|
54
|
+
settings: {
|
|
55
|
+
languageModel: {
|
|
56
|
+
azure: { fetchOnClient: true },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
} as UserSettingsState) as unknown as UserStore;
|
|
60
|
+
expect(modelConfigSelectors.isProviderFetchOnClient('azure')(s)).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
36
64
|
describe('getCustomModelCardById', () => {
|
|
37
65
|
it('should return the custom model card with the given id and provider', () => {
|
|
38
66
|
const s = merge(initialSettingsState, {
|
|
@@ -13,7 +13,7 @@ const isProviderFetchOnClient = (provider: GlobalLLMProviderKey | string) => (s:
|
|
|
13
13
|
const config = getProviderConfigById(provider)(s);
|
|
14
14
|
if (typeof config?.fetchOnClient !== 'undefined') return config?.fetchOnClient;
|
|
15
15
|
|
|
16
|
-
return
|
|
16
|
+
return false;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
const getCustomModelCard =
|
|
@@ -28,7 +28,7 @@ const Error = memo<ErrorProps>(({ messageId, index }) => {
|
|
|
28
28
|
<Alert
|
|
29
29
|
extra={
|
|
30
30
|
<Highlighter copyButtonSize={'small'} language={'json'}>
|
|
31
|
-
{JSON.stringify(error
|
|
31
|
+
{JSON.stringify(error?.body || error, null, 2)}
|
|
32
32
|
</Highlighter>
|
|
33
33
|
}
|
|
34
34
|
extraDefaultExpand
|
package/src/types/files.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
1
3
|
export interface FilePreview {
|
|
2
4
|
base64Url?: string;
|
|
3
5
|
data?: ArrayBuffer;
|
|
@@ -6,3 +8,34 @@ export interface FilePreview {
|
|
|
6
8
|
saveMode: 'local' | 'url';
|
|
7
9
|
url: string;
|
|
8
10
|
}
|
|
11
|
+
|
|
12
|
+
export const UploadFileSchema = z.object({
|
|
13
|
+
data: z.instanceof(ArrayBuffer).optional(),
|
|
14
|
+
/**
|
|
15
|
+
* file type
|
|
16
|
+
* @example 'image/png'
|
|
17
|
+
*/
|
|
18
|
+
fileType: z.string(),
|
|
19
|
+
metadata: z.any().optional(),
|
|
20
|
+
/**
|
|
21
|
+
* file name
|
|
22
|
+
* @example 'test.png'
|
|
23
|
+
*/
|
|
24
|
+
name: z.string(),
|
|
25
|
+
/**
|
|
26
|
+
* the mode database save the file
|
|
27
|
+
* local mean save the raw file into data
|
|
28
|
+
* url mean upload the file to a cdn and then save the url
|
|
29
|
+
*/
|
|
30
|
+
saveMode: z.enum(['local', 'url']),
|
|
31
|
+
/**
|
|
32
|
+
* file size
|
|
33
|
+
*/
|
|
34
|
+
size: z.number(),
|
|
35
|
+
/**
|
|
36
|
+
* file url if saveMode is url
|
|
37
|
+
*/
|
|
38
|
+
url: z.string().optional(),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export type UploadFileParams = z.infer<typeof UploadFileSchema>;
|
|
File without changes
|