@lobehub/chat 1.110.1 → 1.110.3

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 (126) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/Dockerfile +1 -1
  3. package/apps/desktop/.i18nrc.js +2 -1
  4. package/apps/desktop/package.json +1 -2
  5. package/apps/desktop/resources/locales/ar/menu.json +1 -0
  6. package/apps/desktop/resources/locales/bg-BG/menu.json +1 -0
  7. package/apps/desktop/resources/locales/de-DE/menu.json +1 -0
  8. package/apps/desktop/resources/locales/en-US/menu.json +1 -0
  9. package/apps/desktop/resources/locales/es-ES/menu.json +1 -0
  10. package/apps/desktop/resources/locales/fa-IR/menu.json +1 -0
  11. package/apps/desktop/resources/locales/fr-FR/menu.json +1 -0
  12. package/apps/desktop/resources/locales/it-IT/menu.json +1 -0
  13. package/apps/desktop/resources/locales/ja-JP/menu.json +1 -0
  14. package/apps/desktop/resources/locales/ko-KR/menu.json +1 -0
  15. package/apps/desktop/resources/locales/nl-NL/menu.json +1 -0
  16. package/apps/desktop/resources/locales/pl-PL/menu.json +1 -0
  17. package/apps/desktop/resources/locales/pt-BR/menu.json +1 -0
  18. package/apps/desktop/resources/locales/ru-RU/menu.json +1 -0
  19. package/apps/desktop/resources/locales/tr-TR/menu.json +1 -0
  20. package/apps/desktop/resources/locales/vi-VN/menu.json +1 -0
  21. package/apps/desktop/resources/locales/zh-CN/menu.json +1 -0
  22. package/apps/desktop/resources/locales/zh-TW/menu.json +1 -0
  23. package/apps/desktop/src/main/controllers/MenuCtr.ts +2 -2
  24. package/apps/desktop/src/main/controllers/__tests__/MenuCtr.test.ts +13 -13
  25. package/apps/desktop/src/main/locales/default/menu.ts +1 -0
  26. package/apps/desktop/src/main/menus/impls/linux.ts +9 -24
  27. package/apps/desktop/src/main/menus/impls/macOS.ts +9 -28
  28. package/apps/desktop/src/main/menus/impls/windows.ts +9 -27
  29. package/changelog/v1.json +21 -0
  30. package/locales/ar/modelProvider.json +10 -1
  31. package/locales/ar/models.json +19 -1
  32. package/locales/bg-BG/modelProvider.json +10 -1
  33. package/locales/bg-BG/models.json +19 -1
  34. package/locales/de-DE/modelProvider.json +10 -1
  35. package/locales/de-DE/models.json +19 -1
  36. package/locales/en-US/modelProvider.json +10 -1
  37. package/locales/en-US/models.json +19 -1
  38. package/locales/es-ES/modelProvider.json +10 -1
  39. package/locales/es-ES/models.json +19 -1
  40. package/locales/fa-IR/modelProvider.json +10 -1
  41. package/locales/fa-IR/models.json +19 -1
  42. package/locales/fr-FR/modelProvider.json +10 -1
  43. package/locales/fr-FR/models.json +19 -1
  44. package/locales/it-IT/modelProvider.json +10 -1
  45. package/locales/it-IT/models.json +19 -1
  46. package/locales/ja-JP/modelProvider.json +10 -1
  47. package/locales/ja-JP/models.json +19 -1
  48. package/locales/ko-KR/modelProvider.json +10 -1
  49. package/locales/ko-KR/models.json +19 -1
  50. package/locales/nl-NL/modelProvider.json +10 -1
  51. package/locales/nl-NL/models.json +19 -1
  52. package/locales/pl-PL/modelProvider.json +10 -1
  53. package/locales/pl-PL/models.json +19 -1
  54. package/locales/pt-BR/modelProvider.json +10 -1
  55. package/locales/pt-BR/models.json +19 -1
  56. package/locales/ru-RU/modelProvider.json +10 -1
  57. package/locales/ru-RU/models.json +19 -1
  58. package/locales/tr-TR/modelProvider.json +10 -1
  59. package/locales/tr-TR/models.json +19 -1
  60. package/locales/vi-VN/modelProvider.json +10 -1
  61. package/locales/vi-VN/models.json +19 -1
  62. package/locales/zh-CN/modelProvider.json +10 -1
  63. package/locales/zh-CN/models.json +19 -1
  64. package/locales/zh-TW/modelProvider.json +10 -1
  65. package/locales/zh-TW/models.json +19 -1
  66. package/next.config.ts +1 -0
  67. package/package.json +4 -4
  68. package/packages/electron-client-ipc/src/events/menu.ts +1 -1
  69. package/packages/types/package.json +3 -0
  70. package/packages/types/src/agent/chatConfig.ts +1 -1
  71. package/packages/types/src/agent/index.ts +3 -4
  72. package/packages/types/src/discover/assistants.ts +3 -3
  73. package/packages/types/src/message/chat.ts +4 -4
  74. package/src/app/(backend)/_deprecated/createBizOpenAI/auth.ts +2 -1
  75. package/src/app/(backend)/_deprecated/createBizOpenAI/createAzureOpenai.ts +1 -1
  76. package/src/app/(backend)/_deprecated/createBizOpenAI/createOpenai.ts +1 -1
  77. package/src/app/(backend)/_deprecated/createBizOpenAI/index.ts +1 -1
  78. package/src/app/(backend)/middleware/auth/index.test.ts +1 -1
  79. package/src/app/(backend)/middleware/auth/index.ts +1 -1
  80. package/src/app/(backend)/middleware/auth/utils.ts +1 -1
  81. package/src/app/(backend)/webapi/chat/[provider]/route.test.ts +1 -1
  82. package/src/app/(backend)/webapi/chat/[provider]/route.ts +2 -1
  83. package/src/app/(backend)/webapi/models/[provider]/pull/route.ts +2 -1
  84. package/src/app/(backend)/webapi/models/[provider]/route.ts +1 -1
  85. package/src/app/(backend)/webapi/plugin/gateway/route.ts +1 -1
  86. package/src/app/(backend)/webapi/text-to-image/[provider]/route.ts +1 -1
  87. package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +2 -1
  88. package/src/app/[variants]/(main)/settings/provider/_layout/Desktop/Container.tsx +1 -0
  89. package/src/app/[variants]/(main)/settings/provider/_layout/Desktop/index.tsx +4 -9
  90. package/src/app/[variants]/(main)/settings/provider/features/ModelList/DisabledModels.tsx +15 -5
  91. package/src/app/[variants]/(main)/settings/provider/features/ModelList/EnabledModelList/index.tsx +22 -4
  92. package/src/app/[variants]/(main)/settings/provider/features/ModelList/index.tsx +99 -3
  93. package/src/app/[variants]/layout.tsx +2 -1
  94. package/src/components/InnerLink.tsx +20 -0
  95. package/src/config/modelProviders/ai302.ts +1 -0
  96. package/src/config/modelProviders/openai.ts +1 -0
  97. package/src/features/ChatInput/Desktop/InputArea/index.tsx +14 -0
  98. package/src/features/Conversation/Error/index.tsx +1 -1
  99. package/src/features/Conversation/components/ChatItem/index.tsx +18 -1
  100. package/src/features/ElectronTitlebar/UpdateModal.tsx +15 -3
  101. package/src/features/Portal/Artifacts/Header.tsx +1 -1
  102. package/src/hooks/usePlatform.ts +1 -1
  103. package/src/layout/GlobalProvider/index.tsx +3 -0
  104. package/src/libs/model-runtime/RouterRuntime/createRuntime.ts +2 -2
  105. package/src/locales/default/modelProvider.ts +9 -0
  106. package/src/server/ld.ts +1 -1
  107. package/src/services/__tests__/chat.test.ts +1 -1
  108. package/src/services/chat.ts +1 -1
  109. package/src/services/electron/system.ts +3 -1
  110. package/src/store/chat/slices/message/action.ts +1 -1
  111. package/src/store/chat/slices/plugin/action.ts +1 -1
  112. package/src/store/serverConfig/Provider.tsx +7 -2
  113. package/src/store/serverConfig/store.ts +2 -0
  114. package/src/utils/errorResponse.test.ts +1 -1
  115. package/src/utils/errorResponse.ts +2 -1
  116. package/src/utils/fetch/__tests__/parseError.test.ts +1 -2
  117. package/src/utils/fetch/fetchSSE.ts +2 -1
  118. package/src/utils/fetch/parseError.ts +1 -1
  119. package/tsconfig.json +1 -1
  120. package/.dockerignore +0 -9
  121. package/packages/file-loaders/src/loaders/docx/fixtures/test.docx +0 -0
  122. package/packages/file-loaders/src/loaders/excel/fixtures/test.xlsx +0 -0
  123. package/packages/file-loaders/src/loaders/pptx/fixtures/test.pptx +0 -0
  124. package/packages/file-loaders/test/fixtures/test.docx +0 -0
  125. package/packages/file-loaders/test/fixtures/test.pptx +0 -0
  126. /package/{packages/types/src → src/types}/next.ts +0 -0
@@ -1,7 +1,7 @@
1
1
  import { ActionIcon, Text } from '@lobehub/ui';
2
2
  import isEqual from 'fast-deep-equal';
3
3
  import { ArrowDownUpIcon, ToggleLeft } from 'lucide-react';
4
- import { useState } from 'react';
4
+ import { useMemo, useState } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { Center, Flexbox } from 'react-layout-kit';
7
7
 
@@ -11,7 +11,11 @@ import { aiModelSelectors } from '@/store/aiInfra/selectors';
11
11
  import ModelItem from '../ModelItem';
12
12
  import SortModelModal from '../SortModelModal';
13
13
 
14
- const EnabledModelList = () => {
14
+ interface EnabledModelListProps {
15
+ activeTab: string;
16
+ }
17
+
18
+ const EnabledModelList = ({ activeTab }: EnabledModelListProps) => {
15
19
  const { t } = useTranslation('modelProvider');
16
20
 
17
21
  const enabledModels = useAiInfraStore(aiModelSelectors.enabledAiProviderModelList, isEqual);
@@ -20,6 +24,14 @@ const EnabledModelList = () => {
20
24
  const [batchLoading, setBatchLoading] = useState(false);
21
25
 
22
26
  const isEmpty = enabledModels.length === 0;
27
+
28
+ // Filter models based on active tab
29
+ const filteredModels = useMemo(() => {
30
+ if (activeTab === 'all') return enabledModels;
31
+ return enabledModels.filter((model) => model.type === activeTab);
32
+ }, [enabledModels, activeTab]);
33
+
34
+ const isCurrentTabEmpty = filteredModels.length === 0;
23
35
  return (
24
36
  <>
25
37
  <Flexbox horizontal justify={'space-between'}>
@@ -63,17 +75,23 @@ const EnabledModelList = () => {
63
75
  />
64
76
  )}
65
77
  </Flexbox>
78
+
66
79
  {isEmpty ? (
67
80
  <Center padding={12}>
68
81
  <Text style={{ fontSize: 12 }} type={'secondary'}>
69
82
  {t('providerModels.list.enabledEmpty')}
70
83
  </Text>
71
84
  </Center>
85
+ ) : isCurrentTabEmpty ? (
86
+ <Center padding={12}>
87
+ <Text style={{ fontSize: 12 }} type={'secondary'}>
88
+ {t('providerModels.list.noModelsInCategory')}
89
+ </Text>
90
+ </Center>
72
91
  ) : (
73
92
  <Flexbox gap={2}>
74
- {enabledModels.map(({ displayName, id, ...res }) => {
93
+ {filteredModels.map(({ displayName, id, ...res }) => {
75
94
  const label = displayName || id;
76
-
77
95
  return <ModelItem displayName={label as string} id={id as string} key={id} {...res} />;
78
96
  })}
79
97
  </Flexbox>
@@ -1,7 +1,18 @@
1
1
  'use client';
2
2
 
3
+ import { Icon, Tabs } from '@lobehub/ui';
3
4
  import { useTheme } from 'antd-style';
4
- import { Suspense, memo } from 'react';
5
+ import isEqual from 'fast-deep-equal';
6
+ import {
7
+ AudioLines,
8
+ BoltIcon,
9
+ Grid3x3Icon,
10
+ ImageIcon,
11
+ MessageSquareTextIcon,
12
+ MicIcon,
13
+ } from 'lucide-react';
14
+ import { Suspense, memo, useMemo, useState } from 'react';
15
+ import { useTranslation } from 'react-i18next';
5
16
  import { Flexbox } from 'react-layout-kit';
6
17
 
7
18
  import { useIsMobile } from '@/hooks/useIsMobile';
@@ -20,14 +31,92 @@ interface ContentProps {
20
31
  }
21
32
 
22
33
  const Content = memo<ContentProps>(({ id }) => {
34
+ const { t } = useTranslation('modelProvider');
35
+ const [activeTab, setActiveTab] = useState('all');
36
+
23
37
  const [isSearching, isEmpty, useFetchAiProviderModels] = useAiInfraStore((s) => [
24
38
  !!s.modelSearchKeyword,
25
39
  aiModelSelectors.isEmptyAiProviderModelList(s),
26
40
  s.useFetchAiProviderModels,
27
41
  ]);
28
42
 
43
+ const allModels = useAiInfraStore(aiModelSelectors.filteredAiProviderModelList, isEqual);
44
+
29
45
  const { isLoading } = useFetchAiProviderModels(id);
30
46
 
47
+ // Count models by type (for all models, not just enabled)
48
+ const modelCounts = useMemo(() => {
49
+ const counts = {
50
+ all: allModels.length,
51
+ chat: 0,
52
+ embedding: 0,
53
+ image: 0,
54
+ stt: 0,
55
+ tts: 0,
56
+ };
57
+
58
+ allModels.forEach((model) => {
59
+ const type = model.type;
60
+ if (type && Object.prototype.hasOwnProperty.call(counts, type)) {
61
+ counts[type as keyof typeof counts]++;
62
+ }
63
+ });
64
+
65
+ return counts;
66
+ }, [allModels]);
67
+
68
+ // Tab definitions with counts (only show tabs with models > 0, except 'all' tab)
69
+ const tabs = useMemo(() => {
70
+ const formatTabLabel = (baseLabel: string, count: number) =>
71
+ count > 0 ? `${baseLabel} (${count})` : baseLabel;
72
+
73
+ const allTabs = [
74
+ {
75
+ count: modelCounts.all,
76
+ icon: <Icon icon={Grid3x3Icon} size={16} />,
77
+ key: 'all',
78
+ label: formatTabLabel(t('providerModels.tabs.all'), modelCounts.all),
79
+ },
80
+ {
81
+ count: modelCounts.chat,
82
+ icon: <Icon icon={MessageSquareTextIcon} size={16} />,
83
+ key: 'chat',
84
+ label: formatTabLabel(t('providerModels.tabs.chat'), modelCounts.chat),
85
+ },
86
+ {
87
+ count: modelCounts.image,
88
+ icon: <Icon icon={ImageIcon} size={16} />,
89
+ key: 'image',
90
+ label: formatTabLabel(t('providerModels.tabs.image'), modelCounts.image),
91
+ },
92
+ {
93
+ count: modelCounts.embedding,
94
+ icon: <Icon icon={BoltIcon} size={16} />,
95
+ key: 'embedding',
96
+ label: formatTabLabel(t('providerModels.tabs.embedding'), modelCounts.embedding),
97
+ },
98
+ {
99
+ count: modelCounts.stt,
100
+ icon: <Icon icon={MicIcon} size={16} />,
101
+ key: 'stt',
102
+ label: formatTabLabel(t('providerModels.tabs.stt'), modelCounts.stt),
103
+ },
104
+ {
105
+ count: modelCounts.tts,
106
+ icon: <Icon icon={AudioLines} size={16} />,
107
+ key: 'tts',
108
+ label: formatTabLabel(t('providerModels.tabs.tts'), modelCounts.tts),
109
+ },
110
+ ];
111
+
112
+ // Only show tabs that have models (count > 0), but always show 'all' tab
113
+ return allTabs.filter((tab) => tab.key === 'all' || tab.count > 0);
114
+ }, [modelCounts]);
115
+
116
+ // Ensure active tab is available, fallback to 'all' if current tab is hidden
117
+ const availableTabKeys = tabs.map((tab) => tab.key);
118
+ const currentActiveTab = availableTabKeys.includes(activeTab) ? activeTab : 'all';
119
+
31
120
  if (isLoading) return <SkeletonList />;
32
121
 
33
122
  if (isSearching) return <SearchResult />;
@@ -36,8 +125,15 @@ const Content = memo<ContentProps>(({ id }) => {
36
125
  <EmptyModels provider={id} />
37
126
  ) : (
38
127
  <Flexbox>
39
- <EnabledModelList />
40
- <DisabledModels />
128
+ <Tabs
129
+ activeKey={currentActiveTab}
130
+ items={tabs}
131
+ onChange={setActiveTab}
132
+ size="small"
133
+ style={{ marginBottom: 12 }}
134
+ />
135
+ <EnabledModelList activeTab={currentActiveTab} />
136
+ <DisabledModels activeTab={currentActiveTab} />
41
137
  </Flexbox>
42
138
  );
43
139
  });
@@ -31,7 +31,7 @@ const RootLayout = async ({ children, params, modal }: RootLayoutProps) => {
31
31
  const direction = isRtlLang(locale) ? 'rtl' : 'ltr';
32
32
 
33
33
  return (
34
- <html dir={direction} lang={locale} suppressHydrationWarning>
34
+ <html dir={direction} lang={locale}>
35
35
  <head>
36
36
  {process.env.DEBUG_REACT_SCAN === '1' && (
37
37
  // eslint-disable-next-line @next/next/no-sync-scripts
@@ -46,6 +46,7 @@ const RootLayout = async ({ children, params, modal }: RootLayoutProps) => {
46
46
  locale={locale}
47
47
  neutralColor={neutralColor}
48
48
  primaryColor={primaryColor}
49
+ variants={variants}
49
50
  >
50
51
  <AuthProvider>
51
52
  {children}
@@ -0,0 +1,20 @@
1
+ 'use client';
2
+
3
+ import Link, { LinkProps } from 'next/link';
4
+ import { AnchorHTMLAttributes, ReactNode } from 'react';
5
+
6
+ import { useServerConfigStore } from '@/store/serverConfig';
7
+
8
+ interface InnerLinkProps
9
+ extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkProps>,
10
+ LinkProps {
11
+ children?: ReactNode | undefined;
12
+ }
13
+
14
+ const InnerLink = ({ href, ...props }: InnerLinkProps) => {
15
+ const variants = useServerConfigStore((s) => s.segmentVariants);
16
+
17
+ return <Link {...props} as={href} href={`/${variants}${href}`} />;
18
+ };
19
+
20
+ export default InnerLink;
@@ -2,6 +2,7 @@ import { ModelProviderCard } from '@/types/llm';
2
2
 
3
3
  // ref: https://302.ai/pricing/
4
4
  const Ai302: ModelProviderCard = {
5
+ apiKeyUrl: 'https://lobe.li/Oizw5sN',
5
6
  chatModels: [
6
7
  {
7
8
  contextWindowTokens: 32_000,
@@ -2,6 +2,7 @@ import { ModelProviderCard } from '@/types/llm';
2
2
 
3
3
  // ref: https://platform.openai.com/docs/deprecations
4
4
  const OpenAI: ModelProviderCard = {
5
+ apiKeyUrl: 'https://platform.openai.com/api-keys?utm_source=lobehub',
5
6
  chatModels: [
6
7
  {
7
8
  contextWindowTokens: 1_047_576,
@@ -5,6 +5,7 @@ import { RefObject, memo, useEffect, useRef } from 'react';
5
5
  import { useHotkeysContext } from 'react-hotkeys-hook';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
8
+ import { isDesktop } from '@/const/version';
8
9
  import { useUserStore } from '@/store/user';
9
10
  import { preferenceSelectors } from '@/store/user/selectors';
10
11
  import { HotkeyEnum } from '@/types/hotkey';
@@ -86,6 +87,19 @@ const InputArea = memo<InputAreaProps>(({ onSend, value, loading, onChange }) =>
86
87
  onCompositionStart={() => {
87
88
  isChineseInput.current = true;
88
89
  }}
90
+ onContextMenu={async (e) => {
91
+ if (isDesktop) {
92
+ e.preventDefault();
93
+ const textArea = ref.current?.resizableTextArea?.textArea;
94
+ const hasSelection = textArea && textArea.selectionStart !== textArea.selectionEnd;
95
+ const { electronSystemService } = await import('@/services/electron/system');
96
+
97
+ electronSystemService.showContextMenu('editor', {
98
+ hasSelection: !!hasSelection,
99
+ value: value,
100
+ });
101
+ }
102
+ }}
89
103
  onFocus={() => {
90
104
  enableScope(HotkeyEnum.AddUserMessage);
91
105
  }}
@@ -1,3 +1,4 @@
1
+ import { ChatErrorType, ErrorType } from '@lobechat/types/fetch';
1
2
  import { IPluginErrorType } from '@lobehub/chat-plugin-sdk';
2
3
  import type { AlertProps } from '@lobehub/ui';
3
4
  import { Skeleton } from 'antd';
@@ -7,7 +8,6 @@ import { useTranslation } from 'react-i18next';
7
8
 
8
9
  import { useProviderName } from '@/hooks/useProviderName';
9
10
  import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '@/libs/model-runtime';
10
- import { ChatErrorType, ErrorType } from '@/types/fetch';
11
11
  import { ChatMessage, ChatMessageError } from '@/types/message';
12
12
 
13
13
  import ChatInvalidAPIKey from './ChatInvalidApiKey';
@@ -6,6 +6,7 @@ import { MouseEventHandler, ReactNode, memo, use, useCallback, useMemo } from 'r
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { Flexbox } from 'react-layout-kit';
8
8
 
9
+ import { isDesktop } from '@/const/version';
9
10
  import ChatItem from '@/features/ChatItem';
10
11
  import { VirtuosoContext } from '@/features/Conversation/components/VirtualizedList/VirtuosoContext';
11
12
  import { useAgentStore } from '@/store/agent';
@@ -220,6 +221,19 @@ const Item = memo<ChatListItemProps>(
220
221
  toggleMessageEditing(id, edit);
221
222
  }, []);
222
223
 
224
+ const onContextMenu = useCallback(async () => {
225
+ if (isDesktop && item) {
226
+ const { electronSystemService } = await import('@/services/electron/system');
227
+
228
+ electronSystemService.showContextMenu('chat', {
229
+ content: item.content,
230
+ hasError: !!item.error,
231
+ messageId: id,
232
+ role: item.role,
233
+ });
234
+ }
235
+ }, [id, item]);
236
+
223
237
  const belowMessage = useMemo(() => item && <BelowMessage data={item} />, [item]);
224
238
  const errorMessage = useMemo(() => item && <ErrorMessageExtra data={item} />, [item]);
225
239
  const messageExtra = useMemo(() => item && <MessageExtra data={item} />, [item]);
@@ -228,7 +242,10 @@ const Item = memo<ChatListItemProps>(
228
242
  item && (
229
243
  <InPortalThreadContext.Provider value={inPortalThread}>
230
244
  {enableHistoryDivider && <History />}
231
- <Flexbox className={cx(styles.message, className, isMessageLoading && styles.loading)}>
245
+ <Flexbox
246
+ className={cx(styles.message, className, isMessageLoading && styles.loading)}
247
+ onContextMenu={onContextMenu}
248
+ >
232
249
  <ChatItem
233
250
  actions={actionBar}
234
251
  avatar={item.meta}
@@ -115,11 +115,23 @@ export const UpdateModal = memo(() => {
115
115
  const closeDownloadedModal = () => setDownloadedInfo(null);
116
116
  const closeLatestVersionModal = () => setLatestVersionInfo(null);
117
117
 
118
+ const handleCancelCheck = () => {
119
+ setIsChecking(false);
120
+ setUpdateAvailableInfo(null);
121
+ setDownloadedInfo(null);
122
+ setProgress(null);
123
+ setLatestVersionInfo(null);
124
+ };
125
+
118
126
  const renderCheckingModal = () => (
119
127
  <Modal
120
- closable={false}
121
- footer={null}
122
- maskClosable={false}
128
+ closable
129
+ footer={[
130
+ <Button key="cancel" onClick={handleCancelCheck}>
131
+ {t('cancel', { ns: 'common' })}
132
+ </Button>,
133
+ ]}
134
+ onCancel={handleCancelCheck}
123
135
  open={isChecking}
124
136
  title={t('updater.checkingUpdate')}
125
137
  >
@@ -1,3 +1,4 @@
1
+ import { ArtifactType } from '@lobechat/types/artifact';
1
2
  import { ActionIcon, Icon, Segmented, Text } from '@lobehub/ui';
2
3
  import { ConfigProvider } from 'antd';
3
4
  import { cx } from 'antd-style';
@@ -9,7 +10,6 @@ import { useChatStore } from '@/store/chat';
9
10
  import { chatPortalSelectors } from '@/store/chat/selectors';
10
11
  import { ArtifactDisplayMode } from '@/store/chat/slices/portal/initialState';
11
12
  import { oneLineEllipsis } from '@/styles';
12
- import { ArtifactType } from '@/types/artifact';
13
13
 
14
14
  const Header = () => {
15
15
  const { t } = useTranslation('portal');
@@ -37,6 +37,6 @@ export const usePlatform = () => {
37
37
  ((platformInfo.isChromium && !platformInfo.isIOS) ||
38
38
  (platformInfo.isMacOS && platformInfo.isSonomaOrLaterSafari)),
39
39
  }),
40
- [platformInfo],
40
+ [],
41
41
  );
42
42
  };
@@ -23,6 +23,7 @@ interface GlobalLayoutProps {
23
23
  locale: string;
24
24
  neutralColor?: string;
25
25
  primaryColor?: string;
26
+ variants?: string;
26
27
  }
27
28
 
28
29
  const GlobalLayout = async ({
@@ -32,6 +33,7 @@ const GlobalLayout = async ({
32
33
  locale: userLocale,
33
34
  appearance,
34
35
  isMobile,
36
+ variants,
35
37
  }: GlobalLayoutProps) => {
36
38
  const antdLocale = await getAntdLocale(userLocale);
37
39
 
@@ -52,6 +54,7 @@ const GlobalLayout = async ({
52
54
  <ServerConfigStoreProvider
53
55
  featureFlags={serverFeatureFlags}
54
56
  isMobile={isMobile}
57
+ segmentVariants={variants}
55
58
  serverConfig={serverConfig}
56
59
  >
57
60
  <QueryProvider>
@@ -135,9 +135,9 @@ export const createRouterRuntime = ({
135
135
  this._runtimes = routers.map((router) => {
136
136
  const providerAI = router.runtime ?? baseRuntimeMap[router.apiType] ?? LobeOpenAI;
137
137
 
138
- const finalOptions = { ...router.options, ...options };
138
+ const finalOptions = { ...params, ...options, ...router.options };
139
139
  // @ts-ignore
140
- const runtime: LobeRuntimeAI = new providerAI({ ...params, ...finalOptions, id });
140
+ const runtime: LobeRuntimeAI = new providerAI({ ...finalOptions, id });
141
141
 
142
142
  return { id: router.apiType, models: router.models, runtime };
143
143
  });
@@ -310,6 +310,7 @@ export default {
310
310
  latestTime: '上次更新时间:{{time}}',
311
311
  noLatestTime: '暂未获取列表',
312
312
  },
313
+ noModelsInCategory: '该分类下暂无启用的模型',
313
314
  resetAll: {
314
315
  conform: '确认重置当前模型的所有修改?重置后当前模型列表将会回到默认状态',
315
316
  success: '重置成功',
@@ -321,6 +322,14 @@ export default {
321
322
  total: '共 {{count}} 个模型可用',
322
323
  },
323
324
  searchNotFound: '未找到搜索结果',
325
+ tabs: {
326
+ all: '全部',
327
+ chat: '对话',
328
+ embedding: '向量化',
329
+ image: '图片',
330
+ stt: 'ASR',
331
+ tts: 'TTS',
332
+ },
324
333
  },
325
334
  sortModal: {
326
335
  success: '排序更新成功',
package/src/server/ld.ts CHANGED
@@ -22,7 +22,7 @@ export const AUTHOR_LIST = {
22
22
  avatar: 'https://avatars.githubusercontent.com/u/17870709?v=4',
23
23
  desc: 'Founder, Design Engineer',
24
24
  name: 'CanisMinor',
25
- url: 'https://github.com/arvinxx',
25
+ url: 'https://github.com/canisminor1990',
26
26
  },
27
27
  lobehub: {
28
28
  avatar: 'https://avatars.githubusercontent.com/u/131470832?v=4',
@@ -1,3 +1,4 @@
1
+ import { ChatErrorType } from '@lobechat/types/fetch';
1
2
  import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
2
3
  import { act } from '@testing-library/react';
3
4
  import { merge } from 'lodash-es';
@@ -35,7 +36,6 @@ import { UserStore } from '@/store/user';
35
36
  import { UserSettingsState, initialSettingsState } from '@/store/user/slices/settings/initialState';
36
37
  import { DalleManifest } from '@/tools/dalle';
37
38
  import { WebBrowsingManifest } from '@/tools/web-browsing';
38
- import { ChatErrorType } from '@/types/fetch';
39
39
  import { ChatImageItem, ChatMessage } from '@/types/message';
40
40
  import { ChatStreamPayload, type OpenAIChatMessage } from '@/types/openai/chat';
41
41
  import { LobeTool } from '@/types/tool';
@@ -1,3 +1,4 @@
1
+ import { ChatErrorType } from '@lobechat/types/fetch';
1
2
  import { PluginRequestPayload, createHeadersWithPluginSettings } from '@lobehub/chat-plugin-sdk';
2
3
  import { produce } from 'immer';
3
4
  import { merge } from 'lodash-es';
@@ -34,7 +35,6 @@ import {
34
35
  } from '@/store/user/selectors';
35
36
  import { WebBrowsingManifest } from '@/tools/web-browsing';
36
37
  import { WorkingModel } from '@/types/agent';
37
- import { ChatErrorType } from '@/types/fetch';
38
38
  import { ChatImageItem, ChatMessage, MessageToolCall } from '@/types/message';
39
39
  import type { ChatStreamPayload, OpenAIChatMessage } from '@/types/openai/chat';
40
40
  import { UserMessageContentPart } from '@/types/openai/chat';
@@ -26,7 +26,9 @@ class ElectronSystemService {
26
26
  return dispatch('minimizeWindow');
27
27
  }
28
28
 
29
- // Add other system-related service methods here if needed in the future
29
+ showContextMenu = async (type: string, data?: any) => {
30
+ return dispatch('showContextMenu', { data, type });
31
+ };
30
32
  }
31
33
 
32
34
  // Export a singleton instance of the service
@@ -1,5 +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 { ChatErrorType } from '@lobechat/types/fetch';
3
4
  import { copyToClipboard } from '@lobehub/ui';
4
5
  import isEqual from 'fast-deep-equal';
5
6
  import { SWRResponse, mutate } from 'swr';
@@ -12,7 +13,6 @@ import { topicService } from '@/services/topic';
12
13
  import { traceService } from '@/services/trace';
13
14
  import { ChatStore } from '@/store/chat/store';
14
15
  import { messageMapKey } from '@/store/chat/utils/messageMapKey';
15
- import { ChatErrorType } from '@/types/fetch';
16
16
  import {
17
17
  ChatMessage,
18
18
  ChatMessageError,
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable sort-keys-fix/sort-keys-fix, typescript-sort-keys/interface */
2
+ import { ChatErrorType } from '@lobechat/types/fetch';
2
3
  import { PluginErrorType } from '@lobehub/chat-plugin-sdk';
3
4
  import isEqual from 'fast-deep-equal';
4
5
  import { t } from 'i18next';
@@ -13,7 +14,6 @@ import { ChatStore } from '@/store/chat/store';
13
14
  import { useToolStore } from '@/store/tool';
14
15
  import { pluginSelectors } from '@/store/tool/selectors';
15
16
  import { builtinTools } from '@/tools';
16
- import { ChatErrorType } from '@/types/fetch';
17
17
  import {
18
18
  ChatMessage,
19
19
  ChatMessageError,
@@ -11,12 +11,17 @@ interface GlobalStoreProviderProps {
11
11
  children: ReactNode;
12
12
  featureFlags?: Partial<IFeatureFlags>;
13
13
  isMobile?: boolean;
14
+ segmentVariants?: string;
14
15
  serverConfig?: GlobalServerConfig;
15
16
  }
16
17
 
17
18
  export const ServerConfigStoreProvider = memo<GlobalStoreProviderProps>(
18
- ({ children, featureFlags, serverConfig, isMobile }) => (
19
- <Provider createStore={() => createServerConfigStore({ featureFlags, isMobile, serverConfig })}>
19
+ ({ children, featureFlags, serverConfig, isMobile, segmentVariants }) => (
20
+ <Provider
21
+ createStore={() =>
22
+ createServerConfigStore({ featureFlags, isMobile, segmentVariants, serverConfig })
23
+ }
24
+ >
20
25
  {children}
21
26
  </Provider>
22
27
  ),
@@ -15,11 +15,13 @@ import { ServerConfigAction, createServerConfigSlice } from './action';
15
15
  interface ServerConfigState {
16
16
  featureFlags: IFeatureFlags;
17
17
  isMobile?: boolean;
18
+ segmentVariants?: string;
18
19
  serverConfig: GlobalServerConfig;
19
20
  }
20
21
 
21
22
  const initialState: ServerConfigState = {
22
23
  featureFlags: DEFAULT_FEATURE_FLAGS,
24
+ segmentVariants: '',
23
25
  serverConfig: { aiProvider: {}, telemetry: {} },
24
26
  };
25
27
 
@@ -1,7 +1,7 @@
1
+ import { ChatErrorType } from '@lobechat/types/fetch';
1
2
  import { describe, expect, it, vi } from 'vitest';
2
3
 
3
4
  import { AgentRuntimeErrorType } from '@/libs/model-runtime';
4
- import { ChatErrorType } from '@/types/fetch';
5
5
 
6
6
  import { createErrorResponse } from './errorResponse';
7
7
 
@@ -1,5 +1,6 @@
1
+ import { ChatErrorType, ErrorResponse, ErrorType } from '@lobechat/types/fetch';
2
+
1
3
  import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '@/libs/model-runtime';
2
- import { ChatErrorType, ErrorResponse, ErrorType } from '@/types/fetch';
3
4
 
4
5
  const getStatus = (errorType: ILobeAgentRuntimeErrorType | ErrorType) => {
5
6
  // InvalidAccessCode / InvalidAzureAPIKey / InvalidOpenAIAPIKey / InvalidZhipuAPIKey ....
@@ -1,7 +1,6 @@
1
+ import { ErrorResponse } from '@lobechat/types/fetch';
1
2
  import { afterEach, describe, expect, it, vi } from 'vitest';
2
3
 
3
- import { ErrorResponse } from '@/types/fetch';
4
-
5
4
  import { getMessageError } from '../parseError';
6
5
 
7
6
  // 模拟 i18next
@@ -1,7 +1,8 @@
1
+ import { ChatErrorType } from '@lobechat/types/fetch';
2
+
1
3
  import { MESSAGE_CANCEL_FLAT } from '@/const/message';
2
4
  import { LOBE_CHAT_OBSERVATION_ID, LOBE_CHAT_TRACE_ID } from '@/const/trace';
3
5
  import { parseToolCalls } from '@/libs/model-runtime';
4
- import { ChatErrorType } from '@/types/fetch';
5
6
  import { ResponseAnimation, ResponseAnimationStyle } from '@/types/llm';
6
7
  import {
7
8
  ChatMessageError,
@@ -1,6 +1,6 @@
1
+ import { ErrorResponse, ErrorType } from '@lobechat/types/fetch';
1
2
  import { t } from 'i18next';
2
3
 
3
- import { ErrorResponse, ErrorType } from '@/types/fetch';
4
4
  import { ChatMessageError } from '@/types/message';
5
5
 
6
6
  export const getMessageError = async (response: Response) => {
package/tsconfig.json CHANGED
@@ -18,7 +18,7 @@
18
18
  "baseUrl": ".",
19
19
  "types": ["vitest/globals", "@serwist/next/typings"],
20
20
  "paths": {
21
- "@/types/*": ["./packages/types/src/*"],
21
+ "@/types/*": ["./packages/types/src/*", "./src/types/*"],
22
22
  "@/*": ["./src/*"],
23
23
  "~test-utils": ["./tests/utils.tsx"]
24
24
  },
package/.dockerignore DELETED
@@ -1,9 +0,0 @@
1
- Dockerfile
2
- .dockerignore
3
- node_modules
4
- npm-debug.log
5
- .next
6
- .git
7
- .github
8
- *.md
9
- .env.example
File without changes