@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,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isDesktop } from '@lobechat/const';
|
|
2
2
|
import { getModelPropertyWithFallback, resolveImageSinglePrice } from '@lobechat/model-runtime';
|
|
3
3
|
import { uniqBy } from 'lodash-es';
|
|
4
4
|
import {
|
|
@@ -319,8 +319,7 @@ export const createAiProviderSlice: StateCreator<
|
|
|
319
319
|
const isAuthLoaded = authSelectors.isLoaded(useUserStore.getState());
|
|
320
320
|
// Only fetch when auth is loaded and login status is explicitly defined (true or false)
|
|
321
321
|
// Prevents unnecessary requests when login state is null/undefined
|
|
322
|
-
const shouldFetch =
|
|
323
|
-
isAuthLoaded && !isDeprecatedEdition && isLogin !== null && isLogin !== undefined;
|
|
322
|
+
const shouldFetch = isAuthLoaded && isLogin !== null && isLogin !== undefined;
|
|
324
323
|
return useClientDataSWR<AiProviderRuntimeStateWithBuiltinModels | undefined>(
|
|
325
324
|
shouldFetch ? [AiProviderSwrKey.fetchAiProviderRuntimeState, isLogin] : null,
|
|
326
325
|
async ([, isLogin]) => {
|
|
@@ -381,7 +380,7 @@ export const createAiProviderSlice: StateCreator<
|
|
|
381
380
|
};
|
|
382
381
|
},
|
|
383
382
|
{
|
|
384
|
-
focusThrottleInterval: isDesktop
|
|
383
|
+
focusThrottleInterval: isDesktop ? 100 : undefined,
|
|
385
384
|
onSuccess: (data) => {
|
|
386
385
|
if (!data) return;
|
|
387
386
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable sort-keys-fix/sort-keys-fix, typescript-sort-keys/interface */
|
|
2
2
|
// Disable the auto sort key eslint rule to make the code more logic and readable
|
|
3
|
-
import { LOADING_FLAT, THREAD_DRAFT_ID
|
|
3
|
+
import { LOADING_FLAT, THREAD_DRAFT_ID } from '@lobechat/const';
|
|
4
4
|
import { chainSummaryTitle } from '@lobechat/prompts';
|
|
5
5
|
import {
|
|
6
6
|
CreateMessageParams,
|
|
@@ -222,7 +222,7 @@ export const chatThreadMessage: StateCreator<
|
|
|
222
222
|
|
|
223
223
|
useFetchThreads: (enable, topicId) =>
|
|
224
224
|
useClientDataSWR<ThreadItem[]>(
|
|
225
|
-
enable && !!topicId
|
|
225
|
+
enable && !!topicId ? [SWR_USE_FETCH_THREADS, topicId] : null,
|
|
226
226
|
async ([, topicId]: [string, string]) => threadService.getThreads(topicId),
|
|
227
227
|
{
|
|
228
228
|
onSuccess: (threads) => {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest';
|
|
2
2
|
|
|
3
|
-
import { DatabaseLoadingState } from '@/types/clientDB';
|
|
4
3
|
import { merge } from '@/utils/merge';
|
|
5
4
|
|
|
6
5
|
import { GlobalState, INITIAL_STATUS, initialState } from '../initialState';
|
|
@@ -108,101 +107,4 @@ describe('systemStatusSelectors', () => {
|
|
|
108
107
|
expect(systemStatusSelectors.themeMode(s)).toBe('auto');
|
|
109
108
|
});
|
|
110
109
|
});
|
|
111
|
-
|
|
112
|
-
describe('pglite status selectors', () => {
|
|
113
|
-
describe('isPgliteNotEnabled', () => {
|
|
114
|
-
it('should return true when conditions are met', () => {
|
|
115
|
-
const s: GlobalState = {
|
|
116
|
-
...initialState,
|
|
117
|
-
isStatusInit: true,
|
|
118
|
-
status: {
|
|
119
|
-
...initialState.status,
|
|
120
|
-
isEnablePglite: false,
|
|
121
|
-
},
|
|
122
|
-
};
|
|
123
|
-
expect(systemStatusSelectors.isPgliteNotEnabled(s)).toBe(true);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('should return false when isStatusInit is false', () => {
|
|
127
|
-
const s: GlobalState = {
|
|
128
|
-
...initialState,
|
|
129
|
-
isStatusInit: false,
|
|
130
|
-
status: {
|
|
131
|
-
...initialState.status,
|
|
132
|
-
isEnablePglite: false,
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
expect(systemStatusSelectors.isPgliteNotEnabled(s)).toBe(false);
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
describe('isPgliteNotInited', () => {
|
|
140
|
-
it('should return true when pglite is enabled but not ready', () => {
|
|
141
|
-
const s: GlobalState = {
|
|
142
|
-
...initialState,
|
|
143
|
-
isStatusInit: true,
|
|
144
|
-
status: {
|
|
145
|
-
...initialState.status,
|
|
146
|
-
isEnablePglite: true,
|
|
147
|
-
},
|
|
148
|
-
initClientDBStage: DatabaseLoadingState.Initializing,
|
|
149
|
-
};
|
|
150
|
-
expect(systemStatusSelectors.isPgliteNotInited(s)).toBe(true);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
it('should return false when pglite is ready', () => {
|
|
154
|
-
const s: GlobalState = {
|
|
155
|
-
...initialState,
|
|
156
|
-
isStatusInit: true,
|
|
157
|
-
status: {
|
|
158
|
-
...initialState.status,
|
|
159
|
-
isEnablePglite: true,
|
|
160
|
-
},
|
|
161
|
-
initClientDBStage: DatabaseLoadingState.Ready,
|
|
162
|
-
};
|
|
163
|
-
expect(systemStatusSelectors.isPgliteNotInited(s)).toBe(false);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('should return false when pglite is not enabled', () => {
|
|
167
|
-
const s: GlobalState = {
|
|
168
|
-
...initialState,
|
|
169
|
-
isStatusInit: true,
|
|
170
|
-
status: {
|
|
171
|
-
...initialState.status,
|
|
172
|
-
isEnablePglite: false,
|
|
173
|
-
},
|
|
174
|
-
initClientDBStage: DatabaseLoadingState.Initializing,
|
|
175
|
-
};
|
|
176
|
-
expect(systemStatusSelectors.isPgliteNotInited(s)).toBe(false);
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
describe('isPgliteInited', () => {
|
|
181
|
-
it('should return true when pglite is enabled and ready', () => {
|
|
182
|
-
const s: GlobalState = {
|
|
183
|
-
...initialState,
|
|
184
|
-
isStatusInit: true,
|
|
185
|
-
status: {
|
|
186
|
-
...initialState.status,
|
|
187
|
-
isEnablePglite: true,
|
|
188
|
-
},
|
|
189
|
-
initClientDBStage: DatabaseLoadingState.Ready,
|
|
190
|
-
};
|
|
191
|
-
expect(systemStatusSelectors.isPgliteInited(s)).toBe(true);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
it('should return false when not ready', () => {
|
|
195
|
-
const s: GlobalState = {
|
|
196
|
-
...initialState,
|
|
197
|
-
isStatusInit: true,
|
|
198
|
-
status: {
|
|
199
|
-
...initialState.status,
|
|
200
|
-
isEnablePglite: true,
|
|
201
|
-
},
|
|
202
|
-
initClientDBStage: DatabaseLoadingState.Initializing,
|
|
203
|
-
};
|
|
204
|
-
expect(systemStatusSelectors.isPgliteInited(s)).toBe(false);
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
110
|
});
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { isServerMode, isUsePgliteDB } from '@/const/version';
|
|
2
|
-
import { DatabaseLoadingState } from '@/types/clientDB';
|
|
3
|
-
|
|
4
1
|
import { GlobalState, INITIAL_STATUS } from '../initialState';
|
|
5
2
|
|
|
6
3
|
export const systemStatus = (s: GlobalState) => s.status;
|
|
@@ -32,29 +29,6 @@ const wideScreen = (s: GlobalState) => !s.status.noWideScreen;
|
|
|
32
29
|
const chatInputHeight = (s: GlobalState) => s.status.chatInputHeight || 64;
|
|
33
30
|
const expandInputActionbar = (s: GlobalState) => s.status.expandInputActionbar;
|
|
34
31
|
const isStatusInit = (s: GlobalState) => !!s.isStatusInit;
|
|
35
|
-
const isPgliteNotEnabled = (s: GlobalState) =>
|
|
36
|
-
isUsePgliteDB && !isServerMode && isStatusInit(s) && !s.status.isEnablePglite;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* 当且仅当 client db 模式,且 pglite 未初始化完成时返回 true
|
|
40
|
-
*/
|
|
41
|
-
const isPgliteNotInited = (s: GlobalState) =>
|
|
42
|
-
isUsePgliteDB &&
|
|
43
|
-
isStatusInit(s) &&
|
|
44
|
-
s.status.isEnablePglite &&
|
|
45
|
-
s.initClientDBStage !== DatabaseLoadingState.Ready;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* 当且仅当 client db 模式,且 pglite 初始化完成时返回 true
|
|
49
|
-
*/
|
|
50
|
-
const isPgliteInited = (s: GlobalState): boolean =>
|
|
51
|
-
(isStatusInit(s) &&
|
|
52
|
-
s.status.isEnablePglite &&
|
|
53
|
-
s.initClientDBStage === DatabaseLoadingState.Ready) ||
|
|
54
|
-
false;
|
|
55
|
-
|
|
56
|
-
// 这个变量控制 clientdb 是否完成初始化,正常来说,只有 pgliteDB 模式下,才会存在变化,其他时候都是 true
|
|
57
|
-
const isDBInited = (s: GlobalState): boolean => (isUsePgliteDB ? isPgliteInited(s) : true);
|
|
58
32
|
|
|
59
33
|
const getAgentSystemRoleExpanded =
|
|
60
34
|
(agentId: string) =>
|
|
@@ -80,10 +54,6 @@ export const systemStatusSelectors = {
|
|
|
80
54
|
imagePanelWidth,
|
|
81
55
|
imageTopicPanelWidth,
|
|
82
56
|
inZenMode,
|
|
83
|
-
isDBInited,
|
|
84
|
-
isPgliteInited,
|
|
85
|
-
isPgliteNotEnabled,
|
|
86
|
-
isPgliteNotInited,
|
|
87
57
|
isShowCredit,
|
|
88
58
|
isStatusInit,
|
|
89
59
|
language,
|
|
@@ -11,7 +11,7 @@ describe('featureFlagsSelectors', () => {
|
|
|
11
11
|
featureFlags: {
|
|
12
12
|
...mapFeatureFlagsEnvToState(DEFAULT_FEATURE_FLAGS),
|
|
13
13
|
isAgentEditable: false,
|
|
14
|
-
|
|
14
|
+
showProvider: true,
|
|
15
15
|
showMarket: true,
|
|
16
16
|
showAiImage: true,
|
|
17
17
|
},
|
|
@@ -20,7 +20,7 @@ describe('featureFlagsSelectors', () => {
|
|
|
20
20
|
const result = featureFlagsSelectors(store.getState());
|
|
21
21
|
|
|
22
22
|
expect(result.isAgentEditable).toBe(false);
|
|
23
|
-
expect(result.
|
|
23
|
+
expect(result.showProvider).toBe(true);
|
|
24
24
|
expect(result.showMarket).toBe(true);
|
|
25
25
|
expect(result.showAiImage).toBe(true);
|
|
26
26
|
});
|
|
@@ -21,7 +21,6 @@ describe('createServerConfigStore', () => {
|
|
|
21
21
|
it('should initialize store with default state', () => {
|
|
22
22
|
const store = createServerConfigStore();
|
|
23
23
|
|
|
24
|
-
expect(store.getState().featureFlags).toHaveProperty('showLLM');
|
|
25
24
|
expect(store.getState().featureFlags).toHaveProperty('enablePlugins');
|
|
26
25
|
expect(store.getState()).toMatchObject({
|
|
27
26
|
serverConfig: { telemetry: {}, aiProvider: {} },
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { Skeleton } from 'antd';
|
|
4
|
-
import { DatabaseIcon } from 'lucide-react';
|
|
5
|
-
import { memo } from 'react';
|
|
6
|
-
import { useTranslation } from 'react-i18next';
|
|
7
|
-
import { Flexbox } from 'react-layout-kit';
|
|
8
|
-
import useSWR from 'swr';
|
|
9
|
-
|
|
10
|
-
import GroupIcon from '@/components/GroupIcon';
|
|
11
|
-
import IndexCard from '@/components/IndexCard';
|
|
12
|
-
import ProgressItem from '@/components/ProgressItem';
|
|
13
|
-
import { formatSize } from '@/utils/format';
|
|
14
|
-
|
|
15
|
-
const IndexedDBStorage = memo(() => {
|
|
16
|
-
const { t } = useTranslation('setting');
|
|
17
|
-
const { data, isLoading } = useSWR('fetch-client-usage', async () => {
|
|
18
|
-
const estimate = await navigator.storage.estimate();
|
|
19
|
-
const quota = estimate.quota || 0;
|
|
20
|
-
const usage = estimate.usage || 0;
|
|
21
|
-
|
|
22
|
-
const percent = (usage / quota) * 100;
|
|
23
|
-
|
|
24
|
-
return { percent: percent < 1 ? 1 : percent, total: quota, used: usage };
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
return (
|
|
28
|
-
<IndexCard
|
|
29
|
-
desc={t('storage.desc', { day: 15 })}
|
|
30
|
-
icon={<GroupIcon icon={DatabaseIcon} />}
|
|
31
|
-
padding={0}
|
|
32
|
-
title={t('storage.title')}
|
|
33
|
-
>
|
|
34
|
-
{isLoading ? (
|
|
35
|
-
<Flexbox padding={16}>
|
|
36
|
-
<Skeleton active paragraph={{ rows: 1, width: '100%' }} title={false} />
|
|
37
|
-
<Skeleton.Button active style={{ height: 48, width: '100%' }} />
|
|
38
|
-
</Flexbox>
|
|
39
|
-
) : (
|
|
40
|
-
<Flexbox gap={16} paddingBlock={16}>
|
|
41
|
-
<ProgressItem
|
|
42
|
-
percent={data?.percent || 0}
|
|
43
|
-
title={t('storage.used')}
|
|
44
|
-
usage={{
|
|
45
|
-
total: data ? formatSize(data.total) : '-',
|
|
46
|
-
used: data ? formatSize(data.used) : '-',
|
|
47
|
-
}}
|
|
48
|
-
/>
|
|
49
|
-
</Flexbox>
|
|
50
|
-
)}
|
|
51
|
-
</IndexCard>
|
|
52
|
-
);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
export default IndexedDBStorage;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { ActionIcon } from '@lobehub/ui';
|
|
2
|
-
import { Upload } from 'antd';
|
|
3
|
-
import { FileUp, LucideImage } from 'lucide-react';
|
|
4
|
-
import { memo } from 'react';
|
|
5
|
-
import { useTranslation } from 'react-i18next';
|
|
6
|
-
|
|
7
|
-
import { message } from '@/components/AntdStaticMethods';
|
|
8
|
-
import { useModelSupportFiles } from '@/hooks/useModelSupportFiles';
|
|
9
|
-
import { useModelSupportVision } from '@/hooks/useModelSupportVision';
|
|
10
|
-
import { useAgentStore } from '@/store/agent';
|
|
11
|
-
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
12
|
-
import { useFileStore } from '@/store/file';
|
|
13
|
-
|
|
14
|
-
const FileUpload = memo(() => {
|
|
15
|
-
const { t } = useTranslation('chat');
|
|
16
|
-
|
|
17
|
-
const upload = useFileStore((s) => s.uploadChatFiles);
|
|
18
|
-
|
|
19
|
-
const model = useAgentStore(agentSelectors.currentAgentModel);
|
|
20
|
-
const provider = useAgentStore(agentSelectors.currentAgentModelProvider);
|
|
21
|
-
|
|
22
|
-
const enabledFiles = useModelSupportFiles(model, provider);
|
|
23
|
-
const supportVision = useModelSupportVision(model, provider);
|
|
24
|
-
const canUpload = enabledFiles || supportVision;
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<Upload
|
|
28
|
-
accept={enabledFiles ? undefined : 'image/*'}
|
|
29
|
-
beforeUpload={async (file) => {
|
|
30
|
-
// Check if trying to upload non-image files in client mode
|
|
31
|
-
if (!enabledFiles && !file.type.startsWith('image')) {
|
|
32
|
-
message.warning(t('upload.clientMode.fileNotSupported'));
|
|
33
|
-
return false;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
await upload([file]);
|
|
37
|
-
|
|
38
|
-
return false;
|
|
39
|
-
}}
|
|
40
|
-
disabled={!canUpload}
|
|
41
|
-
multiple={true}
|
|
42
|
-
showUploadList={false}
|
|
43
|
-
>
|
|
44
|
-
<ActionIcon
|
|
45
|
-
disabled={!canUpload}
|
|
46
|
-
icon={enabledFiles ? FileUp : LucideImage}
|
|
47
|
-
title={t(
|
|
48
|
-
canUpload
|
|
49
|
-
? enabledFiles
|
|
50
|
-
? 'upload.clientMode.actionFiletip'
|
|
51
|
-
: 'upload.clientMode.actionTooltip'
|
|
52
|
-
: 'upload.clientMode.disabled',
|
|
53
|
-
)}
|
|
54
|
-
tooltipProps={{
|
|
55
|
-
placement: 'bottom',
|
|
56
|
-
}}
|
|
57
|
-
/>
|
|
58
|
-
</Upload>
|
|
59
|
-
);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
export default FileUpload;
|