@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.
Files changed (61) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/package.json +2 -8
  4. package/packages/const/src/version.ts +0 -5
  5. package/packages/database/src/models/__tests__/chunk.test.ts +38 -0
  6. package/packages/model-runtime/src/core/streams/ollama.test.ts +67 -0
  7. package/packages/model-runtime/src/core/streams/ollama.ts +5 -5
  8. package/src/app/(backend)/api/webhooks/clerk/route.ts +1 -2
  9. package/src/app/[variants]/(main)/(mobile)/me/(home)/__tests__/useCategory.test.tsx +0 -20
  10. package/src/app/[variants]/(main)/(mobile)/me/(home)/features/useCategory.tsx +4 -33
  11. package/src/app/[variants]/(main)/(mobile)/me/profile/features/Category.tsx +18 -23
  12. package/src/app/[variants]/(main)/(mobile)/me/settings/features/useCategory.tsx +5 -15
  13. package/src/app/[variants]/(main)/discover/(detail)/provider/[...slugs]/features/Sidebar/ActionButton/ProviderConfig.tsx +4 -11
  14. package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/components/ModelSelect/index.tsx +12 -27
  15. package/src/app/[variants]/(main)/image/layout.tsx +0 -4
  16. package/src/app/[variants]/(main)/profile/hooks/useCategory.tsx +10 -13
  17. package/src/app/[variants]/(main)/profile/stats/features/ShareButton/Preview.tsx +2 -14
  18. package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +2 -3
  19. package/src/app/[variants]/(main)/settings/_layout/SettingsContent.tsx +1 -12
  20. package/src/app/[variants]/(main)/settings/_layout/type.ts +0 -1
  21. package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +8 -16
  22. package/src/app/[variants]/(main)/settings/page.tsx +3 -7
  23. package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/index.tsx +2 -4
  24. package/src/app/[variants]/(main)/settings/storage/index.tsx +1 -9
  25. package/src/app/[variants]/(main)/settings/system-agent/index.tsx +1 -2
  26. package/src/components/InvalidAPIKey/APIKeyForm/useApiKey.ts +0 -12
  27. package/src/config/featureFlags/schema.test.ts +1 -3
  28. package/src/config/featureFlags/schema.ts +0 -3
  29. package/src/features/ChatInput/ActionBar/Knowledge/index.tsx +2 -3
  30. package/src/features/ChatInput/ActionBar/Search/index.tsx +5 -7
  31. package/src/features/ChatInput/ActionBar/Upload/index.tsx +1 -3
  32. package/src/features/Conversation/Messages/Assistant/index.tsx +1 -1
  33. package/src/features/Conversation/components/ShareMessageModal/index.tsx +3 -8
  34. package/src/features/DevPanel/PostgresViewer/usePgTable.ts +3 -11
  35. package/src/features/ModelSwitchPanel/index.tsx +9 -24
  36. package/src/features/ShareModal/index.tsx +7 -13
  37. package/src/features/User/UserPanel/PanelContent.tsx +6 -8
  38. package/src/hooks/useCheckPluginsIsInstalled.ts +1 -4
  39. package/src/hooks/useFetchGroups.ts +1 -4
  40. package/src/hooks/useFetchInstalledPlugins.ts +1 -4
  41. package/src/hooks/useFetchMessages.ts +1 -4
  42. package/src/hooks/useFetchSessions.ts +1 -4
  43. package/src/hooks/useFetchThreads.ts +1 -5
  44. package/src/hooks/useFetchTopics.ts +1 -4
  45. package/src/hooks/useInterceptingRoutes.test.ts +0 -19
  46. package/src/hooks/useInterceptingRoutes.ts +1 -7
  47. package/src/layout/GlobalProvider/StoreInitialization.tsx +2 -4
  48. package/src/services/_auth.ts +2 -11
  49. package/src/services/_header.ts +2 -10
  50. package/src/services/chat/chat.test.ts +53 -10
  51. package/src/services/chat/clientModelRuntime.test.ts +108 -172
  52. package/src/services/chat/contextEngineering.ts +2 -2
  53. package/src/services/config.ts +2 -2
  54. package/src/store/aiInfra/slices/aiProvider/action.ts +3 -4
  55. package/src/store/chat/slices/thread/action.ts +2 -2
  56. package/src/store/global/selectors/systemStatus.test.ts +0 -98
  57. package/src/store/global/selectors/systemStatus.ts +0 -30
  58. package/src/store/serverConfig/selectors.test.ts +2 -2
  59. package/src/store/serverConfig/store.test.ts +0 -1
  60. package/src/app/[variants]/(main)/settings/storage/IndexedDBStorage.tsx +0 -55
  61. package/src/features/ChatInput/ActionBar/Upload/ClientMode.tsx +0 -62
@@ -1,10 +1,7 @@
1
- import { useGlobalStore } from '@/store/global';
2
- import { systemStatusSelectors } from '@/store/global/selectors';
3
1
  import { useToolStore } from '@/store/tool';
4
2
 
5
3
  export const useCheckPluginsIsInstalled = (plugins: string[]) => {
6
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
7
4
  const checkPluginsIsInstalled = useToolStore((s) => s.useCheckPluginsIsInstalled);
8
5
 
9
- checkPluginsIsInstalled(isDBInited, plugins);
6
+ checkPluginsIsInstalled(true, plugins);
10
7
  };
@@ -1,13 +1,10 @@
1
1
  import { useChatGroupStore } from '@/store/chatGroup';
2
- import { useGlobalStore } from '@/store/global';
3
- import { systemStatusSelectors } from '@/store/global/selectors';
4
2
  import { useUserStore } from '@/store/user';
5
3
  import { authSelectors } from '@/store/user/slices/auth/selectors';
6
4
 
7
5
  export const useFetchGroups = () => {
8
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
9
6
  const isLogin = useUserStore(authSelectors.isLogin);
10
7
  const useFetchGroups = useChatGroupStore((s) => s.useFetchGroups);
11
8
 
12
- useFetchGroups(isDBInited ?? false, isLogin ?? false);
9
+ useFetchGroups(true, isLogin ?? false);
13
10
  };
@@ -1,10 +1,7 @@
1
- import { useGlobalStore } from '@/store/global';
2
- import { systemStatusSelectors } from '@/store/global/selectors';
3
1
  import { useToolStore } from '@/store/tool';
4
2
 
5
3
  export const useFetchInstalledPlugins = () => {
6
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
7
4
  const [useFetchInstalledPlugins] = useToolStore((s) => [s.useFetchInstalledPlugins]);
8
5
 
9
- return useFetchInstalledPlugins(isDBInited);
6
+ return useFetchInstalledPlugins(true);
10
7
  };
@@ -1,13 +1,10 @@
1
1
  import { useEffect } from 'react';
2
2
 
3
3
  import { useChatStore } from '@/store/chat';
4
- import { useGlobalStore } from '@/store/global';
5
- import { systemStatusSelectors } from '@/store/global/selectors';
6
4
  import { useSessionStore } from '@/store/session';
7
5
  import { sessionSelectors } from '@/store/session/selectors';
8
6
 
9
7
  export const useFetchMessages = () => {
10
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
11
8
  const sessionId = useSessionStore((s) => s.activeId);
12
9
  const [activeTopicId, useFetchMessages, internal_updateActiveSessionType] = useChatStore((s) => [
13
10
  s.activeTopicId,
@@ -29,5 +26,5 @@ export const useFetchMessages = () => {
29
26
  }
30
27
  }, [currentSession?.id, currentSession?.type, internal_updateActiveSessionType]);
31
28
 
32
- useFetchMessages(isDBInited, sessionId, activeTopicId, isGroupSession ? 'group' : 'session');
29
+ useFetchMessages(true, sessionId, activeTopicId, isGroupSession ? 'group' : 'session');
33
30
  };
@@ -1,13 +1,10 @@
1
- import { useGlobalStore } from '@/store/global';
2
- import { systemStatusSelectors } from '@/store/global/selectors';
3
1
  import { useSessionStore } from '@/store/session';
4
2
  import { useUserStore } from '@/store/user';
5
3
  import { authSelectors } from '@/store/user/slices/auth/selectors';
6
4
 
7
5
  export const useFetchSessions = () => {
8
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
9
6
  const isLogin = useUserStore(authSelectors.isLogin);
10
7
  const useFetchSessions = useSessionStore((s) => s.useFetchSessions);
11
8
 
12
- useFetchSessions(isDBInited, isLogin);
9
+ useFetchSessions(true, isLogin);
13
10
  };
@@ -1,11 +1,7 @@
1
1
  import { useChatStore } from '@/store/chat';
2
- import { useGlobalStore } from '@/store/global';
3
- import { systemStatusSelectors } from '@/store/global/selectors';
4
2
 
5
3
  export const useFetchThreads = (activeTopicId?: string) => {
6
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
7
-
8
4
  const [useFetchThreads] = useChatStore((s) => [s.useFetchThreads]);
9
5
 
10
- useFetchThreads(isDBInited, activeTopicId);
6
+ useFetchThreads(true, activeTopicId);
11
7
  };
@@ -1,6 +1,4 @@
1
1
  import { useChatStore } from '@/store/chat';
2
- import { useGlobalStore } from '@/store/global';
3
- import { systemStatusSelectors } from '@/store/global/selectors';
4
2
  import { useSessionStore } from '@/store/session';
5
3
 
6
4
  /**
@@ -9,7 +7,6 @@ import { useSessionStore } from '@/store/session';
9
7
  export const useFetchTopics = () => {
10
8
  const [sessionId] = useSessionStore((s) => [s.activeId]);
11
9
  const useFetchTopics = useChatStore((s) => s.useFetchTopics);
12
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
13
10
 
14
- useFetchTopics(isDBInited, sessionId);
11
+ useFetchTopics(true, sessionId);
15
12
  };
@@ -42,26 +42,7 @@ vi.mock('@/store/global', () => ({
42
42
  setState: vi.fn(),
43
43
  },
44
44
  }));
45
- let isDeprecatedEdition = false;
46
- vi.mock('@/const/version', async (importOriginal) => {
47
- const actual = await importOriginal<typeof import('@/const/version')>();
48
- return {
49
- ...actual,
50
- get isDeprecatedEdition() {
51
- return isDeprecatedEdition;
52
- },
53
- };
54
- });
55
-
56
45
  describe('useOpenChatSettings', () => {
57
- it('should handle inbox session id correctly', () => {
58
- isDeprecatedEdition = true;
59
- vi.mocked(useSessionStore).mockReturnValue(INBOX_SESSION_ID);
60
- const { result } = renderHook(() => useOpenChatSettings());
61
-
62
- expect(result.current()).toBe('/settings?active=agent'); // Assuming openSettings returns a function
63
- isDeprecatedEdition = false;
64
- });
65
46
 
66
47
  it('should handle mobile route for chat settings', () => {
67
48
  vi.mocked(useSessionStore).mockReturnValue('123');
@@ -1,11 +1,9 @@
1
1
  import { useMemo } from 'react';
2
2
 
3
- import { INBOX_SESSION_ID } from '@/const/session';
4
- import { isDeprecatedEdition } from '@/const/version';
5
3
  import { useIsMobile } from '@/hooks/useIsMobile';
6
4
  import { useQueryRoute } from '@/hooks/useQueryRoute';
7
5
  import { useAgentStore } from '@/store/agent';
8
- import { ChatSettingsTabs, SettingsTabs } from '@/store/global/initialState';
6
+ import { ChatSettingsTabs } from '@/store/global/initialState';
9
7
  import { useSessionStore } from '@/store/session';
10
8
 
11
9
  export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Meta) => {
@@ -15,10 +13,6 @@ export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Met
15
13
  const router = useQueryRoute();
16
14
 
17
15
  return useMemo(() => {
18
- if (isDeprecatedEdition && activeId === INBOX_SESSION_ID) {
19
- return () => router.push(`/settings?active=${SettingsTabs.Agent}`);
20
- }
21
-
22
16
  if (isMobile) return () => router.push('/chat/settings', { query: { session: activeId } });
23
17
 
24
18
  return () => {
@@ -1,16 +1,15 @@
1
1
  'use client';
2
2
 
3
+ import { enableNextAuth } from '@lobechat/const';
3
4
  import { useRouter } from 'next/navigation';
4
5
  import { memo } from 'react';
5
6
  import { useTranslation } from 'react-i18next';
6
7
  import { createStoreUpdater } from 'zustand-utils';
7
8
 
8
- import { enableNextAuth } from '@/const/auth';
9
9
  import { useIsMobile } from '@/hooks/useIsMobile';
10
10
  import { useAgentStore } from '@/store/agent';
11
11
  import { useAiInfraStore } from '@/store/aiInfra';
12
12
  import { useGlobalStore } from '@/store/global';
13
- import { systemStatusSelectors } from '@/store/global/selectors';
14
13
  import { useServerConfigStore } from '@/store/serverConfig';
15
14
  import { serverConfigSelectors } from '@/store/serverConfig/selectors';
16
15
  import { useUserStore } from '@/store/user';
@@ -54,8 +53,7 @@ const StoreInitialization = memo(() => {
54
53
  * IMPORTANT: Explicitly convert to boolean to avoid passing null/undefined downstream,
55
54
  * which would cause unnecessary API requests with invalid login state.
56
55
  */
57
- const isDBInited = useGlobalStore(systemStatusSelectors.isDBInited);
58
- const isLoginOnInit = isDBInited ? Boolean(enableNextAuth ? isSignedIn : isLogin) : false;
56
+ const isLoginOnInit = Boolean(enableNextAuth ? isSignedIn : isLogin);
59
57
 
60
58
  // init inbox agent and default agent config
61
59
  useInitAgentStore(isLoginOnInit, serverConfig.defaultAgent?.config);
@@ -1,4 +1,4 @@
1
- import { LOBE_CHAT_AUTH_HEADER, isDeprecatedEdition } from '@lobechat/const';
1
+ import { LOBE_CHAT_AUTH_HEADER } from '@lobechat/const';
2
2
  import {
3
3
  AWSBedrockKeyVault,
4
4
  AzureOpenAIKeyVault,
@@ -119,16 +119,7 @@ interface AuthParams {
119
119
  }
120
120
 
121
121
  export const createPayloadWithKeyVaults = (provider: string) => {
122
- let keyVaults = {};
123
-
124
- // TODO: remove this condition in V2.0
125
- if (isDeprecatedEdition) {
126
- keyVaults = keyVaultsConfigSelectors.getVaultByProvider(provider as any)(
127
- useUserStore.getState(),
128
- );
129
- } else {
130
- keyVaults = aiProviderSelectors.providerKeyVaults(provider)(useAiInfraStore.getState()) || {};
131
- }
122
+ let keyVaults = aiProviderSelectors.providerKeyVaults(provider)(useAiInfraStore.getState()) || {};
132
123
 
133
124
  const runtimeProvider = resolveRuntimeProvider(provider);
134
125
 
@@ -4,7 +4,6 @@ import {
4
4
  OPENAI_API_KEY_HEADER_KEY,
5
5
  OPENAI_END_POINT,
6
6
  } from '@/const/fetch';
7
- import { isDeprecatedEdition } from '@/const/version';
8
7
  import { aiProviderSelectors, useAiInfraStore } from '@/store/aiInfra';
9
8
  import { useUserStore } from '@/store/user';
10
9
  import { keyVaultsConfigSelectors } from '@/store/user/selectors';
@@ -17,16 +16,9 @@ import { keyVaultsConfigSelectors } from '@/store/user/selectors';
17
16
  export const createHeaderWithOpenAI = (header?: HeadersInit): HeadersInit => {
18
17
  const state = useUserStore.getState();
19
18
 
20
- let keyVaults: Record<string, any> = {};
19
+ const keyVaults: Record<string, any> =
20
+ aiProviderSelectors.providerKeyVaults('openai')(useAiInfraStore.getState()) || {};
21
21
 
22
- // TODO: remove this condition in V2.0
23
- if (isDeprecatedEdition) {
24
- keyVaults = keyVaultsConfigSelectors.getVaultByProvider('openai' as any)(
25
- useUserStore.getState(),
26
- );
27
- } else {
28
- keyVaults = aiProviderSelectors.providerKeyVaults('openai')(useAiInfraStore.getState()) || {};
29
- }
30
22
  // eslint-disable-next-line no-undef
31
23
  return {
32
24
  ...header,
@@ -278,15 +278,16 @@ describe('ChatService', () => {
278
278
 
279
279
  describe('should handle content correctly for vision models', () => {
280
280
  it('should include image content when with vision model', async () => {
281
+ // Mock helpers to return true for vision support (must be first)
282
+ const helpers = await import('./helper');
283
+ vi.spyOn(helpers, 'isCanUseVision').mockReturnValue(true);
284
+
281
285
  // Mock utility functions used in processImageList
282
286
  const { parseDataUri } = await import('@lobechat/utils/uriParser');
283
287
  const { isDesktopLocalStaticServerUrl } = await import('@lobechat/utils/url');
284
288
  vi.mocked(parseDataUri).mockReturnValue({ type: 'url', base64: null, mimeType: null });
285
289
  vi.mocked(isDesktopLocalStaticServerUrl).mockReturnValue(false); // Not a local URL
286
290
 
287
- // Mock aiModelSelectors to return true for vision support
288
- vi.spyOn(aiModelSelectors, 'isModelSupportVision').mockReturnValue(() => true);
289
-
290
291
  const messages = [
291
292
  {
292
293
  content: 'Hello',
@@ -315,13 +316,23 @@ describe('ChatService', () => {
315
316
  {
316
317
  content: [
317
318
  {
318
- text: 'Hello',
319
+ text: `Hello
320
+
321
+ <!-- SYSTEM CONTEXT (NOT PART OF USER QUERY) -->
322
+ <context.instruction>following part contains context information injected by the system. Please follow these instructions:
323
+
324
+ 1. Always prioritize handling user-visible content.
325
+ 2. the context is only required when user's queries rely on it.
326
+ </context.instruction>
327
+ <files_info>
328
+ <images>
329
+ <images_docstring>here are user upload images you can refer to</images_docstring>
330
+ <image name="abc.png" url="http://example.com/image.jpg"></image>
331
+ </images>
332
+ </files_info>
333
+ <!-- END SYSTEM CONTEXT -->`,
319
334
  type: 'text',
320
335
  },
321
- {
322
- image_url: { detail: 'auto', url: 'http://example.com/image.jpg' },
323
- type: 'image_url',
324
- },
325
336
  ],
326
337
  role: 'user',
327
338
  },
@@ -417,7 +428,21 @@ describe('ChatService', () => {
417
428
  {
418
429
  content: [
419
430
  {
420
- text: 'Hello',
431
+ text: `Hello
432
+
433
+ <!-- SYSTEM CONTEXT (NOT PART OF USER QUERY) -->
434
+ <context.instruction>following part contains context information injected by the system. Please follow these instructions:
435
+
436
+ 1. Always prioritize handling user-visible content.
437
+ 2. the context is only required when user's queries rely on it.
438
+ </context.instruction>
439
+ <files_info>
440
+ <images>
441
+ <images_docstring>here are user upload images you can refer to</images_docstring>
442
+ <image name="local-image.png" url="http://127.0.0.1:3000/uploads/image.png"></image>
443
+ </images>
444
+ </files_info>
445
+ <!-- END SYSTEM CONTEXT -->`,
421
446
  type: 'text',
422
447
  },
423
448
  {
@@ -432,6 +457,8 @@ describe('ChatService', () => {
432
457
  },
433
458
  ],
434
459
  model: 'gpt-4-vision-preview',
460
+ enabledSearch: undefined,
461
+ tools: undefined,
435
462
  },
436
463
  undefined,
437
464
  );
@@ -491,7 +518,21 @@ describe('ChatService', () => {
491
518
  {
492
519
  content: [
493
520
  {
494
- text: 'Hello',
521
+ text: `Hello
522
+
523
+ <!-- SYSTEM CONTEXT (NOT PART OF USER QUERY) -->
524
+ <context.instruction>following part contains context information injected by the system. Please follow these instructions:
525
+
526
+ 1. Always prioritize handling user-visible content.
527
+ 2. the context is only required when user's queries rely on it.
528
+ </context.instruction>
529
+ <files_info>
530
+ <images>
531
+ <images_docstring>here are user upload images you can refer to</images_docstring>
532
+ <image name="remote-image.jpg" url="https://example.com/remote-image.jpg"></image>
533
+ </images>
534
+ </files_info>
535
+ <!-- END SYSTEM CONTEXT -->`,
495
536
  type: 'text',
496
537
  },
497
538
  {
@@ -503,6 +544,8 @@ describe('ChatService', () => {
503
544
  },
504
545
  ],
505
546
  model: 'gpt-4-vision-preview',
547
+ enabledSearch: undefined,
548
+ tools: undefined,
506
549
  },
507
550
  undefined,
508
551
  );