@lobehub/lobehub 2.0.0-next.67 → 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 +50 -0
- package/changelog/v1.json +18 -0
- package/package.json +2 -8
- package/packages/const/src/version.ts +0 -5
- package/packages/database/src/models/__tests__/chunk.test.ts +38 -0
- package/packages/model-runtime/src/core/streams/ollama.test.ts +67 -0
- package/packages/model-runtime/src/core/streams/ollama.ts +5 -5
- 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
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.69](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.68...v2.0.0-next.69)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2025-11-17**</sup>
|
|
8
|
+
|
|
9
|
+
#### ♻ Code Refactoring
|
|
10
|
+
|
|
11
|
+
- **misc**: Remove `language_model_settings` and remove isDeprecatedEdition.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Code refactoring
|
|
19
|
+
|
|
20
|
+
- **misc**: Remove `language_model_settings` and remove isDeprecatedEdition, closes [#10264](https://github.com/lobehub/lobe-chat/issues/10264) ([ae613c7](https://github.com/lobehub/lobe-chat/commit/ae613c7))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## [Version 2.0.0-next.68](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.67...v2.0.0-next.68)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2025-11-16**</sup>
|
|
33
|
+
|
|
34
|
+
#### 🐛 Bug Fixes
|
|
35
|
+
|
|
36
|
+
- **misc**: The tool to fail execution on ollama when a message contains b….
|
|
37
|
+
|
|
38
|
+
<br/>
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
42
|
+
|
|
43
|
+
#### What's fixed
|
|
44
|
+
|
|
45
|
+
- **misc**: The tool to fail execution on ollama when a message contains b…, closes [#10259](https://github.com/lobehub/lobe-chat/issues/10259) ([1ad8080](https://github.com/lobehub/lobe-chat/commit/1ad8080))
|
|
46
|
+
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<div align="right">
|
|
50
|
+
|
|
51
|
+
[](#readme-top)
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
5
55
|
## [Version 2.0.0-next.67](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.66...v2.0.0-next.67)
|
|
6
56
|
|
|
7
57
|
<sup>Released on **2025-11-16**</sup>
|
package/changelog/v1.json
CHANGED
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"children": {
|
|
4
|
+
"improvements": [
|
|
5
|
+
"Remove language_model_settings and remove isDeprecatedEdition."
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"date": "2025-11-17",
|
|
9
|
+
"version": "2.0.0-next.69"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"children": {
|
|
13
|
+
"fixes": [
|
|
14
|
+
"The tool to fail execution on ollama when a message contains b…."
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"date": "2025-11-16",
|
|
18
|
+
"version": "2.0.0-next.68"
|
|
19
|
+
},
|
|
2
20
|
{
|
|
3
21
|
"children": {
|
|
4
22
|
"improvements": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.69",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent 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",
|
|
@@ -122,9 +122,6 @@
|
|
|
122
122
|
"eslint --fix"
|
|
123
123
|
]
|
|
124
124
|
},
|
|
125
|
-
"overrides": {
|
|
126
|
-
"eta": "4.0.1"
|
|
127
|
-
},
|
|
128
125
|
"dependencies": {
|
|
129
126
|
"@ant-design/icons": "^5.6.1",
|
|
130
127
|
"@ant-design/pro-components": "^2.8.10",
|
|
@@ -398,9 +395,6 @@
|
|
|
398
395
|
"pnpm": {
|
|
399
396
|
"onlyBuiltDependencies": [
|
|
400
397
|
"@vercel/speed-insights"
|
|
401
|
-
]
|
|
402
|
-
"overrides": {
|
|
403
|
-
"eta": "4.0.1"
|
|
404
|
-
}
|
|
398
|
+
]
|
|
405
399
|
}
|
|
406
400
|
}
|
|
@@ -4,13 +4,8 @@ import { BRANDING_NAME, ORG_NAME } from './branding';
|
|
|
4
4
|
|
|
5
5
|
export const CURRENT_VERSION = pkg.version;
|
|
6
6
|
|
|
7
|
-
export const isServerMode = true;
|
|
8
|
-
export const isUsePgliteDB = false;
|
|
9
|
-
|
|
10
7
|
export const isDesktop = process.env.NEXT_PUBLIC_IS_DESKTOP_APP === '1';
|
|
11
8
|
|
|
12
|
-
export const isDeprecatedEdition = false;
|
|
13
|
-
|
|
14
9
|
// @ts-ignore
|
|
15
10
|
export const isCustomBranding = BRANDING_NAME !== 'LobeHub';
|
|
16
11
|
// @ts-ignore
|
|
@@ -287,6 +287,44 @@ describe('ChunkModel', () => {
|
|
|
287
287
|
expect(result[1].index).toBe(1);
|
|
288
288
|
expect(result[2].index).toBe(2);
|
|
289
289
|
});
|
|
290
|
+
|
|
291
|
+
it('should handle chunks with null metadata and return undefined pageNumber', async () => {
|
|
292
|
+
const fileId = '1';
|
|
293
|
+
const [chunk] = await serverDB
|
|
294
|
+
.insert(chunks)
|
|
295
|
+
.values([{ text: 'Chunk with null metadata', userId, index: 0, metadata: null }])
|
|
296
|
+
.returning();
|
|
297
|
+
|
|
298
|
+
await serverDB.insert(fileChunks).values([{ fileId, chunkId: chunk.id, userId }]);
|
|
299
|
+
|
|
300
|
+
const result = await chunkModel.findByFileId(fileId, 0);
|
|
301
|
+
|
|
302
|
+
expect(result).toHaveLength(1);
|
|
303
|
+
expect(result[0].metadata).toBeNull();
|
|
304
|
+
expect(result[0].pageNumber).toBeUndefined();
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('should handle chunks with metadata containing pageNumber', async () => {
|
|
308
|
+
const fileId = '1';
|
|
309
|
+
const [chunk] = await serverDB
|
|
310
|
+
.insert(chunks)
|
|
311
|
+
.values([
|
|
312
|
+
{
|
|
313
|
+
text: 'Chunk with pageNumber',
|
|
314
|
+
userId,
|
|
315
|
+
index: 0,
|
|
316
|
+
metadata: { pageNumber: 5 } as any,
|
|
317
|
+
},
|
|
318
|
+
])
|
|
319
|
+
.returning();
|
|
320
|
+
|
|
321
|
+
await serverDB.insert(fileChunks).values([{ fileId, chunkId: chunk.id, userId }]);
|
|
322
|
+
|
|
323
|
+
const result = await chunkModel.findByFileId(fileId, 0);
|
|
324
|
+
|
|
325
|
+
expect(result).toHaveLength(1);
|
|
326
|
+
expect(result[0].pageNumber).toBe(5);
|
|
327
|
+
});
|
|
290
328
|
});
|
|
291
329
|
|
|
292
330
|
describe('getChunksTextByFileId', () => {
|
|
@@ -235,6 +235,73 @@ describe('OllamaStream', () => {
|
|
|
235
235
|
expect(onToolCall).toHaveBeenCalledTimes(1);
|
|
236
236
|
expect(onCompletionMock).toHaveBeenCalledTimes(1);
|
|
237
237
|
});
|
|
238
|
+
|
|
239
|
+
it('tools use with a done', async () => {
|
|
240
|
+
vi.spyOn(uuidModule, 'nanoid').mockReturnValueOnce('1').mockReturnValueOnce('abcd1234');
|
|
241
|
+
|
|
242
|
+
const mockOllamaStream = new ReadableStream<ChatResponse>({
|
|
243
|
+
start(controller) {
|
|
244
|
+
controller.enqueue({
|
|
245
|
+
model: 'qwen2.5',
|
|
246
|
+
created_at: new Date('2024-12-01T03:34:55.166692Z'),
|
|
247
|
+
message: {
|
|
248
|
+
role: 'assistant',
|
|
249
|
+
content: '',
|
|
250
|
+
tool_calls: [
|
|
251
|
+
{
|
|
252
|
+
function: {
|
|
253
|
+
name: 'realtime-weather____fetchCurrentWeather',
|
|
254
|
+
arguments: { city: '杭州' },
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
done_reason: 'stop',
|
|
260
|
+
done: true,
|
|
261
|
+
total_duration: 1122415333,
|
|
262
|
+
load_duration: 26178333,
|
|
263
|
+
prompt_eval_count: 221,
|
|
264
|
+
prompt_eval_duration: 507000000,
|
|
265
|
+
eval_count: 26,
|
|
266
|
+
eval_duration: 583000000,
|
|
267
|
+
} as unknown as ChatResponse);
|
|
268
|
+
|
|
269
|
+
controller.close();
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
const onStartMock = vi.fn();
|
|
273
|
+
const onTextMock = vi.fn();
|
|
274
|
+
const onToolCall = vi.fn();
|
|
275
|
+
const onCompletionMock = vi.fn();
|
|
276
|
+
|
|
277
|
+
const protocolStream = OllamaStream(mockOllamaStream, {
|
|
278
|
+
onStart: onStartMock,
|
|
279
|
+
onText: onTextMock,
|
|
280
|
+
onCompletion: onCompletionMock,
|
|
281
|
+
onToolsCalling: onToolCall,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const decoder = new TextDecoder();
|
|
285
|
+
const chunks = [];
|
|
286
|
+
|
|
287
|
+
// @ts-ignore
|
|
288
|
+
for await (const chunk of protocolStream) {
|
|
289
|
+
chunks.push(decoder.decode(chunk, { stream: true }));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
expect(chunks).toEqual(
|
|
293
|
+
[
|
|
294
|
+
'id: chat_1',
|
|
295
|
+
'event: tool_calls',
|
|
296
|
+
`data: [{"function":{"arguments":"{\\"city\\":\\"杭州\\"}","name":"realtime-weather____fetchCurrentWeather"},"id":"realtime-weather____fetchCurrentWeather_0_abcd1234","index":0,"type":"function"}]\n`,
|
|
297
|
+
].map((i) => `${i}\n`),
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
expect(onTextMock).toHaveBeenCalledTimes(0);
|
|
301
|
+
expect(onStartMock).toHaveBeenCalledTimes(1);
|
|
302
|
+
expect(onToolCall).toHaveBeenCalledTimes(1);
|
|
303
|
+
expect(onCompletionMock).toHaveBeenCalledTimes(1);
|
|
304
|
+
});
|
|
238
305
|
});
|
|
239
306
|
|
|
240
307
|
it('should handle empty stream', async () => {
|
|
@@ -11,11 +11,6 @@ import {
|
|
|
11
11
|
} from './protocol';
|
|
12
12
|
|
|
13
13
|
const transformOllamaStream = (chunk: ChatResponse, stack: StreamContext): StreamProtocolChunk => {
|
|
14
|
-
// maybe need another structure to add support for multiple choices
|
|
15
|
-
if (chunk.done && !chunk.message.content) {
|
|
16
|
-
return { data: 'finished', id: stack.id, type: 'stop' };
|
|
17
|
-
}
|
|
18
|
-
|
|
19
14
|
if (chunk.message.thinking) {
|
|
20
15
|
return { data: chunk.message.thinking, id: stack.id, type: 'reasoning' };
|
|
21
16
|
}
|
|
@@ -36,6 +31,11 @@ const transformOllamaStream = (chunk: ChatResponse, stack: StreamContext): Strea
|
|
|
36
31
|
};
|
|
37
32
|
}
|
|
38
33
|
|
|
34
|
+
// maybe need another structure to add support for multiple choices
|
|
35
|
+
if (chunk.done && !chunk.message.content) {
|
|
36
|
+
return { data: 'finished', id: stack.id, type: 'stop' };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
39
|
// 判断是否有 <think> 或 </think> 标签,更新 thinkingInContent 状态
|
|
40
40
|
if (chunk.message.content.includes('<think>')) {
|
|
41
41
|
stack.thinkingInContent = true;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
|
|
3
|
-
import { isServerMode } from '@/const/version';
|
|
4
3
|
import { serverDB } from '@/database/server';
|
|
5
4
|
import { authEnv } from '@/envs/auth';
|
|
6
5
|
import { pino } from '@/libs/logger';
|
|
@@ -8,7 +7,7 @@ import { UserService } from '@/server/services/user';
|
|
|
8
7
|
|
|
9
8
|
import { validateRequest } from './validateRequest';
|
|
10
9
|
|
|
11
|
-
if (authEnv.NEXT_PUBLIC_ENABLE_CLERK_AUTH &&
|
|
10
|
+
if (authEnv.NEXT_PUBLIC_ENABLE_CLERK_AUTH && !authEnv.CLERK_WEBHOOK_SECRET) {
|
|
12
11
|
throw new Error('`CLERK_WEBHOOK_SECRET` environment variable is missing');
|
|
13
12
|
}
|
|
14
13
|
|
|
@@ -23,10 +23,6 @@ vi.mock('react-i18next', () => ({
|
|
|
23
23
|
})),
|
|
24
24
|
}));
|
|
25
25
|
|
|
26
|
-
vi.mock('../../settings/features/useCategory', () => ({
|
|
27
|
-
useCategory: vi.fn(() => [{ key: 'extraSetting', label: 'Extra Setting' }]),
|
|
28
|
-
}));
|
|
29
|
-
|
|
30
26
|
// 定义一个变量来存储 enableAuth 的值
|
|
31
27
|
let enableAuth = true;
|
|
32
28
|
let enableClerk = true;
|
|
@@ -68,7 +64,6 @@ describe('useCategory', () => {
|
|
|
68
64
|
const items = result.current;
|
|
69
65
|
expect(items.some((item) => item.key === 'profile')).toBe(true);
|
|
70
66
|
expect(items.some((item) => item.key === 'setting')).toBe(true);
|
|
71
|
-
expect(items.some((item) => item.key === 'data')).toBe(true);
|
|
72
67
|
expect(items.some((item) => item.key === 'docs')).toBe(true);
|
|
73
68
|
expect(items.some((item) => item.key === 'feedback')).toBe(true);
|
|
74
69
|
expect(items.some((item) => item.key === 'changelog')).toBe(true);
|
|
@@ -93,19 +88,4 @@ describe('useCategory', () => {
|
|
|
93
88
|
expect(items.some((item) => item.key === 'changelog')).toBe(true);
|
|
94
89
|
});
|
|
95
90
|
});
|
|
96
|
-
|
|
97
|
-
it('should handle settings for non-authenticated users', () => {
|
|
98
|
-
act(() => {
|
|
99
|
-
useUserStore.setState({ isSignedIn: false });
|
|
100
|
-
});
|
|
101
|
-
enableClerk = false;
|
|
102
|
-
enableAuth = false;
|
|
103
|
-
|
|
104
|
-
const { result } = renderHook(() => useCategory(), { wrapper });
|
|
105
|
-
|
|
106
|
-
act(() => {
|
|
107
|
-
const items = result.current;
|
|
108
|
-
expect(items.some((item) => item.key === 'extraSetting')).toBe(true);
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
91
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { DOCUMENTS, FEEDBACK, LOBE_CHAT_CLOUD, OFFICIAL_URL, UTM_SOURCE } from '@lobechat/const';
|
|
1
2
|
import {
|
|
2
3
|
Book,
|
|
3
4
|
CircleUserRound,
|
|
4
5
|
Cloudy,
|
|
5
|
-
Database,
|
|
6
6
|
Download,
|
|
7
7
|
Feather,
|
|
8
8
|
FileClockIcon,
|
|
@@ -12,26 +12,17 @@ import { useRouter } from 'next/navigation';
|
|
|
12
12
|
import { useTranslation } from 'react-i18next';
|
|
13
13
|
|
|
14
14
|
import { CellProps } from '@/components/Cell';
|
|
15
|
-
import { enableAuth } from '@/const/auth';
|
|
16
|
-
import { LOBE_CHAT_CLOUD } from '@/const/branding';
|
|
17
|
-
import { DOCUMENTS, FEEDBACK, OFFICIAL_URL, UTM_SOURCE } from '@/const/url';
|
|
18
|
-
import { isServerMode } from '@/const/version';
|
|
19
15
|
import { usePWAInstall } from '@/hooks/usePWAInstall';
|
|
20
16
|
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
|
21
17
|
import { useUserStore } from '@/store/user';
|
|
22
18
|
import { authSelectors } from '@/store/user/selectors';
|
|
23
19
|
|
|
24
|
-
import { useCategory as useSettingsCategory } from '../../settings/features/useCategory';
|
|
25
|
-
|
|
26
20
|
export const useCategory = () => {
|
|
27
21
|
const router = useRouter();
|
|
28
22
|
const { canInstall, install } = usePWAInstall();
|
|
29
23
|
const { t } = useTranslation(['common', 'setting', 'auth']);
|
|
30
24
|
const { showCloudPromotion, hideDocs } = useServerConfigStore(featureFlagsSelectors);
|
|
31
|
-
const [
|
|
32
|
-
authSelectors.isLogin(s),
|
|
33
|
-
authSelectors.isLoginWithAuth(s),
|
|
34
|
-
]);
|
|
25
|
+
const [isLoginWithAuth] = useUserStore((s) => [authSelectors.isLoginWithAuth(s)]);
|
|
35
26
|
|
|
36
27
|
const profile: CellProps[] = [
|
|
37
28
|
{
|
|
@@ -66,29 +57,10 @@ export const useCategory = () => {
|
|
|
66
57
|
},
|
|
67
58
|
];
|
|
68
59
|
|
|
69
|
-
const settingsWithoutAuth = [
|
|
70
|
-
...useSettingsCategory(),
|
|
71
|
-
{
|
|
72
|
-
type: 'divider',
|
|
73
|
-
},
|
|
74
|
-
];
|
|
75
|
-
|
|
76
60
|
/* ↓ cloud slot ↓ */
|
|
77
61
|
|
|
78
62
|
/* ↑ cloud slot ↑ */
|
|
79
63
|
|
|
80
|
-
const data: CellProps[] = [
|
|
81
|
-
{
|
|
82
|
-
icon: Database,
|
|
83
|
-
key: 'data',
|
|
84
|
-
label: t('userPanel.data'),
|
|
85
|
-
onClick: () => router.push('/me/data'),
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
type: 'divider',
|
|
89
|
-
},
|
|
90
|
-
];
|
|
91
|
-
|
|
92
64
|
const helps: CellProps[] = [
|
|
93
65
|
showCloudPromotion && {
|
|
94
66
|
icon: Cloudy,
|
|
@@ -120,13 +92,12 @@ export const useCategory = () => {
|
|
|
120
92
|
{
|
|
121
93
|
type: 'divider',
|
|
122
94
|
},
|
|
123
|
-
...(
|
|
124
|
-
...(
|
|
95
|
+
...(isLoginWithAuth ? profile : []),
|
|
96
|
+
...(isLoginWithAuth ? settings : []),
|
|
125
97
|
/* ↓ cloud slot ↓ */
|
|
126
98
|
|
|
127
99
|
/* ↑ cloud slot ↑ */
|
|
128
100
|
...(canInstall ? pwa : []),
|
|
129
|
-
...(isLogin && !isServerMode ? data : []),
|
|
130
101
|
...(!hideDocs ? helps : []),
|
|
131
102
|
].filter(Boolean) as CellProps[];
|
|
132
103
|
|
|
@@ -6,8 +6,6 @@ import { memo } from 'react';
|
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
|
|
8
8
|
import Cell, { CellProps } from '@/components/Cell';
|
|
9
|
-
import { enableAuth } from '@/const/auth';
|
|
10
|
-
import { isDeprecatedEdition } from '@/const/version';
|
|
11
9
|
import { ProfileTabs } from '@/store/global/initialState';
|
|
12
10
|
import { useUserStore } from '@/store/user';
|
|
13
11
|
import { authSelectors } from '@/store/user/selectors';
|
|
@@ -27,33 +25,30 @@ const Category = memo(() => {
|
|
|
27
25
|
label: t('tab.profile'),
|
|
28
26
|
onClick: () => router.push('/profile'),
|
|
29
27
|
},
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
!isDeprecatedEdition && {
|
|
28
|
+
isLoginWithClerk && {
|
|
29
|
+
icon: ShieldCheck,
|
|
30
|
+
key: ProfileTabs.Security,
|
|
31
|
+
label: t('tab.security'),
|
|
32
|
+
onClick: () => router.push('/profile/security'),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
38
35
|
icon: ChartColumnBigIcon,
|
|
39
36
|
key: ProfileTabs.Stats,
|
|
40
37
|
label: t('tab.stats'),
|
|
41
38
|
onClick: () => router.push('/profile/stats'),
|
|
42
39
|
},
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
signOut();
|
|
54
|
-
router.push('/login');
|
|
55
|
-
},
|
|
40
|
+
isLogin && {
|
|
41
|
+
type: 'divider',
|
|
42
|
+
},
|
|
43
|
+
isLogin && {
|
|
44
|
+
icon: LogOut,
|
|
45
|
+
key: 'logout',
|
|
46
|
+
label: t('signout', { ns: 'auth' }),
|
|
47
|
+
onClick: () => {
|
|
48
|
+
signOut();
|
|
49
|
+
router.push('/login');
|
|
56
50
|
},
|
|
51
|
+
},
|
|
57
52
|
].filter(Boolean) as CellProps[];
|
|
58
53
|
|
|
59
54
|
return items?.map(({ key, ...item }, index) => <Cell key={key || index} {...item} />);
|
|
@@ -3,14 +3,11 @@ import { useRouter } from 'next/navigation';
|
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
|
|
5
5
|
import { CellProps } from '@/components/Cell';
|
|
6
|
-
import { isDeprecatedEdition } from '@/const/version';
|
|
7
6
|
import { SettingsTabs } from '@/store/global/initialState';
|
|
8
|
-
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
|
9
7
|
|
|
10
8
|
export const useCategory = () => {
|
|
11
9
|
const router = useRouter();
|
|
12
10
|
const { t } = useTranslation('setting');
|
|
13
|
-
const { showLLM } = useServerConfigStore(featureFlagsSelectors);
|
|
14
11
|
|
|
15
12
|
const items: CellProps[] = [
|
|
16
13
|
{
|
|
@@ -23,18 +20,11 @@ export const useCategory = () => {
|
|
|
23
20
|
key: SettingsTabs.SystemAgent,
|
|
24
21
|
label: t('tab.system-agent'),
|
|
25
22
|
},
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
label: t('tab.llm'),
|
|
32
|
-
}
|
|
33
|
-
: {
|
|
34
|
-
icon: Brain,
|
|
35
|
-
key: SettingsTabs.Provider,
|
|
36
|
-
label: t('tab.provider'),
|
|
37
|
-
}),
|
|
23
|
+
{
|
|
24
|
+
icon: Brain,
|
|
25
|
+
key: SettingsTabs.Provider,
|
|
26
|
+
label: t('tab.provider'),
|
|
27
|
+
},
|
|
38
28
|
{ icon: Mic2, key: SettingsTabs.TTS, label: t('tab.tts') },
|
|
39
29
|
{
|
|
40
30
|
icon: Bot,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { isDesktop } from '@lobechat/const';
|
|
3
4
|
import { Button, Icon } from '@lobehub/ui';
|
|
4
5
|
import { Dropdown } from 'antd';
|
|
5
6
|
import { createStyles } from 'antd-style';
|
|
@@ -9,8 +10,6 @@ import { useRouter } from 'nextjs-toploader/app';
|
|
|
9
10
|
import { memo } from 'react';
|
|
10
11
|
import { useTranslation } from 'react-i18next';
|
|
11
12
|
|
|
12
|
-
import { isDeprecatedEdition, isDesktop } from '@/const/version';
|
|
13
|
-
|
|
14
13
|
import { useDetailContext } from '../../DetailProvider';
|
|
15
14
|
|
|
16
15
|
const useStyles = createStyles(({ css }) => ({
|
|
@@ -27,10 +26,8 @@ const ProviderConfig = memo(() => {
|
|
|
27
26
|
const { url, modelsUrl, identifier } = useDetailContext();
|
|
28
27
|
const router = useRouter();
|
|
29
28
|
const openSettings = async () => {
|
|
30
|
-
const searchParams =
|
|
31
|
-
|
|
32
|
-
: { active: 'provider', provider: identifier };
|
|
33
|
-
const tab = isDeprecatedEdition ? 'llm' : 'provider';
|
|
29
|
+
const searchParams = { active: 'provider', provider: identifier };
|
|
30
|
+
const tab = 'provider';
|
|
34
31
|
|
|
35
32
|
if (isDesktop) {
|
|
36
33
|
const { dispatch } = await import('@lobechat/electron-client-ipc');
|
|
@@ -41,11 +38,7 @@ const ProviderConfig = memo(() => {
|
|
|
41
38
|
return;
|
|
42
39
|
}
|
|
43
40
|
|
|
44
|
-
router.push(
|
|
45
|
-
isDeprecatedEdition
|
|
46
|
-
? '/settings?active=llm'
|
|
47
|
-
: `/settings?active=provider&provider=${identifier}`,
|
|
48
|
-
);
|
|
41
|
+
router.push(`/settings?active=provider&provider=${identifier}`);
|
|
49
42
|
};
|
|
50
43
|
|
|
51
44
|
const icon = <Icon icon={SquareArrowOutUpRight} size={16} />;
|
package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/ModelSelect/index.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EnabledProviderWithModels } from '@lobechat/types';
|
|
1
2
|
import { ActionIcon, Icon, Select, type SelectProps } from '@lobehub/ui';
|
|
2
3
|
import { createStyles, useTheme } from 'antd-style';
|
|
3
4
|
import { LucideArrowRight, LucideBolt } from 'lucide-react';
|
|
@@ -8,13 +9,10 @@ import { useTranslation } from 'react-i18next';
|
|
|
8
9
|
import { Flexbox } from 'react-layout-kit';
|
|
9
10
|
|
|
10
11
|
import { ProviderItemRender } from '@/components/ModelSelect';
|
|
11
|
-
import { isDeprecatedEdition } from '@/const/version';
|
|
12
12
|
import { useAiInfraStore } from '@/store/aiInfra';
|
|
13
13
|
import { aiProviderSelectors } from '@/store/aiInfra/slices/aiProvider/selectors';
|
|
14
14
|
import { useImageStore } from '@/store/image';
|
|
15
|
-
import { imageGenerationConfigSelectors } from '@/store/image/
|
|
16
|
-
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
|
17
|
-
import { EnabledProviderWithModels } from '@/types/aiProvider';
|
|
15
|
+
import { imageGenerationConfigSelectors } from '@/store/image/selectors';
|
|
18
16
|
|
|
19
17
|
import ImageModelItem from './ImageModelItem';
|
|
20
18
|
|
|
@@ -36,7 +34,6 @@ const ModelSelect = memo(() => {
|
|
|
36
34
|
const { styles } = useStyles();
|
|
37
35
|
const { t } = useTranslation('components');
|
|
38
36
|
const theme = useTheme();
|
|
39
|
-
const { showLLM } = useServerConfigStore(featureFlagsSelectors);
|
|
40
37
|
const router = useRouter();
|
|
41
38
|
|
|
42
39
|
const [currentModel, currentProvider] = useImageStore((s) => [
|
|
@@ -67,11 +64,7 @@ const ModelSelect = memo(() => {
|
|
|
67
64
|
</Flexbox>
|
|
68
65
|
),
|
|
69
66
|
onClick: () => {
|
|
70
|
-
router.push(
|
|
71
|
-
isDeprecatedEdition
|
|
72
|
-
? '/settings?active=llm'
|
|
73
|
-
: `/settings?active=provider&provider=${provider.id}`,
|
|
74
|
-
);
|
|
67
|
+
router.push(`/settings?active=provider&provider=${provider.id}`);
|
|
75
68
|
},
|
|
76
69
|
value: `${provider.id}/empty`,
|
|
77
70
|
},
|
|
@@ -93,7 +86,7 @@ const ModelSelect = memo(() => {
|
|
|
93
86
|
</Flexbox>
|
|
94
87
|
),
|
|
95
88
|
onClick: () => {
|
|
96
|
-
router.push(
|
|
89
|
+
router.push('/settings?active=provider');
|
|
97
90
|
},
|
|
98
91
|
value: 'no-provider',
|
|
99
92
|
},
|
|
@@ -114,26 +107,18 @@ const ModelSelect = memo(() => {
|
|
|
114
107
|
provider={provider.id}
|
|
115
108
|
source={provider.source}
|
|
116
109
|
/>
|
|
117
|
-
{
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
>
|
|
125
|
-
<ActionIcon
|
|
126
|
-
icon={LucideBolt}
|
|
127
|
-
size={'small'}
|
|
128
|
-
title={t('ModelSwitchPanel.goToSettings')}
|
|
129
|
-
/>
|
|
130
|
-
</Link>
|
|
131
|
-
)}
|
|
110
|
+
<Link href={`/settings?active=provider&provider=${provider.id}`}>
|
|
111
|
+
<ActionIcon
|
|
112
|
+
icon={LucideBolt}
|
|
113
|
+
size={'small'}
|
|
114
|
+
title={t('ModelSwitchPanel.goToSettings')}
|
|
115
|
+
/>
|
|
116
|
+
</Link>
|
|
132
117
|
</Flexbox>
|
|
133
118
|
),
|
|
134
119
|
options: getImageModels(provider),
|
|
135
120
|
}));
|
|
136
|
-
}, [enabledImageModelList,
|
|
121
|
+
}, [enabledImageModelList, t, theme.colorTextTertiary, router]);
|
|
137
122
|
|
|
138
123
|
const labelRender: SelectProps['labelRender'] = (props) => {
|
|
139
124
|
const modelInfo = enabledImageModelList
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import ServerLayout from '@/components/server/ServerLayout';
|
|
2
|
-
import { isServerMode } from '@/const/version';
|
|
3
2
|
|
|
4
|
-
import NotSupportClient from './NotSupportClient';
|
|
5
3
|
import Desktop from './_layout/Desktop';
|
|
6
4
|
import Mobile from './_layout/Mobile';
|
|
7
5
|
import { LayoutProps } from './_layout/type';
|
|
@@ -11,8 +9,6 @@ const AiImageLayout = ServerLayout({ Desktop, Mobile });
|
|
|
11
9
|
AiImageLayout.displayName = 'AiImageLayout';
|
|
12
10
|
|
|
13
11
|
const Layout = (props: LayoutProps) => {
|
|
14
|
-
if (!isServerMode) return <NotSupportClient />;
|
|
15
|
-
|
|
16
12
|
return <AiImageLayout {...props} />;
|
|
17
13
|
};
|
|
18
14
|
|