@lobehub/chat 1.43.6 → 1.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/docs/self-hosting/server-database/docker-compose.mdx +2 -2
- package/locales/ar/common.json +1 -0
- package/locales/ar/modelProvider.json +176 -0
- package/locales/ar/setting.json +1 -0
- package/locales/bg-BG/common.json +1 -0
- package/locales/bg-BG/modelProvider.json +176 -0
- package/locales/bg-BG/setting.json +1 -0
- package/locales/de-DE/common.json +1 -0
- package/locales/de-DE/modelProvider.json +176 -0
- package/locales/de-DE/setting.json +1 -0
- package/locales/en-US/common.json +1 -0
- package/locales/en-US/modelProvider.json +176 -0
- package/locales/en-US/setting.json +1 -0
- package/locales/es-ES/common.json +1 -0
- package/locales/es-ES/modelProvider.json +176 -0
- package/locales/es-ES/setting.json +1 -0
- package/locales/fa-IR/common.json +1 -0
- package/locales/fa-IR/modelProvider.json +176 -0
- package/locales/fa-IR/setting.json +1 -0
- package/locales/fr-FR/common.json +1 -0
- package/locales/fr-FR/modelProvider.json +176 -0
- package/locales/fr-FR/setting.json +1 -0
- package/locales/it-IT/common.json +1 -0
- package/locales/it-IT/modelProvider.json +176 -0
- package/locales/it-IT/setting.json +1 -0
- package/locales/ja-JP/common.json +1 -0
- package/locales/ja-JP/modelProvider.json +176 -0
- package/locales/ja-JP/setting.json +1 -0
- package/locales/ko-KR/common.json +1 -0
- package/locales/ko-KR/modelProvider.json +176 -0
- package/locales/ko-KR/setting.json +1 -0
- package/locales/nl-NL/common.json +1 -0
- package/locales/nl-NL/modelProvider.json +176 -0
- package/locales/nl-NL/setting.json +1 -0
- package/locales/pl-PL/common.json +1 -0
- package/locales/pl-PL/modelProvider.json +176 -0
- package/locales/pl-PL/setting.json +1 -0
- package/locales/pt-BR/common.json +1 -0
- package/locales/pt-BR/modelProvider.json +176 -0
- package/locales/pt-BR/setting.json +1 -0
- package/locales/ru-RU/common.json +1 -0
- package/locales/ru-RU/modelProvider.json +176 -0
- package/locales/ru-RU/setting.json +1 -0
- package/locales/tr-TR/common.json +1 -0
- package/locales/tr-TR/modelProvider.json +176 -0
- package/locales/tr-TR/setting.json +1 -0
- package/locales/vi-VN/common.json +1 -0
- package/locales/vi-VN/modelProvider.json +176 -0
- package/locales/vi-VN/setting.json +1 -0
- package/locales/zh-CN/common.json +1 -0
- package/locales/zh-CN/modelProvider.json +176 -0
- package/locales/zh-CN/setting.json +1 -0
- package/locales/zh-TW/common.json +1 -0
- package/locales/zh-TW/modelProvider.json +176 -0
- package/locales/zh-TW/setting.json +1 -0
- package/package.json +4 -4
- package/src/app/(main)/(mobile)/me/settings/features/Category.tsx +1 -1
- package/src/app/(main)/(mobile)/me/settings/features/useCategory.tsx +12 -5
- package/src/app/(main)/changelog/features/VersionTag.tsx +1 -2
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatList/ChatItem/Thread.tsx +1 -1
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatList/ChatItem/ThreadItem.tsx +1 -2
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatList/ChatItem/index.tsx +0 -1
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/InboxWelcome/AgentsSuggest.tsx +1 -1
- package/src/app/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/InboxWelcome/QuestionSuggest.tsx +1 -1
- package/src/app/(main)/chat/(workspace)/@conversation/features/ZenModeToast/Toast.tsx +1 -1
- package/src/app/(main)/chat/(workspace)/@topic/features/TopicListContent/ThreadItem/index.tsx +0 -2
- package/src/app/(main)/chat/(workspace)/@topic/features/TopicListContent/TopicItem/index.tsx +0 -1
- package/src/app/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/Tags.tsx +2 -3
- package/src/app/(main)/chat/@session/features/SessionListContent/CollapseGroup/index.tsx +1 -1
- package/src/app/(main)/chat/features/Migration/Start.tsx +1 -1
- package/src/app/(main)/discover/(detail)/assistant/[slug]/features/ConversationExample/TopicList.tsx +4 -3
- package/src/app/(main)/discover/(detail)/assistant/[slug]/features/Header.tsx +1 -1
- package/src/app/(main)/discover/(detail)/features/ShareButton.tsx +2 -1
- package/src/app/(main)/discover/(detail)/model/[...slugs]/features/Header.tsx +1 -1
- package/src/app/(main)/discover/(detail)/plugin/[slug]/features/Header.tsx +1 -1
- package/src/app/(main)/discover/(detail)/provider/[slug]/features/Header.tsx +1 -1
- package/src/app/(main)/discover/(list)/_layout/Desktop/Nav.tsx +0 -1
- package/src/app/(main)/discover/(list)/assistants/features/Card.tsx +1 -1
- package/src/app/(main)/discover/(list)/models/features/Card.tsx +1 -1
- package/src/app/(main)/discover/(list)/plugins/features/Card.tsx +1 -1
- package/src/app/(main)/discover/(list)/providers/features/Card.tsx +1 -1
- package/src/app/(main)/discover/components/GridLoadingCard.tsx +2 -1
- package/src/app/(main)/discover/components/Title.tsx +1 -1
- package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/EmptyStatus.tsx +1 -1
- package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/Item/index.tsx +0 -1
- package/src/app/(main)/files/(content)/@modal/(.)[id]/FullscreenModal.tsx +2 -2
- package/src/app/(main)/files/(content)/NotSupportClient.tsx +2 -2
- package/src/app/(main)/profile/_layout/Desktop/SideBar.tsx +1 -1
- package/src/app/(main)/profile/stats/features/ShareButton/Preview.tsx +5 -5
- package/src/app/(main)/repos/[id]/evals/components/Container.tsx +1 -1
- package/src/app/(main)/repos/[id]/evals/dataset/DatasetList/Item.tsx +0 -1
- package/src/app/(main)/settings/_layout/Desktop/SideBar.tsx +1 -1
- package/src/app/(main)/settings/about/features/ItemCard.tsx +3 -3
- package/src/app/(main)/settings/about/features/Version.tsx +1 -1
- package/src/app/(main)/settings/hooks/useCategory.tsx +22 -9
- package/src/app/(main)/settings/llm/components/ProviderConfig/index.tsx +2 -1
- package/src/app/(main)/settings/llm/components/ProviderModelList/ModelFetcher.tsx +0 -1
- package/src/app/(main)/settings/provider/(detail)/[id]/index.tsx +19 -0
- package/src/app/(main)/settings/provider/(detail)/[id]/page.tsx +95 -0
- package/src/app/(main)/settings/provider/(detail)/azure/page.tsx +119 -0
- package/src/app/(main)/settings/provider/(detail)/bedrock/page.tsx +91 -0
- package/src/app/(main)/settings/provider/(detail)/cloudflare/page.tsx +58 -0
- package/src/app/(main)/settings/provider/(detail)/github/page.tsx +67 -0
- package/src/app/(main)/settings/provider/(detail)/huggingface/page.tsx +67 -0
- package/src/app/(main)/settings/provider/(detail)/ollama/Checker.tsx +73 -0
- package/src/app/(main)/settings/provider/(detail)/ollama/page.tsx +34 -0
- package/src/app/(main)/settings/provider/(detail)/openai/page.tsx +23 -0
- package/src/app/(main)/settings/provider/(detail)/wenxin/page.tsx +61 -0
- package/src/app/(main)/settings/provider/(list)/Footer.tsx +36 -0
- package/src/app/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +134 -0
- package/src/app/(main)/settings/provider/(list)/ProviderGrid/index.tsx +91 -0
- package/src/app/(main)/settings/provider/(list)/index.tsx +19 -0
- package/src/app/(main)/settings/provider/ProviderMenu/AddNew.tsx +28 -0
- package/src/app/(main)/settings/provider/ProviderMenu/All.tsx +29 -0
- package/src/app/(main)/settings/provider/ProviderMenu/Item.tsx +69 -0
- package/src/app/(main)/settings/provider/ProviderMenu/List.tsx +76 -0
- package/src/app/(main)/settings/provider/ProviderMenu/SearchResult.tsx +43 -0
- package/src/app/(main)/settings/provider/ProviderMenu/SkeletonList.tsx +60 -0
- package/src/app/(main)/settings/provider/ProviderMenu/SortProviderModal/GroupItem.tsx +30 -0
- package/src/app/(main)/settings/provider/ProviderMenu/SortProviderModal/index.tsx +91 -0
- package/src/app/(main)/settings/provider/ProviderMenu/index.tsx +80 -0
- package/src/app/(main)/settings/provider/_layout/Desktop.tsx +37 -0
- package/src/app/(main)/settings/provider/_layout/Mobile.tsx +14 -0
- package/src/app/(main)/settings/provider/const.ts +20 -0
- package/src/app/(main)/settings/provider/features/CreateNewProvider/index.tsx +146 -0
- package/src/app/(main)/settings/provider/features/ModelList/CreateNewModelModal/Form.tsx +105 -0
- package/src/app/(main)/settings/provider/features/ModelList/CreateNewModelModal/index.tsx +69 -0
- package/src/app/(main)/settings/provider/features/ModelList/DisabledModels.tsx +29 -0
- package/src/app/(main)/settings/provider/features/ModelList/EmptyModels.tsx +101 -0
- package/src/app/(main)/settings/provider/features/ModelList/EnabledModelList/index.tsx +85 -0
- package/src/app/(main)/settings/provider/features/ModelList/ModelConfigModal/Form.tsx +109 -0
- package/src/app/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx +76 -0
- package/src/app/(main)/settings/provider/features/ModelList/ModelItem.tsx +346 -0
- package/src/app/(main)/settings/provider/features/ModelList/ModelTitle/Search.tsx +37 -0
- package/src/app/(main)/settings/provider/features/ModelList/ModelTitle/index.tsx +145 -0
- package/src/app/(main)/settings/provider/features/ModelList/SearchResult.tsx +67 -0
- package/src/app/(main)/settings/provider/features/ModelList/SkeletonList.tsx +63 -0
- package/src/app/(main)/settings/provider/features/ModelList/SortModelModal/ListItem.tsx +20 -0
- package/src/app/(main)/settings/provider/features/ModelList/SortModelModal/index.tsx +96 -0
- package/src/app/(main)/settings/provider/features/ModelList/index.tsx +59 -0
- package/src/app/(main)/settings/provider/features/ProviderConfig/Checker.tsx +120 -0
- package/src/app/(main)/settings/provider/features/ProviderConfig/SkeletonInput.tsx +5 -0
- package/src/app/(main)/settings/provider/features/ProviderConfig/UpdateProviderInfo/SettingModal.tsx +137 -0
- package/src/app/(main)/settings/provider/features/ProviderConfig/UpdateProviderInfo/index.tsx +49 -0
- package/src/app/(main)/settings/provider/features/ProviderConfig/index.tsx +343 -0
- package/src/app/(main)/settings/provider/layout.tsx +21 -0
- package/src/app/(main)/settings/provider/page.tsx +17 -0
- package/src/app/(main)/settings/provider/type.ts +5 -0
- package/src/app/(main)/settings/sync/features/DeviceInfo/Card.tsx +1 -1
- package/src/app/(main)/settings/sync/features/DeviceInfo/index.tsx +1 -1
- package/src/app/@modal/(.)changelog/modal/features/ReadDetail.tsx +1 -1
- package/src/app/@modal/(.)changelog/modal/features/VersionTag.tsx +1 -2
- package/src/app/@modal/(.)changelog/modal/layout.tsx +1 -1
- package/src/components/Cell/index.tsx +1 -1
- package/src/components/DragUpload/index.tsx +2 -3
- package/src/components/FeatureList/index.tsx +1 -1
- package/src/components/FileParsingStatus/EmbeddingStatus.tsx +1 -1
- package/src/components/FileParsingStatus/index.tsx +1 -1
- package/src/components/FunctionModal/style.tsx +2 -2
- package/src/components/GoBack/index.tsx +1 -2
- package/src/components/HotKeys/index.tsx +1 -1
- package/src/components/InstantSwitch/index.tsx +28 -0
- package/src/components/Menu/index.tsx +1 -1
- package/src/components/ModelSelect/index.tsx +2 -3
- package/src/components/Notification/index.tsx +2 -1
- package/src/components/StatisticCard/index.tsx +5 -6
- package/src/config/aiModels/ai21.ts +38 -0
- package/src/config/aiModels/ai360.ts +71 -0
- package/src/config/aiModels/anthropic.ts +152 -0
- package/src/config/aiModels/azure.ts +86 -0
- package/src/config/aiModels/baichuan.ts +107 -0
- package/src/config/aiModels/bedrock.ts +315 -0
- package/src/config/aiModels/cloudflare.ts +88 -0
- package/src/config/aiModels/deepseek.ts +27 -0
- package/src/config/aiModels/fireworksai.ts +232 -0
- package/src/config/aiModels/giteeai.ts +137 -0
- package/src/config/aiModels/github.ts +273 -0
- package/src/config/aiModels/google.ts +317 -0
- package/src/config/aiModels/groq.ts +202 -0
- package/src/config/aiModels/higress.ts +2828 -0
- package/src/config/aiModels/huggingface.ts +56 -0
- package/src/config/aiModels/hunyuan.ts +151 -0
- package/src/config/aiModels/index.ts +98 -0
- package/src/config/aiModels/internlm.ts +40 -0
- package/src/config/aiModels/minimax.ts +55 -0
- package/src/config/aiModels/mistral.ts +172 -0
- package/src/config/aiModels/moonshot.ts +44 -0
- package/src/config/aiModels/novita.ts +124 -0
- package/src/config/aiModels/ollama.ts +412 -0
- package/src/config/aiModels/openai.ts +537 -0
- package/src/config/aiModels/openrouter.ts +252 -0
- package/src/config/aiModels/perplexity.ts +67 -0
- package/src/config/aiModels/qwen.ts +302 -0
- package/src/config/aiModels/sensenova.ts +114 -0
- package/src/config/aiModels/siliconcloud.ts +679 -0
- package/src/config/aiModels/spark.ts +68 -0
- package/src/config/aiModels/stepfun.ts +153 -0
- package/src/config/aiModels/taichu.ts +19 -0
- package/src/config/aiModels/togetherai.ts +334 -0
- package/src/config/aiModels/upstage.ts +37 -0
- package/src/config/aiModels/wenxin.ts +171 -0
- package/src/config/aiModels/xai.ts +72 -0
- package/src/config/aiModels/zeroone.ts +156 -0
- package/src/config/aiModels/zhipu.ts +235 -0
- package/src/config/featureFlags/schema.ts +3 -0
- package/src/config/modelProviders/anthropic.ts +1 -0
- package/src/config/modelProviders/github.ts +0 -1
- package/src/config/modelProviders/google.ts +1 -0
- package/src/config/modelProviders/stepfun.ts +2 -0
- package/src/database/migrations/0013_add_ai_infra.sql +44 -0
- package/src/database/migrations/meta/0013_snapshot.json +3598 -0
- package/src/database/migrations/meta/_journal.json +7 -0
- package/src/database/repositories/aiInfra/index.ts +115 -0
- package/src/database/schemas/aiInfra.ts +69 -0
- package/src/database/schemas/index.ts +1 -0
- package/src/database/server/models/__tests__/aiModel.test.ts +318 -0
- package/src/database/server/models/__tests__/aiProvider.test.ts +373 -0
- package/src/database/server/models/aiModel.ts +250 -0
- package/src/database/server/models/aiProvider.ts +234 -0
- package/src/features/AgentSetting/AgentPrompt/index.tsx +2 -2
- package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +2 -1
- package/src/features/ChatInput/ActionBar/Tools/index.tsx +2 -3
- package/src/features/ChatInput/ActionBar/Upload/ServerMode.tsx +2 -3
- package/src/features/ChatInput/Desktop/FilePreview/FileItem/index.tsx +3 -2
- package/src/features/ChatInput/Desktop/FilePreview/FileList.tsx +2 -2
- package/src/features/ChatInput/Mobile/Files/FileItem/File.tsx +2 -2
- package/src/features/ChatInput/Mobile/InputArea/index.tsx +1 -1
- package/src/features/ChatInput/STT/common.tsx +1 -1
- package/src/features/Conversation/Error/style.tsx +2 -2
- package/src/features/Conversation/Messages/Assistant/FileChunks/Item/style.ts +2 -2
- package/src/features/Conversation/Messages/Assistant/FileChunks/index.tsx +1 -1
- package/src/features/Conversation/Messages/Assistant/ToolCallItem/Inspector/style.ts +2 -3
- package/src/features/Conversation/Messages/Assistant/ToolCallItem/style.ts +2 -3
- package/src/features/Conversation/Messages/User/FileListViewer/Item.tsx +0 -1
- package/src/features/Conversation/components/BackBottom/style.ts +2 -2
- package/src/features/Conversation/components/MarkdownElements/LobeArtifact/Render/Icon.tsx +2 -3
- package/src/features/Conversation/components/MarkdownElements/LobeArtifact/Render/index.tsx +3 -3
- package/src/features/Conversation/components/MarkdownElements/LobeThinking/Render.tsx +1 -1
- package/src/features/Conversation/components/OTPInput.tsx +2 -2
- package/src/features/DataImporter/Loading.tsx +1 -1
- package/src/features/FileManager/FileList/EmptyStatus.tsx +1 -1
- package/src/features/FileManager/FileList/index.tsx +1 -1
- package/src/features/FileManager/UploadDock/Item.tsx +1 -1
- package/src/features/FileManager/UploadDock/index.tsx +4 -4
- package/src/features/FileViewer/NotSupport/index.tsx +1 -1
- package/src/features/FileViewer/Renderer/MSDoc/index.tsx +0 -1
- package/src/features/FileViewer/Renderer/TXT/index.tsx +1 -1
- package/src/features/InitClientDB/EnableModal.tsx +1 -1
- package/src/features/InitClientDB/ErrorResult.tsx +1 -1
- package/src/features/InitClientDB/InitIndicator.tsx +1 -1
- package/src/features/KnowledgeBaseModal/AddFilesToKnowledgeBase/SelectForm.tsx +0 -1
- package/src/features/ModelSwitchPanel/index.tsx +2 -2
- package/src/features/PluginsUI/Render/Loading.tsx +0 -1
- package/src/features/Portal/Home/Body/Files/FileList/Item.tsx +1 -1
- package/src/features/Portal/Home/Body/Plugins/ArtifactList/Item/style.ts +1 -2
- package/src/features/Setting/SettingContainer.tsx +8 -1
- package/src/features/ShareModal/ShareImage/style.ts +2 -2
- package/src/features/ShareModal/style.ts +2 -2
- package/src/features/User/DataStatistics.tsx +1 -1
- package/src/hooks/useEnabledChatModels.ts +10 -1
- package/src/hooks/useModelSupportToolUse.ts +15 -0
- package/src/hooks/useModelSupportVision.ts +15 -0
- package/src/layout/AuthProvider/Clerk/useAppearance.ts +3 -3
- package/src/layout/GlobalProvider/AppTheme.tsx +1 -1
- package/src/layout/GlobalProvider/StoreInitialization.tsx +5 -0
- package/src/locales/default/common.ts +1 -0
- package/src/locales/default/modelProvider.ts +178 -0
- package/src/locales/default/setting.ts +1 -0
- package/src/server/modules/KeyVaultsEncrypt/index.ts +1 -1
- package/src/server/routers/lambda/aiModel.ts +128 -0
- package/src/server/routers/lambda/aiProvider.ts +127 -0
- package/src/server/routers/lambda/index.ts +4 -0
- package/src/services/__tests__/_auth.test.ts +16 -49
- package/src/services/__tests__/chat.test.ts +2 -0
- package/src/services/_auth.ts +42 -25
- package/src/services/aiModel.ts +52 -0
- package/src/services/aiProvider.ts +47 -0
- package/src/services/chat.ts +62 -18
- package/src/store/aiInfra/index.ts +2 -0
- package/src/store/aiInfra/initialState.ts +11 -0
- package/src/store/aiInfra/selectors.ts +2 -0
- package/src/store/aiInfra/slices/aiModel/action.ts +146 -0
- package/src/store/aiInfra/slices/aiModel/index.ts +3 -0
- package/src/store/aiInfra/slices/aiModel/initialState.ts +14 -0
- package/src/store/aiInfra/slices/aiModel/selectors.ts +63 -0
- package/src/store/aiInfra/slices/aiProvider/action.ts +208 -0
- package/src/store/aiInfra/slices/aiProvider/index.ts +3 -0
- package/src/store/aiInfra/slices/aiProvider/initialState.ts +32 -0
- package/src/store/aiInfra/slices/aiProvider/selectors.ts +99 -0
- package/src/store/aiInfra/store.ts +25 -0
- package/src/store/global/initialState.ts +1 -0
- package/src/store/serverConfig/selectors.test.ts +1 -0
- package/src/styles/global.ts +1 -1
- package/src/types/aiModel.ts +32 -6
- package/src/types/aiProvider.ts +11 -4
- package/src/utils/fetch/fetchSSE.ts +3 -1
@@ -0,0 +1,146 @@
|
|
1
|
+
import isEqual from 'fast-deep-equal';
|
2
|
+
import { SWRResponse, mutate } from 'swr';
|
3
|
+
import { StateCreator } from 'zustand/vanilla';
|
4
|
+
|
5
|
+
import { useClientDataSWR } from '@/libs/swr';
|
6
|
+
import { aiModelService } from '@/services/aiModel';
|
7
|
+
import { AiInfraStore } from '@/store/aiInfra/store';
|
8
|
+
import {
|
9
|
+
AiModelSortMap,
|
10
|
+
AiProviderModelListItem,
|
11
|
+
CreateAiModelParams,
|
12
|
+
ToggleAiModelEnableParams,
|
13
|
+
} from '@/types/aiModel';
|
14
|
+
|
15
|
+
const FETCH_AI_PROVIDER_MODEL_LIST_KEY = 'FETCH_AI_PROVIDER_MODELS';
|
16
|
+
|
17
|
+
export interface AiModelAction {
|
18
|
+
batchToggleAiModels: (ids: string[], enabled: boolean) => Promise<void>;
|
19
|
+
batchUpdateAiModels: (models: AiProviderModelListItem[]) => Promise<void>;
|
20
|
+
clearRemoteModels: (provider: string) => Promise<void>;
|
21
|
+
createNewAiModel: (params: CreateAiModelParams) => Promise<void>;
|
22
|
+
fetchRemoteModelList: (providerId: string) => Promise<void>;
|
23
|
+
internal_toggleAiModelLoading: (id: string, loading: boolean) => void;
|
24
|
+
|
25
|
+
refreshAiModelList: () => Promise<void>;
|
26
|
+
removeAiModel: (id: string, providerId: string) => Promise<void>;
|
27
|
+
toggleModelEnabled: (params: Omit<ToggleAiModelEnableParams, 'providerId'>) => Promise<void>;
|
28
|
+
updateAiModelsConfig: (
|
29
|
+
id: string,
|
30
|
+
providerId: string,
|
31
|
+
data: Partial<AiProviderModelListItem>,
|
32
|
+
) => Promise<void>;
|
33
|
+
updateAiModelsSort: (providerId: string, items: AiModelSortMap[]) => Promise<void>;
|
34
|
+
|
35
|
+
useFetchAiProviderModels: (id: string) => SWRResponse<AiProviderModelListItem[]>;
|
36
|
+
}
|
37
|
+
|
38
|
+
export const createAiModelSlice: StateCreator<
|
39
|
+
AiInfraStore,
|
40
|
+
[['zustand/devtools', never]],
|
41
|
+
[],
|
42
|
+
AiModelAction
|
43
|
+
> = (set, get) => ({
|
44
|
+
batchToggleAiModels: async (ids, enabled) => {
|
45
|
+
const { activeAiProvider } = get();
|
46
|
+
if (!activeAiProvider) return;
|
47
|
+
|
48
|
+
await aiModelService.batchToggleAiModels(activeAiProvider, ids, enabled);
|
49
|
+
await get().refreshAiModelList();
|
50
|
+
},
|
51
|
+
batchUpdateAiModels: async (models) => {
|
52
|
+
const { activeAiProvider: id } = get();
|
53
|
+
if (!id) return;
|
54
|
+
|
55
|
+
await aiModelService.batchUpdateAiModels(id, models);
|
56
|
+
await get().refreshAiModelList();
|
57
|
+
},
|
58
|
+
clearRemoteModels: async (provider) => {
|
59
|
+
await aiModelService.clearRemoteModels(provider);
|
60
|
+
await get().refreshAiModelList();
|
61
|
+
},
|
62
|
+
createNewAiModel: async (data) => {
|
63
|
+
await aiModelService.createAiModel(data);
|
64
|
+
await get().refreshAiModelList();
|
65
|
+
},
|
66
|
+
fetchRemoteModelList: async (providerId) => {
|
67
|
+
const { modelsService } = await import('@/services/models');
|
68
|
+
|
69
|
+
const data = await modelsService.getChatModels(providerId);
|
70
|
+
if (data) {
|
71
|
+
await get().batchUpdateAiModels(
|
72
|
+
data.map((model) => ({
|
73
|
+
...model,
|
74
|
+
abilities: {
|
75
|
+
files: model.files,
|
76
|
+
functionCall: model.functionCall,
|
77
|
+
vision: model.vision,
|
78
|
+
},
|
79
|
+
enabled: model.enabled || false,
|
80
|
+
source: 'remote',
|
81
|
+
type: 'chat',
|
82
|
+
})),
|
83
|
+
);
|
84
|
+
|
85
|
+
await get().refreshAiModelList();
|
86
|
+
}
|
87
|
+
},
|
88
|
+
internal_toggleAiModelLoading: (id, loading) => {
|
89
|
+
set(
|
90
|
+
(state) => {
|
91
|
+
if (loading) return { aiModelLoadingIds: [...state.aiModelLoadingIds, id] };
|
92
|
+
|
93
|
+
return { aiModelLoadingIds: state.aiModelLoadingIds.filter((i) => i !== id) };
|
94
|
+
},
|
95
|
+
false,
|
96
|
+
'toggleAiModelLoading',
|
97
|
+
);
|
98
|
+
},
|
99
|
+
refreshAiModelList: async () => {
|
100
|
+
await mutate([FETCH_AI_PROVIDER_MODEL_LIST_KEY, get().activeAiProvider]);
|
101
|
+
// make refresh provide runtime state async, not block
|
102
|
+
get().refreshAiProviderRuntimeState();
|
103
|
+
},
|
104
|
+
removeAiModel: async (id, providerId) => {
|
105
|
+
await aiModelService.deleteAiModel({ id, providerId });
|
106
|
+
await get().refreshAiModelList();
|
107
|
+
},
|
108
|
+
toggleModelEnabled: async (params) => {
|
109
|
+
const { activeAiProvider } = get();
|
110
|
+
if (!activeAiProvider) return;
|
111
|
+
|
112
|
+
get().internal_toggleAiModelLoading(params.id, true);
|
113
|
+
|
114
|
+
await aiModelService.toggleModelEnabled({ ...params, providerId: activeAiProvider });
|
115
|
+
await get().refreshAiModelList();
|
116
|
+
|
117
|
+
get().internal_toggleAiModelLoading(params.id, false);
|
118
|
+
},
|
119
|
+
|
120
|
+
updateAiModelsConfig: async (id, providerId, data) => {
|
121
|
+
await aiModelService.updateAiModel(id, providerId, data);
|
122
|
+
await get().refreshAiModelList();
|
123
|
+
},
|
124
|
+
updateAiModelsSort: async (id, items) => {
|
125
|
+
await aiModelService.updateAiModelOrder(id, items);
|
126
|
+
await get().refreshAiModelList();
|
127
|
+
},
|
128
|
+
|
129
|
+
useFetchAiProviderModels: (id) =>
|
130
|
+
useClientDataSWR<AiProviderModelListItem[]>(
|
131
|
+
[FETCH_AI_PROVIDER_MODEL_LIST_KEY, id],
|
132
|
+
([, id]) => aiModelService.getAiProviderModelList(id as string),
|
133
|
+
{
|
134
|
+
onSuccess: (data) => {
|
135
|
+
// no need to update list if the list have been init and data is the same
|
136
|
+
if (get().isAiModelListInit && isEqual(data, get().aiProviderModelList)) return;
|
137
|
+
|
138
|
+
set(
|
139
|
+
{ aiProviderModelList: data, isAiModelListInit: true },
|
140
|
+
false,
|
141
|
+
`useFetchAiProviderModels/${id}`,
|
142
|
+
);
|
143
|
+
},
|
144
|
+
},
|
145
|
+
),
|
146
|
+
});
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { AiProviderModelListItem } from '@/types/aiModel';
|
2
|
+
|
3
|
+
export interface AIModelsState {
|
4
|
+
aiModelLoadingIds: string[];
|
5
|
+
aiProviderModelList: AiProviderModelListItem[];
|
6
|
+
isAiModelListInit?: boolean;
|
7
|
+
modelSearchKeyword: string;
|
8
|
+
}
|
9
|
+
|
10
|
+
export const initialAIModelState: AIModelsState = {
|
11
|
+
aiModelLoadingIds: [],
|
12
|
+
aiProviderModelList: [],
|
13
|
+
modelSearchKeyword: '',
|
14
|
+
};
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import { AIProviderStoreState } from '@/store/aiInfra/initialState';
|
2
|
+
import { AiModelSourceEnum } from '@/types/aiModel';
|
3
|
+
|
4
|
+
// List
|
5
|
+
const enabledAiProviderModelList = (s: AIProviderStoreState) =>
|
6
|
+
s.aiProviderModelList.filter((item) => item.enabled);
|
7
|
+
|
8
|
+
const disabledAiProviderModelList = (s: AIProviderStoreState) =>
|
9
|
+
s.aiProviderModelList.filter((item) => !item.enabled);
|
10
|
+
|
11
|
+
const filteredAiProviderModelList = (s: AIProviderStoreState) => {
|
12
|
+
const keyword = s.modelSearchKeyword.toLowerCase().trim();
|
13
|
+
|
14
|
+
return s.aiProviderModelList.filter(
|
15
|
+
(model) =>
|
16
|
+
model.id.toLowerCase().includes(keyword) ||
|
17
|
+
model.displayName?.toLowerCase().includes(keyword),
|
18
|
+
);
|
19
|
+
};
|
20
|
+
|
21
|
+
const totalAiProviderModelList = (s: AIProviderStoreState) => s.aiProviderModelList.length;
|
22
|
+
const isEmptyAiProviderModelList = (s: AIProviderStoreState) => totalAiProviderModelList(s) === 0;
|
23
|
+
|
24
|
+
const hasRemoteModels = (s: AIProviderStoreState) =>
|
25
|
+
s.aiProviderModelList.some((m) => m.source === AiModelSourceEnum.Remote);
|
26
|
+
|
27
|
+
const isModelEnabled = (id: string) => (s: AIProviderStoreState) =>
|
28
|
+
enabledAiProviderModelList(s).some((i) => i.id === id);
|
29
|
+
|
30
|
+
const isModelLoading = (id: string) => (s: AIProviderStoreState) =>
|
31
|
+
s.aiModelLoadingIds.includes(id);
|
32
|
+
|
33
|
+
const getAiModelById = (id: string) => (s: AIProviderStoreState) =>
|
34
|
+
s.aiProviderModelList.find((i) => i.id === id);
|
35
|
+
|
36
|
+
const getEnabledModelById = (id: string) => (s: AIProviderStoreState) =>
|
37
|
+
s.enabledAiModels?.find((i) => i.id === id);
|
38
|
+
|
39
|
+
const isModelSupportToolUse = (id: string) => (s: AIProviderStoreState) => {
|
40
|
+
const model = getEnabledModelById(id)(s);
|
41
|
+
|
42
|
+
return model?.abilities?.functionCall;
|
43
|
+
};
|
44
|
+
|
45
|
+
const isModelSupportVision = (id: string) => (s: AIProviderStoreState) => {
|
46
|
+
const model = getEnabledModelById(id)(s);
|
47
|
+
|
48
|
+
return model?.abilities?.vision;
|
49
|
+
};
|
50
|
+
|
51
|
+
export const aiModelSelectors = {
|
52
|
+
disabledAiProviderModelList,
|
53
|
+
enabledAiProviderModelList,
|
54
|
+
filteredAiProviderModelList,
|
55
|
+
getAiModelById,
|
56
|
+
hasRemoteModels,
|
57
|
+
isEmptyAiProviderModelList,
|
58
|
+
isModelEnabled,
|
59
|
+
isModelLoading,
|
60
|
+
isModelSupportToolUse,
|
61
|
+
isModelSupportVision,
|
62
|
+
totalAiProviderModelList,
|
63
|
+
};
|
@@ -0,0 +1,208 @@
|
|
1
|
+
import { uniqBy } from 'lodash-es';
|
2
|
+
import { SWRResponse, mutate } from 'swr';
|
3
|
+
import { StateCreator } from 'zustand/vanilla';
|
4
|
+
|
5
|
+
import { DEFAULT_MODEL_PROVIDER_LIST } from '@/config/modelProviders';
|
6
|
+
import { isServerMode } from '@/const/version';
|
7
|
+
import { useClientDataSWR } from '@/libs/swr';
|
8
|
+
import { aiProviderService } from '@/services/aiProvider';
|
9
|
+
import { AiInfraStore } from '@/store/aiInfra/store';
|
10
|
+
import { ModelAbilities } from '@/types/aiModel';
|
11
|
+
import {
|
12
|
+
AiProviderDetailItem,
|
13
|
+
AiProviderListItem,
|
14
|
+
AiProviderRuntimeState,
|
15
|
+
AiProviderSortMap,
|
16
|
+
AiProviderSourceEnum,
|
17
|
+
CreateAiProviderParams,
|
18
|
+
UpdateAiProviderConfigParams,
|
19
|
+
UpdateAiProviderParams,
|
20
|
+
} from '@/types/aiProvider';
|
21
|
+
|
22
|
+
enum AiProviderSwrKey {
|
23
|
+
fetchAiProviderItem = 'FETCH_AI_PROVIDER_ITEM',
|
24
|
+
fetchAiProviderList = 'FETCH_AI_PROVIDER',
|
25
|
+
fetchAiProviderRuntimeState = 'FETCH_AI_PROVIDER_RUNTIME_STATE',
|
26
|
+
}
|
27
|
+
|
28
|
+
export interface AiProviderAction {
|
29
|
+
createNewAiProvider: (params: CreateAiProviderParams) => Promise<void>;
|
30
|
+
deleteAiProvider: (id: string) => Promise<void>;
|
31
|
+
internal_toggleAiProviderLoading: (id: string, loading: boolean) => void;
|
32
|
+
refreshAiProviderDetail: () => Promise<void>;
|
33
|
+
refreshAiProviderList: () => Promise<void>;
|
34
|
+
refreshAiProviderRuntimeState: () => Promise<void>;
|
35
|
+
removeAiProvider: (id: string) => Promise<void>;
|
36
|
+
toggleProviderEnabled: (id: string, enabled: boolean) => Promise<void>;
|
37
|
+
updateAiProvider: (id: string, value: UpdateAiProviderParams) => Promise<void>;
|
38
|
+
updateAiProviderConfig: (id: string, value: UpdateAiProviderConfigParams) => Promise<void>;
|
39
|
+
updateAiProviderSort: (items: AiProviderSortMap[]) => Promise<void>;
|
40
|
+
|
41
|
+
useFetchAiProviderItem: (id: string) => SWRResponse<AiProviderDetailItem | undefined>;
|
42
|
+
useFetchAiProviderList: (params?: { suspense?: boolean }) => SWRResponse<AiProviderListItem[]>;
|
43
|
+
/**
|
44
|
+
* fetch provider keyVaults and user enabled model list
|
45
|
+
* @param isLoginOnInit
|
46
|
+
*/
|
47
|
+
useFetchAiProviderRuntimeState: (
|
48
|
+
isLoginOnInit: boolean | undefined,
|
49
|
+
) => SWRResponse<AiProviderRuntimeState | undefined>;
|
50
|
+
}
|
51
|
+
|
52
|
+
export const createAiProviderSlice: StateCreator<
|
53
|
+
AiInfraStore,
|
54
|
+
[['zustand/devtools', never]],
|
55
|
+
[],
|
56
|
+
AiProviderAction
|
57
|
+
> = (set, get) => ({
|
58
|
+
createNewAiProvider: async (params) => {
|
59
|
+
await aiProviderService.createAiProvider({ ...params, source: AiProviderSourceEnum.Custom });
|
60
|
+
await get().refreshAiProviderList();
|
61
|
+
},
|
62
|
+
deleteAiProvider: async (id: string) => {
|
63
|
+
await aiProviderService.deleteAiProvider(id);
|
64
|
+
|
65
|
+
await get().refreshAiProviderList();
|
66
|
+
},
|
67
|
+
internal_toggleAiProviderLoading: (id, loading) => {
|
68
|
+
set(
|
69
|
+
(state) => {
|
70
|
+
if (loading) return { aiProviderLoadingIds: [...state.aiProviderLoadingIds, id] };
|
71
|
+
|
72
|
+
return { aiProviderLoadingIds: state.aiProviderLoadingIds.filter((i) => i !== id) };
|
73
|
+
},
|
74
|
+
false,
|
75
|
+
'toggleAiProviderLoading',
|
76
|
+
);
|
77
|
+
},
|
78
|
+
refreshAiProviderDetail: async () => {
|
79
|
+
await mutate([AiProviderSwrKey.fetchAiProviderItem, get().activeAiProvider]);
|
80
|
+
await get().refreshAiProviderRuntimeState();
|
81
|
+
},
|
82
|
+
refreshAiProviderList: async () => {
|
83
|
+
await mutate(AiProviderSwrKey.fetchAiProviderList);
|
84
|
+
await get().refreshAiProviderRuntimeState();
|
85
|
+
},
|
86
|
+
refreshAiProviderRuntimeState: async () => {
|
87
|
+
await mutate(AiProviderSwrKey.fetchAiProviderRuntimeState);
|
88
|
+
},
|
89
|
+
removeAiProvider: async (id) => {
|
90
|
+
await aiProviderService.deleteAiProvider(id);
|
91
|
+
await get().refreshAiProviderList();
|
92
|
+
},
|
93
|
+
|
94
|
+
toggleProviderEnabled: async (id: string, enabled: boolean) => {
|
95
|
+
get().internal_toggleAiProviderLoading(id, true);
|
96
|
+
await aiProviderService.toggleProviderEnabled(id, enabled);
|
97
|
+
await get().refreshAiProviderList();
|
98
|
+
|
99
|
+
get().internal_toggleAiProviderLoading(id, false);
|
100
|
+
},
|
101
|
+
|
102
|
+
updateAiProvider: async (id, value) => {
|
103
|
+
get().internal_toggleAiProviderLoading(id, true);
|
104
|
+
await aiProviderService.updateAiProvider(id, value);
|
105
|
+
await get().refreshAiProviderList();
|
106
|
+
await get().refreshAiProviderDetail();
|
107
|
+
|
108
|
+
get().internal_toggleAiProviderLoading(id, false);
|
109
|
+
},
|
110
|
+
|
111
|
+
updateAiProviderConfig: async (id, value) => {
|
112
|
+
get().internal_toggleAiProviderLoading(id, true);
|
113
|
+
await aiProviderService.updateAiProviderConfig(id, value);
|
114
|
+
await get().refreshAiProviderDetail();
|
115
|
+
|
116
|
+
get().internal_toggleAiProviderLoading(id, false);
|
117
|
+
},
|
118
|
+
|
119
|
+
updateAiProviderSort: async (items) => {
|
120
|
+
await aiProviderService.updateAiProviderOrder(items);
|
121
|
+
await get().refreshAiProviderList();
|
122
|
+
},
|
123
|
+
useFetchAiProviderItem: (id) =>
|
124
|
+
useClientDataSWR<AiProviderDetailItem | undefined>(
|
125
|
+
[AiProviderSwrKey.fetchAiProviderItem, id],
|
126
|
+
() => aiProviderService.getAiProviderById(id),
|
127
|
+
{
|
128
|
+
onSuccess: (data) => {
|
129
|
+
if (!data) return;
|
130
|
+
|
131
|
+
set({ activeAiProvider: id, aiProviderDetail: data }, false, 'useFetchAiProviderItem');
|
132
|
+
},
|
133
|
+
},
|
134
|
+
),
|
135
|
+
useFetchAiProviderList: () =>
|
136
|
+
useClientDataSWR<AiProviderListItem[]>(
|
137
|
+
AiProviderSwrKey.fetchAiProviderList,
|
138
|
+
() => aiProviderService.getAiProviderList(),
|
139
|
+
{
|
140
|
+
fallbackData: [],
|
141
|
+
onSuccess: (data) => {
|
142
|
+
if (!get().initAiProviderList) {
|
143
|
+
set(
|
144
|
+
{ aiProviderList: data, initAiProviderList: true },
|
145
|
+
false,
|
146
|
+
'useFetchAiProviderList/init',
|
147
|
+
);
|
148
|
+
return;
|
149
|
+
}
|
150
|
+
|
151
|
+
set({ aiProviderList: data }, false, 'useFetchAiProviderList/refresh');
|
152
|
+
},
|
153
|
+
},
|
154
|
+
),
|
155
|
+
|
156
|
+
useFetchAiProviderRuntimeState: (isLogin) =>
|
157
|
+
useClientDataSWR<AiProviderRuntimeState | undefined>(
|
158
|
+
isServerMode ? [AiProviderSwrKey.fetchAiProviderRuntimeState, isLogin] : null,
|
159
|
+
async ([, isLogin]) => {
|
160
|
+
if (isLogin) return aiProviderService.getAiProviderRuntimeState();
|
161
|
+
|
162
|
+
const { LOBE_DEFAULT_MODEL_LIST } = await import('@/config/aiModels');
|
163
|
+
return {
|
164
|
+
enabledAiModels: LOBE_DEFAULT_MODEL_LIST.filter((m) => m.enabled),
|
165
|
+
enabledAiProviders: DEFAULT_MODEL_PROVIDER_LIST.filter(
|
166
|
+
(provider) => provider.enabled,
|
167
|
+
).map((item) => ({ id: item.id, name: item.name, source: 'builtin' })),
|
168
|
+
runtimeConfig: {},
|
169
|
+
};
|
170
|
+
},
|
171
|
+
{
|
172
|
+
onSuccess: (data) => {
|
173
|
+
if (!data) return;
|
174
|
+
|
175
|
+
const getModelListByType = (providerId: string, type: string) => {
|
176
|
+
const models = data.enabledAiModels
|
177
|
+
.filter((model) => model.providerId === providerId && model.type === type)
|
178
|
+
.map((model) => ({
|
179
|
+
abilities: (model.abilities || {}) as ModelAbilities,
|
180
|
+
contextWindowTokens: model.contextWindowTokens,
|
181
|
+
displayName: model.displayName ?? '',
|
182
|
+
id: model.id,
|
183
|
+
}));
|
184
|
+
|
185
|
+
return uniqBy(models, 'id');
|
186
|
+
};
|
187
|
+
|
188
|
+
// 3. 组装最终数据结构
|
189
|
+
const enabledChatModelList = data.enabledAiProviders.map((provider) => ({
|
190
|
+
children: getModelListByType(provider.id, 'chat'),
|
191
|
+
id: provider.id,
|
192
|
+
name: provider.name || provider.id,
|
193
|
+
}));
|
194
|
+
|
195
|
+
set(
|
196
|
+
{
|
197
|
+
aiProviderRuntimeConfig: data.runtimeConfig,
|
198
|
+
enabledAiModels: data.enabledAiModels,
|
199
|
+
enabledAiProviders: data.enabledAiProviders,
|
200
|
+
enabledChatModelList,
|
201
|
+
},
|
202
|
+
false,
|
203
|
+
'useInitAiProviderKeyVaults',
|
204
|
+
);
|
205
|
+
},
|
206
|
+
},
|
207
|
+
),
|
208
|
+
});
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import { EnabledProviderWithModels } from '@/types/aiModel';
|
2
|
+
import {
|
3
|
+
AiProviderDetailItem,
|
4
|
+
AiProviderListItem,
|
5
|
+
AiProviderRuntimeConfig,
|
6
|
+
EnabledAiModel,
|
7
|
+
EnabledProvider,
|
8
|
+
} from '@/types/aiProvider';
|
9
|
+
|
10
|
+
export interface AIProviderState {
|
11
|
+
activeAiProvider?: string;
|
12
|
+
activeProviderModelList: any[];
|
13
|
+
aiProviderDetail?: AiProviderDetailItem | null;
|
14
|
+
aiProviderList: AiProviderListItem[];
|
15
|
+
aiProviderLoadingIds: string[];
|
16
|
+
aiProviderRuntimeConfig: Record<string, AiProviderRuntimeConfig>;
|
17
|
+
enabledAiModels?: EnabledAiModel[];
|
18
|
+
enabledAiProviders?: EnabledProvider[];
|
19
|
+
// used for select
|
20
|
+
enabledChatModelList?: EnabledProviderWithModels[];
|
21
|
+
initAiProviderList: boolean;
|
22
|
+
providerSearchKeyword: string;
|
23
|
+
}
|
24
|
+
|
25
|
+
export const initialAIProviderState: AIProviderState = {
|
26
|
+
activeProviderModelList: [],
|
27
|
+
aiProviderList: [],
|
28
|
+
aiProviderLoadingIds: [],
|
29
|
+
aiProviderRuntimeConfig: {},
|
30
|
+
initAiProviderList: false,
|
31
|
+
providerSearchKeyword: '',
|
32
|
+
};
|
@@ -0,0 +1,99 @@
|
|
1
|
+
import { isProviderDisableBroswerRequest } from '@/config/modelProviders';
|
2
|
+
import { AIProviderStoreState } from '@/store/aiInfra/initialState';
|
3
|
+
import { AiProviderRuntimeConfig } from '@/types/aiProvider';
|
4
|
+
import { GlobalLLMProviderKey } from '@/types/user/settings';
|
5
|
+
|
6
|
+
// List
|
7
|
+
const enabledAiProviderList = (s: AIProviderStoreState) =>
|
8
|
+
s.aiProviderList.filter((item) => item.enabled).sort((a, b) => a.sort! - b.sort!);
|
9
|
+
|
10
|
+
const disabledAiProviderList = (s: AIProviderStoreState) =>
|
11
|
+
s.aiProviderList.filter((item) => !item.enabled);
|
12
|
+
|
13
|
+
const isProviderEnabled = (id: string) => (s: AIProviderStoreState) =>
|
14
|
+
enabledAiProviderList(s).some((i) => i.id === id);
|
15
|
+
|
16
|
+
const isProviderLoading = (id: string) => (s: AIProviderStoreState) =>
|
17
|
+
s.aiProviderLoadingIds.includes(id);
|
18
|
+
|
19
|
+
const activeProviderConfig = (s: AIProviderStoreState) => s.aiProviderDetail;
|
20
|
+
|
21
|
+
// Detail
|
22
|
+
|
23
|
+
const isAiProviderConfigLoading = (id: string) => (s: AIProviderStoreState) =>
|
24
|
+
s.activeAiProvider !== id;
|
25
|
+
|
26
|
+
const providerWhitelist = new Set(['ollama']);
|
27
|
+
|
28
|
+
const activeProviderKeyVaults = (s: AIProviderStoreState) => activeProviderConfig(s)?.keyVaults;
|
29
|
+
|
30
|
+
const isActiveProviderEndpointNotEmpty = (s: AIProviderStoreState) => {
|
31
|
+
const vault = activeProviderKeyVaults(s);
|
32
|
+
return !!vault?.baseURL || !!vault?.endpoint;
|
33
|
+
};
|
34
|
+
|
35
|
+
const isActiveProviderApiKeyNotEmpty = (s: AIProviderStoreState) => {
|
36
|
+
const vault = activeProviderKeyVaults(s);
|
37
|
+
return !!vault?.apiKey || !!vault?.accessKeyId || !!vault?.secretAccessKey;
|
38
|
+
};
|
39
|
+
|
40
|
+
/**
|
41
|
+
* @description The conditions to enable client fetch
|
42
|
+
* 1. If no baseUrl and apikey input, force on Server.
|
43
|
+
* 2. If only contains baseUrl, force on Client
|
44
|
+
* 3. Follow the user settings.
|
45
|
+
* 4. On Server, by default.
|
46
|
+
*/
|
47
|
+
const isProviderFetchOnClient =
|
48
|
+
(provider: GlobalLLMProviderKey | string) => (s: AIProviderStoreState) => {
|
49
|
+
const config = activeProviderConfig(s);
|
50
|
+
|
51
|
+
// If the provider already disable broswer request in model config, force on Server.
|
52
|
+
if (isProviderDisableBroswerRequest(provider)) return false;
|
53
|
+
|
54
|
+
// If the provider in the whitelist, follow the user settings
|
55
|
+
if (providerWhitelist.has(provider) && typeof config?.fetchOnClient !== 'undefined')
|
56
|
+
return config?.fetchOnClient;
|
57
|
+
|
58
|
+
// 1. If no baseUrl and apikey input, force on Server.
|
59
|
+
const isProviderEndpointNotEmpty = isActiveProviderEndpointNotEmpty(s);
|
60
|
+
const isProviderApiKeyNotEmpty = isActiveProviderApiKeyNotEmpty(s);
|
61
|
+
if (!isProviderEndpointNotEmpty && !isProviderApiKeyNotEmpty) return false;
|
62
|
+
|
63
|
+
// 2. If only contains baseUrl, force on Client
|
64
|
+
if (isProviderEndpointNotEmpty && !isProviderApiKeyNotEmpty) return true;
|
65
|
+
|
66
|
+
// 3. Follow the user settings.
|
67
|
+
if (typeof config?.fetchOnClient !== 'undefined') return config?.fetchOnClient;
|
68
|
+
|
69
|
+
// 4. On Server, by default.
|
70
|
+
return false;
|
71
|
+
};
|
72
|
+
|
73
|
+
const providerKeyVaults = (provider: string | undefined) => (s: AIProviderStoreState) => {
|
74
|
+
if (!provider) return undefined;
|
75
|
+
|
76
|
+
return s.aiProviderRuntimeConfig?.[provider]?.keyVaults;
|
77
|
+
};
|
78
|
+
|
79
|
+
const providerConfigById =
|
80
|
+
(id: string) =>
|
81
|
+
(s: AIProviderStoreState): AiProviderRuntimeConfig | undefined => {
|
82
|
+
if (!id) return undefined;
|
83
|
+
|
84
|
+
return s.aiProviderRuntimeConfig?.[id];
|
85
|
+
};
|
86
|
+
|
87
|
+
export const aiProviderSelectors = {
|
88
|
+
activeProviderConfig,
|
89
|
+
disabledAiProviderList,
|
90
|
+
enabledAiProviderList,
|
91
|
+
isActiveProviderApiKeyNotEmpty,
|
92
|
+
isActiveProviderEndpointNotEmpty,
|
93
|
+
isAiProviderConfigLoading,
|
94
|
+
isProviderEnabled,
|
95
|
+
isProviderFetchOnClient,
|
96
|
+
isProviderLoading,
|
97
|
+
providerConfigById,
|
98
|
+
providerKeyVaults,
|
99
|
+
};
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { shallow } from 'zustand/shallow';
|
2
|
+
import { createWithEqualityFn } from 'zustand/traditional';
|
3
|
+
import { StateCreator } from 'zustand/vanilla';
|
4
|
+
|
5
|
+
import { createDevtools } from '../middleware/createDevtools';
|
6
|
+
import { AIProviderStoreState, initialState } from './initialState';
|
7
|
+
import { AiModelAction, createAiModelSlice } from './slices/aiModel';
|
8
|
+
import { AiProviderAction, createAiProviderSlice } from './slices/aiProvider';
|
9
|
+
|
10
|
+
// =============== 聚合 createStoreFn ============ //
|
11
|
+
|
12
|
+
export interface AiInfraStore extends AIProviderStoreState, AiProviderAction, AiModelAction {
|
13
|
+
/* empty */
|
14
|
+
}
|
15
|
+
|
16
|
+
const createStore: StateCreator<AiInfraStore, [['zustand/devtools', never]]> = (...parameters) => ({
|
17
|
+
...initialState,
|
18
|
+
...createAiModelSlice(...parameters),
|
19
|
+
...createAiProviderSlice(...parameters),
|
20
|
+
});
|
21
|
+
|
22
|
+
// =============== 实装 useStore ============ //
|
23
|
+
const devtools = createDevtools('aiInfra');
|
24
|
+
|
25
|
+
export const useAiInfraStore = createWithEqualityFn<AiInfraStore>()(devtools(createStore), shallow);
|
package/src/styles/global.ts
CHANGED
@@ -36,9 +36,9 @@ export default ({ token }: { prefixCls: string; token: Theme }) => css`
|
|
36
36
|
}
|
37
37
|
|
38
38
|
:hover::-webkit-scrollbar-thumb {
|
39
|
+
border: 3px solid transparent;
|
39
40
|
background-color: ${token.colorText};
|
40
41
|
background-clip: content-box;
|
41
|
-
border: 3px solid transparent;
|
42
42
|
}
|
43
43
|
|
44
44
|
::-webkit-scrollbar-track {
|