@lobehub/chat 1.45.9 → 1.45.10

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 (37) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -0
  3. package/locales/ar/modelProvider.json +3 -0
  4. package/locales/bg-BG/modelProvider.json +3 -0
  5. package/locales/de-DE/modelProvider.json +3 -0
  6. package/locales/en-US/modelProvider.json +3 -0
  7. package/locales/es-ES/modelProvider.json +3 -0
  8. package/locales/fa-IR/modelProvider.json +3 -0
  9. package/locales/fr-FR/modelProvider.json +3 -0
  10. package/locales/it-IT/modelProvider.json +3 -0
  11. package/locales/ja-JP/modelProvider.json +3 -0
  12. package/locales/ko-KR/modelProvider.json +3 -0
  13. package/locales/nl-NL/modelProvider.json +3 -0
  14. package/locales/pl-PL/modelProvider.json +3 -0
  15. package/locales/pt-BR/modelProvider.json +3 -0
  16. package/locales/ru-RU/modelProvider.json +3 -0
  17. package/locales/tr-TR/modelProvider.json +3 -0
  18. package/locales/vi-VN/modelProvider.json +3 -0
  19. package/locales/zh-CN/modelProvider.json +3 -0
  20. package/locales/zh-TW/modelProvider.json +3 -0
  21. package/package.json +3 -3
  22. package/src/app/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/Tags.tsx +3 -2
  23. package/src/app/(main)/settings/provider/features/ModelList/DisabledModels.tsx +21 -3
  24. package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +5 -5
  25. package/src/features/ChatInput/ActionBar/Token/index.tsx +3 -6
  26. package/src/features/ChatInput/ActionBar/Tools/index.tsx +3 -1
  27. package/src/features/ChatInput/ActionBar/Upload/ServerMode.tsx +2 -1
  28. package/src/features/ChatInput/Desktop/FilePreview/index.tsx +3 -3
  29. package/src/hooks/useModelContextWindowTokens.ts +15 -0
  30. package/src/hooks/useModelHasContextWindowToken.ts +19 -0
  31. package/src/hooks/useModelSupportToolUse.ts +2 -2
  32. package/src/hooks/useModelSupportVision.ts +2 -2
  33. package/src/locales/default/modelProvider.ts +1 -0
  34. package/src/services/__tests__/chat.test.ts +1 -0
  35. package/src/services/chat.ts +7 -4
  36. package/src/store/aiInfra/slices/aiModel/selectors.ts +21 -6
  37. package/src/types/aiModel.ts +2 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.45.10](https://github.com/lobehub/lobe-chat/compare/v1.45.9...v1.45.10)
6
+
7
+ <sup>Released on **2025-01-14**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix some providers issues.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix some providers issues, closes [#5429](https://github.com/lobehub/lobe-chat/issues/5429) ([b7edbd3](https://github.com/lobehub/lobe-chat/commit/b7edbd3))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 1.45.9](https://github.com/lobehub/lobe-chat/compare/v1.45.8...v1.45.9)
6
31
 
7
32
  <sup>Released on **2025-01-14**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "fixes": [
5
+ "Fix some providers issues."
6
+ ]
7
+ },
8
+ "date": "2025-01-14",
9
+ "version": "1.45.10"
10
+ },
2
11
  {
3
12
  "children": {
4
13
  "fixes": [
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "إضافة نموذج",
275
275
  "disabled": "غير مفعل",
276
+ "disabledActions": {
277
+ "showMore": "عرض الكل"
278
+ },
276
279
  "empty": {
277
280
  "desc": "يرجى إنشاء نموذج مخصص أو سحب نموذج للبدء في الاستخدام",
278
281
  "title": "لا توجد نماذج متاحة"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Добавяне на модел",
275
275
  "disabled": "Неактивен",
276
+ "disabledActions": {
277
+ "showMore": "Покажи всичко"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Моля, създайте персонализиран модел или изтеглете модел, за да започнете да го използвате",
278
281
  "title": "Няма налични модели"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Modell hinzufügen",
275
275
  "disabled": "Nicht aktiviert",
276
+ "disabledActions": {
277
+ "showMore": "Alle anzeigen"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Bitte erstellen Sie ein benutzerdefiniertes Modell oder ziehen Sie ein Modell, um zu beginnen.",
278
281
  "title": "Keine verfügbaren Modelle"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Add Model",
275
275
  "disabled": "Disabled",
276
+ "disabledActions": {
277
+ "showMore": "Show All"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Please create a custom model or pull a model to get started.",
278
281
  "title": "No available models"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Agregar modelo",
275
275
  "disabled": "No habilitado",
276
+ "disabledActions": {
277
+ "showMore": "Mostrar todo"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Por favor, crea un modelo personalizado o importa un modelo para comenzar a usarlo.",
278
281
  "title": "No hay modelos disponibles"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "مدل جدید اضافه کنید",
275
275
  "disabled": "غیرفعال",
276
+ "disabledActions": {
277
+ "showMore": "نمایش همه"
278
+ },
276
279
  "empty": {
277
280
  "desc": "لطفاً یک مدل سفارشی ایجاد کنید یا پس از بارگذاری مدل‌ها، شروع به استفاده کنید",
278
281
  "title": "مدل قابل استفاده‌ای وجود ندارد"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Ajouter un modèle",
275
275
  "disabled": "Non activé",
276
+ "disabledActions": {
277
+ "showMore": "Afficher tout"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Veuillez créer un modèle personnalisé ou importer un modèle pour commencer à l'utiliser.",
278
281
  "title": "Aucun modèle disponible"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Aggiungi modello",
275
275
  "disabled": "Non attivato",
276
+ "disabledActions": {
277
+ "showMore": "Mostra tutto"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Si prega di creare un modello personalizzato o di importare un modello per iniziare a utilizzarlo",
278
281
  "title": "Nessun modello disponibile"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "モデルを追加",
275
275
  "disabled": "無効",
276
+ "disabledActions": {
277
+ "showMore": "すべて表示"
278
+ },
276
279
  "empty": {
277
280
  "desc": "カスタムモデルを作成するか、モデルを取得してから使用を開始してください",
278
281
  "title": "利用可能なモデルはありません"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "모델 추가",
275
275
  "disabled": "비활성화",
276
+ "disabledActions": {
277
+ "showMore": "모두 보기"
278
+ },
276
279
  "empty": {
277
280
  "desc": "사용할 수 있는 모델이 없습니다. 사용자 정의 모델을 생성하거나 모델을 가져온 후 시작하세요.",
278
281
  "title": "사용 가능한 모델이 없습니다."
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Model toevoegen",
275
275
  "disabled": "Niet ingeschakeld",
276
+ "disabledActions": {
277
+ "showMore": "Toon alles"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Maak een aangepast model of haal een model op om te beginnen met gebruiken.",
278
281
  "title": "Geen beschikbare modellen"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Dodaj model",
275
275
  "disabled": "Nieaktywne",
276
+ "disabledActions": {
277
+ "showMore": "Pokaż więcej"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Proszę utworzyć model niestandardowy lub pobrać model, aby rozpocząć korzystanie.",
278
281
  "title": "Brak dostępnych modeli"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Adicionar Modelo",
275
275
  "disabled": "Não habilitado",
276
+ "disabledActions": {
277
+ "showMore": "Mostrar tudo"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Por favor, crie um modelo personalizado ou importe um modelo para começar a usar.",
278
281
  "title": "Nenhum modelo disponível"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Добавить модель",
275
275
  "disabled": "Не активирован",
276
+ "disabledActions": {
277
+ "showMore": "Показать все"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Пожалуйста, создайте пользовательскую модель или загрузите модель, чтобы начать использовать.",
278
281
  "title": "Нет доступных моделей"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Model Ekle",
275
275
  "disabled": "Devre dışı",
276
+ "disabledActions": {
277
+ "showMore": "Hepsini Göster"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Lütfen özel bir model oluşturun veya kullanmaya başlamadan önce bir model çekin",
278
281
  "title": "Kullanılabilir model yok"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "Thêm mô hình",
275
275
  "disabled": "Chưa được kích hoạt",
276
+ "disabledActions": {
277
+ "showMore": "Hiển thị tất cả"
278
+ },
276
279
  "empty": {
277
280
  "desc": "Vui lòng tạo mô hình tùy chỉnh hoặc kéo mô hình để bắt đầu sử dụng",
278
281
  "title": "Chưa có mô hình nào khả dụng"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "添加模型",
275
275
  "disabled": "未启用",
276
+ "disabledActions": {
277
+ "showMore": "显示全部"
278
+ },
276
279
  "empty": {
277
280
  "desc": "请创建自定义模型或拉取模型后开始使用吧",
278
281
  "title": "暂无可用模型"
@@ -273,6 +273,9 @@
273
273
  "list": {
274
274
  "addNew": "新增模型",
275
275
  "disabled": "未啟用",
276
+ "disabledActions": {
277
+ "showMore": "顯示全部"
278
+ },
276
279
  "empty": {
277
280
  "desc": "請創建自定義模型或拉取模型後開始使用吧",
278
281
  "title": "暫無可用模型"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.45.9",
3
+ "version": "1.45.10",
4
4
  "description": "Lobe Chat - an open-source, high-performance chatbot 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",
@@ -236,8 +236,8 @@
236
236
  "yaml": "^2.7.0",
237
237
  "yjs": "^13.6.21",
238
238
  "zod": "^3.24.1",
239
- "zustand": "5.0.1",
240
- "zustand-utils": "^1.3.2"
239
+ "zustand": "^5.0.3",
240
+ "zustand-utils": "^2"
241
241
  },
242
242
  "devDependencies": {
243
243
  "@commitlint/cli": "^19.6.1",
@@ -12,14 +12,15 @@ import PluginTag from '../../../features/PluginTag';
12
12
  import KnowledgeTag from './KnowledgeTag';
13
13
 
14
14
  const TitleTags = memo(() => {
15
- const [model, hasKnowledge] = useAgentStore((s) => [
15
+ const [model, provider, hasKnowledge] = useAgentStore((s) => [
16
16
  agentSelectors.currentAgentModel(s),
17
+ agentSelectors.currentAgentModelProvider(s),
17
18
  agentSelectors.hasKnowledge(s),
18
19
  ]);
19
20
  const plugins = useAgentStore(agentSelectors.currentAgentPlugins, isEqual);
20
21
  const enabledKnowledge = useAgentStore(agentSelectors.currentEnabledKnowledge, isEqual);
21
22
 
22
- const showPlugin = useModelSupportToolUse(model);
23
+ const showPlugin = useModelSupportToolUse(model, provider);
23
24
 
24
25
  return (
25
26
  <Flexbox align={'center'} horizontal>
@@ -1,6 +1,8 @@
1
- import { Typography } from 'antd';
1
+ import { Icon } from '@lobehub/ui';
2
+ import { Button, Typography } from 'antd';
2
3
  import isEqual from 'fast-deep-equal';
3
- import { memo } from 'react';
4
+ import { ChevronDown } from 'lucide-react';
5
+ import { memo, useState } from 'react';
4
6
  import { useTranslation } from 'react-i18next';
5
7
  import { Flexbox } from 'react-layout-kit';
6
8
 
@@ -12,16 +14,32 @@ import ModelItem from './ModelItem';
12
14
  const DisabledModels = memo(() => {
13
15
  const { t } = useTranslation('modelProvider');
14
16
 
17
+ const [showMore, setShowMore] = useState(false);
15
18
  const disabledModels = useAiInfraStore(aiModelSelectors.disabledAiProviderModelList, isEqual);
16
19
 
20
+ const displayModels = showMore ? disabledModels : disabledModels.slice(0, 10);
17
21
  return (
18
22
  <Flexbox>
19
23
  <Typography.Text style={{ fontSize: 12, marginTop: 8 }} type={'secondary'}>
20
24
  {t('providerModels.list.disabled')}
21
25
  </Typography.Text>
22
- {disabledModels.map((item) => (
26
+ {displayModels.map((item) => (
23
27
  <ModelItem {...item} key={item.id} />
24
28
  ))}
29
+ {!showMore && (
30
+ <Button
31
+ block
32
+ color={'default'}
33
+ icon={<Icon icon={ChevronDown} />}
34
+ onClick={() => {
35
+ setShowMore(true);
36
+ }}
37
+ size={'small'}
38
+ variant={'filled'}
39
+ >
40
+ {t('providerModels.list.disabledActions.showMore')}
41
+ </Button>
42
+ )}
25
43
  </Flexbox>
26
44
  );
27
45
  });
@@ -6,6 +6,7 @@ import { memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  import { Center, Flexbox } from 'react-layout-kit';
8
8
 
9
+ import { useModelContextWindowTokens } from '@/hooks/useModelContextWindowTokens';
9
10
  import { useModelSupportToolUse } from '@/hooks/useModelSupportToolUse';
10
11
  import { useTokenCount } from '@/hooks/useTokenCount';
11
12
  import { useAgentStore } from '@/store/agent';
@@ -14,8 +15,6 @@ import { useChatStore } from '@/store/chat';
14
15
  import { topicSelectors } from '@/store/chat/selectors';
15
16
  import { useToolStore } from '@/store/tool';
16
17
  import { toolSelectors } from '@/store/tool/selectors';
17
- import { useUserStore } from '@/store/user';
18
- import { modelProviderSelectors } from '@/store/user/selectors';
19
18
 
20
19
  import TokenProgress from './TokenProgress';
21
20
 
@@ -31,22 +30,23 @@ const Token = memo<TokenTagProps>(({ total: messageString }) => {
31
30
  topicSelectors.currentActiveTopicSummary(s)?.content || '',
32
31
  ]);
33
32
 
34
- const [systemRole, model] = useAgentStore((s) => {
33
+ const [systemRole, model, provider] = useAgentStore((s) => {
35
34
  const config = agentSelectors.currentAgentChatConfig(s);
36
35
 
37
36
  return [
38
37
  agentSelectors.currentAgentSystemRole(s),
39
38
  agentSelectors.currentAgentModel(s) as string,
39
+ agentSelectors.currentAgentModelProvider(s) as string,
40
40
  // add these two params to enable the component to re-render
41
41
  config.historyCount,
42
42
  config.enableHistoryCount,
43
43
  ];
44
44
  });
45
45
 
46
- const maxTokens = useUserStore(modelProviderSelectors.modelMaxToken(model));
46
+ const maxTokens = useModelContextWindowTokens(model, provider);
47
47
 
48
48
  // Tool usage token
49
- const canUseTool = useModelSupportToolUse(model);
49
+ const canUseTool = useModelSupportToolUse(model, provider);
50
50
  const plugins = useAgentStore(agentSelectors.currentAgentPlugins);
51
51
  const toolsString = useToolStore((s) => {
52
52
  const pluginSystemRoles = toolSelectors.enabledSystemRoles(plugins)(s);
@@ -1,21 +1,18 @@
1
1
  import dynamic from 'next/dynamic';
2
2
  import { PropsWithChildren, memo } from 'react';
3
3
 
4
- import { useAgentStore } from '@/store/agent';
5
- import { agentSelectors } from '@/store/agent/selectors';
4
+ import { useModelHasContextWindowToken } from '@/hooks/useModelHasContextWindowToken';
6
5
  import { useChatStore } from '@/store/chat';
7
6
  import { chatSelectors, threadSelectors } from '@/store/chat/selectors';
8
- import { useUserStore } from '@/store/user';
9
- import { modelProviderSelectors } from '@/store/user/selectors';
10
7
 
11
8
  const LargeTokenContent = dynamic(() => import('./TokenTag'), { ssr: false });
12
9
 
13
10
  const Token = memo<PropsWithChildren>(({ children }) => {
14
- const model = useAgentStore(agentSelectors.currentAgentModel);
15
- const showTag = useUserStore(modelProviderSelectors.isModelHasMaxToken(model));
11
+ const showTag = useModelHasContextWindowToken();
16
12
 
17
13
  return showTag && children;
18
14
  });
15
+
19
16
  export const MainToken = memo(() => {
20
17
  const total = useChatStore(chatSelectors.mainAIChatsMessageString);
21
18
 
@@ -15,7 +15,9 @@ const Tools = memo(() => {
15
15
  const { enablePlugins } = useServerConfigStore(featureFlagsSelectors);
16
16
 
17
17
  const model = useAgentStore(agentSelectors.currentAgentModel);
18
- const enableFC = useModelSupportToolUse(model);
18
+ const provider = useAgentStore(agentSelectors.currentAgentModelProvider);
19
+
20
+ const enableFC = useModelSupportToolUse(model, provider);
19
21
 
20
22
  return (
21
23
  enablePlugins && (
@@ -25,8 +25,9 @@ const FileUpload = memo(() => {
25
25
  const upload = useFileStore((s) => s.uploadChatFiles);
26
26
 
27
27
  const model = useAgentStore(agentSelectors.currentAgentModel);
28
+ const provider = useAgentStore(agentSelectors.currentAgentModelProvider);
28
29
 
29
- const canUploadImage = useModelSupportVision(model);
30
+ const canUploadImage = useModelSupportVision(model, provider);
30
31
 
31
32
  const items: MenuProps['items'] = [
32
33
  {
@@ -1,18 +1,18 @@
1
1
  import { memo } from 'react';
2
2
 
3
3
  import DragUpload from '@/components/DragUpload';
4
+ import { useModelSupportVision } from '@/hooks/useModelSupportVision';
4
5
  import { useAgentStore } from '@/store/agent';
5
6
  import { agentSelectors } from '@/store/agent/slices/chat';
6
7
  import { useFileStore } from '@/store/file';
7
- import { useUserStore } from '@/store/user';
8
- import { modelProviderSelectors } from '@/store/user/selectors';
9
8
 
10
9
  import FileItemList from './FileList';
11
10
 
12
11
  const FilePreview = memo(() => {
13
12
  const model = useAgentStore(agentSelectors.currentAgentModel);
13
+ const provider = useAgentStore(agentSelectors.currentAgentModelProvider);
14
14
 
15
- const canUploadImage = useUserStore(modelProviderSelectors.isModelEnabledUpload(model));
15
+ const canUploadImage = useModelSupportVision(model, provider);
16
16
 
17
17
  const [uploadFiles] = useFileStore((s) => [s.uploadChatFiles]);
18
18
 
@@ -0,0 +1,15 @@
1
+ import { isServerMode } from '@/const/version';
2
+ import { aiModelSelectors, useAiInfraStore } from '@/store/aiInfra';
3
+ import { useUserStore } from '@/store/user';
4
+ import { modelProviderSelectors } from '@/store/user/selectors';
5
+
6
+ export const useModelContextWindowTokens = (model: string, provider: string) => {
7
+ const newValue = useAiInfraStore(aiModelSelectors.modelContextWindowTokens(model, provider));
8
+
9
+ // TODO: remove this in V2.0
10
+ const oldValue = useUserStore(modelProviderSelectors.modelMaxToken(model));
11
+ if (!isServerMode) return oldValue;
12
+ //
13
+
14
+ return newValue as number;
15
+ };
@@ -0,0 +1,19 @@
1
+ import { isServerMode } from '@/const/version';
2
+ import { useAgentStore } from '@/store/agent';
3
+ import { agentSelectors } from '@/store/agent/slices/chat';
4
+ import { aiModelSelectors, useAiInfraStore } from '@/store/aiInfra';
5
+ import { useUserStore } from '@/store/user';
6
+ import { modelProviderSelectors } from '@/store/user/selectors';
7
+
8
+ export const useModelHasContextWindowToken = () => {
9
+ const model = useAgentStore(agentSelectors.currentAgentModel);
10
+ const provider = useAgentStore(agentSelectors.currentAgentModelProvider);
11
+ const newValue = useAiInfraStore(aiModelSelectors.isModelHasContextWindowToken(model, provider));
12
+
13
+ // TODO: remove this in V2.0
14
+ const oldValue = useUserStore(modelProviderSelectors.isModelHasMaxToken(model));
15
+ if (!isServerMode) return oldValue;
16
+ //
17
+
18
+ return newValue;
19
+ };
@@ -3,8 +3,8 @@ import { aiModelSelectors, useAiInfraStore } from '@/store/aiInfra';
3
3
  import { useUserStore } from '@/store/user';
4
4
  import { modelProviderSelectors } from '@/store/user/selectors';
5
5
 
6
- export const useModelSupportToolUse = (model: string) => {
7
- const newValue = useAiInfraStore(aiModelSelectors.isModelSupportToolUse(model));
6
+ export const useModelSupportToolUse = (model: string, provider: string) => {
7
+ const newValue = useAiInfraStore(aiModelSelectors.isModelSupportToolUse(model, provider));
8
8
 
9
9
  // TODO: remove this in V2.0
10
10
  const oldValue = useUserStore(modelProviderSelectors.isModelEnabledFunctionCall(model));
@@ -3,8 +3,8 @@ import { aiModelSelectors, useAiInfraStore } from '@/store/aiInfra';
3
3
  import { useUserStore } from '@/store/user';
4
4
  import { modelProviderSelectors } from '@/store/user/selectors';
5
5
 
6
- export const useModelSupportVision = (model: string) => {
7
- const newValue = useAiInfraStore(aiModelSelectors.isModelSupportVision(model));
6
+ export const useModelSupportVision = (model: string, provider: string) => {
7
+ const newValue = useAiInfraStore(aiModelSelectors.isModelSupportVision(model, provider));
8
8
 
9
9
  // TODO: remove this in V2.0
10
10
  const oldValue = useUserStore(modelProviderSelectors.isModelEnabledVision(model));
@@ -278,6 +278,7 @@ export default {
278
278
  list: {
279
279
  addNew: '添加模型',
280
280
  disabled: '未启用',
281
+ disabledActions: { showMore: '显示全部' },
281
282
  empty: {
282
283
  desc: '请创建自定义模型或拉取模型后开始使用吧',
283
284
  title: '暂无可用模型',
@@ -797,6 +797,7 @@ describe('ChatService', () => {
797
797
  const output = chatService['processMessages']({
798
798
  messages,
799
799
  model: 'gpt-4o',
800
+ provider: 'openai',
800
801
  });
801
802
 
802
803
  expect(output).toEqual([
@@ -40,13 +40,13 @@ import { createTraceHeader, getTraceId } from '@/utils/trace';
40
40
  import { createHeaderWithAuth, createPayloadWithKeyVaults } from './_auth';
41
41
  import { API_ENDPOINTS } from './_url';
42
42
 
43
- const isCanUseFC = (model: string) => {
43
+ const isCanUseFC = (model: string, provider: string) => {
44
44
  // TODO: remove isDeprecatedEdition condition in V2.0
45
45
  if (!isServerMode) {
46
46
  return modelProviderSelectors.isModelEnabledFunctionCall(model)(useUserStore.getState());
47
47
  }
48
48
 
49
- return aiModelSelectors.isModelSupportToolUse(model)(useAiInfraStore.getState());
49
+ return aiModelSelectors.isModelSupportToolUse(model, provider)(useAiInfraStore.getState());
50
50
  };
51
51
 
52
52
  const findAzureDeploymentName = (model: string) => {
@@ -232,6 +232,7 @@ class ChatService {
232
232
  {
233
233
  messages,
234
234
  model: payload.model,
235
+ provider: payload.provider!,
235
236
  tools: enabledPlugins,
236
237
  },
237
238
  options,
@@ -242,7 +243,7 @@ class ChatService {
242
243
  const filterTools = toolSelectors.enabledSchema(enabledPlugins)(useToolStore.getState());
243
244
 
244
245
  // check this model can use function call
245
- const canUseFC = isCanUseFC(payload.model);
246
+ const canUseFC = isCanUseFC(payload.model, payload.provider!);
246
247
 
247
248
  // the rule that model can use tools:
248
249
  // 1. tools is not empty
@@ -440,9 +441,11 @@ class ChatService {
440
441
  messages,
441
442
  tools,
442
443
  model,
444
+ provider,
443
445
  }: {
444
446
  messages: ChatMessage[];
445
447
  model: string;
448
+ provider: string;
446
449
  tools?: string[];
447
450
  },
448
451
  options?: FetchOptions,
@@ -513,7 +516,7 @@ class ChatService {
513
516
 
514
517
  // Inject Tool SystemRole
515
518
  const hasTools = tools && tools?.length > 0;
516
- const hasFC = hasTools && isCanUseFC(model);
519
+ const hasFC = hasTools && isCanUseFC(model, provider);
517
520
  const toolsSystemRoles =
518
521
  hasFC && toolSelectors.enabledSystemRoles(tools)(useToolStore.getState());
519
522
 
@@ -33,21 +33,34 @@ const isModelLoading = (id: string) => (s: AIProviderStoreState) =>
33
33
  const getAiModelById = (id: string) => (s: AIProviderStoreState) =>
34
34
  s.aiProviderModelList.find((i) => i.id === id);
35
35
 
36
- const getEnabledModelById = (id: string) => (s: AIProviderStoreState) =>
37
- s.enabledAiModels?.find((i) => i.id === id);
36
+ const getEnabledModelById = (id: string, provider: string) => (s: AIProviderStoreState) =>
37
+ s.enabledAiModels?.find((i) => i.id === id && (provider ? provider === i.providerId : true));
38
38
 
39
- const isModelSupportToolUse = (id: string) => (s: AIProviderStoreState) => {
40
- const model = getEnabledModelById(id)(s);
39
+ const isModelSupportToolUse = (id: string, provider: string) => (s: AIProviderStoreState) => {
40
+ const model = getEnabledModelById(id, provider)(s);
41
41
 
42
42
  return model?.abilities?.functionCall;
43
43
  };
44
44
 
45
- const isModelSupportVision = (id: string) => (s: AIProviderStoreState) => {
46
- const model = getEnabledModelById(id)(s);
45
+ const isModelSupportVision = (id: string, provider: string) => (s: AIProviderStoreState) => {
46
+ const model = getEnabledModelById(id, provider)(s);
47
47
 
48
48
  return model?.abilities?.vision;
49
49
  };
50
50
 
51
+ const isModelHasContextWindowToken =
52
+ (id: string, provider: string) => (s: AIProviderStoreState) => {
53
+ const model = getEnabledModelById(id, provider)(s);
54
+
55
+ return typeof model?.contextWindowTokens === 'number';
56
+ };
57
+
58
+ const modelContextWindowTokens = (id: string, provider: string) => (s: AIProviderStoreState) => {
59
+ const model = getEnabledModelById(id, provider)(s);
60
+
61
+ return model?.contextWindowTokens;
62
+ };
63
+
51
64
  export const aiModelSelectors = {
52
65
  disabledAiProviderModelList,
53
66
  enabledAiProviderModelList,
@@ -56,8 +69,10 @@ export const aiModelSelectors = {
56
69
  hasRemoteModels,
57
70
  isEmptyAiProviderModelList,
58
71
  isModelEnabled,
72
+ isModelHasContextWindowToken,
59
73
  isModelLoading,
60
74
  isModelSupportToolUse,
61
75
  isModelSupportVision,
76
+ modelContextWindowTokens,
62
77
  totalAiProviderModelList,
63
78
  };
@@ -283,8 +283,8 @@ export const UpdateAiModelSchema = z.object({
283
283
  deploymentName: z.string().optional(),
284
284
  })
285
285
  .optional(),
286
- contextWindowTokens: z.number().optional(),
287
- displayName: z.string().optional(),
286
+ contextWindowTokens: z.number().nullable().optional(),
287
+ displayName: z.string().nullable().optional(),
288
288
  });
289
289
 
290
290
  export type UpdateAiModelParams = z.infer<typeof UpdateAiModelSchema>;