@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.
Files changed (298) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/changelog/v1.json +9 -0
  3. package/docs/self-hosting/server-database/docker-compose.mdx +2 -2
  4. package/locales/ar/common.json +1 -0
  5. package/locales/ar/modelProvider.json +176 -0
  6. package/locales/ar/setting.json +1 -0
  7. package/locales/bg-BG/common.json +1 -0
  8. package/locales/bg-BG/modelProvider.json +176 -0
  9. package/locales/bg-BG/setting.json +1 -0
  10. package/locales/de-DE/common.json +1 -0
  11. package/locales/de-DE/modelProvider.json +176 -0
  12. package/locales/de-DE/setting.json +1 -0
  13. package/locales/en-US/common.json +1 -0
  14. package/locales/en-US/modelProvider.json +176 -0
  15. package/locales/en-US/setting.json +1 -0
  16. package/locales/es-ES/common.json +1 -0
  17. package/locales/es-ES/modelProvider.json +176 -0
  18. package/locales/es-ES/setting.json +1 -0
  19. package/locales/fa-IR/common.json +1 -0
  20. package/locales/fa-IR/modelProvider.json +176 -0
  21. package/locales/fa-IR/setting.json +1 -0
  22. package/locales/fr-FR/common.json +1 -0
  23. package/locales/fr-FR/modelProvider.json +176 -0
  24. package/locales/fr-FR/setting.json +1 -0
  25. package/locales/it-IT/common.json +1 -0
  26. package/locales/it-IT/modelProvider.json +176 -0
  27. package/locales/it-IT/setting.json +1 -0
  28. package/locales/ja-JP/common.json +1 -0
  29. package/locales/ja-JP/modelProvider.json +176 -0
  30. package/locales/ja-JP/setting.json +1 -0
  31. package/locales/ko-KR/common.json +1 -0
  32. package/locales/ko-KR/modelProvider.json +176 -0
  33. package/locales/ko-KR/setting.json +1 -0
  34. package/locales/nl-NL/common.json +1 -0
  35. package/locales/nl-NL/modelProvider.json +176 -0
  36. package/locales/nl-NL/setting.json +1 -0
  37. package/locales/pl-PL/common.json +1 -0
  38. package/locales/pl-PL/modelProvider.json +176 -0
  39. package/locales/pl-PL/setting.json +1 -0
  40. package/locales/pt-BR/common.json +1 -0
  41. package/locales/pt-BR/modelProvider.json +176 -0
  42. package/locales/pt-BR/setting.json +1 -0
  43. package/locales/ru-RU/common.json +1 -0
  44. package/locales/ru-RU/modelProvider.json +176 -0
  45. package/locales/ru-RU/setting.json +1 -0
  46. package/locales/tr-TR/common.json +1 -0
  47. package/locales/tr-TR/modelProvider.json +176 -0
  48. package/locales/tr-TR/setting.json +1 -0
  49. package/locales/vi-VN/common.json +1 -0
  50. package/locales/vi-VN/modelProvider.json +176 -0
  51. package/locales/vi-VN/setting.json +1 -0
  52. package/locales/zh-CN/common.json +1 -0
  53. package/locales/zh-CN/modelProvider.json +176 -0
  54. package/locales/zh-CN/setting.json +1 -0
  55. package/locales/zh-TW/common.json +1 -0
  56. package/locales/zh-TW/modelProvider.json +176 -0
  57. package/locales/zh-TW/setting.json +1 -0
  58. package/package.json +4 -4
  59. package/src/app/(main)/(mobile)/me/settings/features/Category.tsx +1 -1
  60. package/src/app/(main)/(mobile)/me/settings/features/useCategory.tsx +12 -5
  61. package/src/app/(main)/changelog/features/VersionTag.tsx +1 -2
  62. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatList/ChatItem/Thread.tsx +1 -1
  63. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatList/ChatItem/ThreadItem.tsx +1 -2
  64. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatList/ChatItem/index.tsx +0 -1
  65. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/InboxWelcome/AgentsSuggest.tsx +1 -1
  66. package/src/app/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/InboxWelcome/QuestionSuggest.tsx +1 -1
  67. package/src/app/(main)/chat/(workspace)/@conversation/features/ZenModeToast/Toast.tsx +1 -1
  68. package/src/app/(main)/chat/(workspace)/@topic/features/TopicListContent/ThreadItem/index.tsx +0 -2
  69. package/src/app/(main)/chat/(workspace)/@topic/features/TopicListContent/TopicItem/index.tsx +0 -1
  70. package/src/app/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/Tags.tsx +2 -3
  71. package/src/app/(main)/chat/@session/features/SessionListContent/CollapseGroup/index.tsx +1 -1
  72. package/src/app/(main)/chat/features/Migration/Start.tsx +1 -1
  73. package/src/app/(main)/discover/(detail)/assistant/[slug]/features/ConversationExample/TopicList.tsx +4 -3
  74. package/src/app/(main)/discover/(detail)/assistant/[slug]/features/Header.tsx +1 -1
  75. package/src/app/(main)/discover/(detail)/features/ShareButton.tsx +2 -1
  76. package/src/app/(main)/discover/(detail)/model/[...slugs]/features/Header.tsx +1 -1
  77. package/src/app/(main)/discover/(detail)/plugin/[slug]/features/Header.tsx +1 -1
  78. package/src/app/(main)/discover/(detail)/provider/[slug]/features/Header.tsx +1 -1
  79. package/src/app/(main)/discover/(list)/_layout/Desktop/Nav.tsx +0 -1
  80. package/src/app/(main)/discover/(list)/assistants/features/Card.tsx +1 -1
  81. package/src/app/(main)/discover/(list)/models/features/Card.tsx +1 -1
  82. package/src/app/(main)/discover/(list)/plugins/features/Card.tsx +1 -1
  83. package/src/app/(main)/discover/(list)/providers/features/Card.tsx +1 -1
  84. package/src/app/(main)/discover/components/GridLoadingCard.tsx +2 -1
  85. package/src/app/(main)/discover/components/Title.tsx +1 -1
  86. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/EmptyStatus.tsx +1 -1
  87. package/src/app/(main)/files/(content)/@menu/features/KnowledgeBase/Item/index.tsx +0 -1
  88. package/src/app/(main)/files/(content)/@modal/(.)[id]/FullscreenModal.tsx +2 -2
  89. package/src/app/(main)/files/(content)/NotSupportClient.tsx +2 -2
  90. package/src/app/(main)/profile/_layout/Desktop/SideBar.tsx +1 -1
  91. package/src/app/(main)/profile/stats/features/ShareButton/Preview.tsx +5 -5
  92. package/src/app/(main)/repos/[id]/evals/components/Container.tsx +1 -1
  93. package/src/app/(main)/repos/[id]/evals/dataset/DatasetList/Item.tsx +0 -1
  94. package/src/app/(main)/settings/_layout/Desktop/SideBar.tsx +1 -1
  95. package/src/app/(main)/settings/about/features/ItemCard.tsx +3 -3
  96. package/src/app/(main)/settings/about/features/Version.tsx +1 -1
  97. package/src/app/(main)/settings/hooks/useCategory.tsx +22 -9
  98. package/src/app/(main)/settings/llm/components/ProviderConfig/index.tsx +2 -1
  99. package/src/app/(main)/settings/llm/components/ProviderModelList/ModelFetcher.tsx +0 -1
  100. package/src/app/(main)/settings/provider/(detail)/[id]/index.tsx +19 -0
  101. package/src/app/(main)/settings/provider/(detail)/[id]/page.tsx +95 -0
  102. package/src/app/(main)/settings/provider/(detail)/azure/page.tsx +119 -0
  103. package/src/app/(main)/settings/provider/(detail)/bedrock/page.tsx +91 -0
  104. package/src/app/(main)/settings/provider/(detail)/cloudflare/page.tsx +58 -0
  105. package/src/app/(main)/settings/provider/(detail)/github/page.tsx +67 -0
  106. package/src/app/(main)/settings/provider/(detail)/huggingface/page.tsx +67 -0
  107. package/src/app/(main)/settings/provider/(detail)/ollama/Checker.tsx +73 -0
  108. package/src/app/(main)/settings/provider/(detail)/ollama/page.tsx +34 -0
  109. package/src/app/(main)/settings/provider/(detail)/openai/page.tsx +23 -0
  110. package/src/app/(main)/settings/provider/(detail)/wenxin/page.tsx +61 -0
  111. package/src/app/(main)/settings/provider/(list)/Footer.tsx +36 -0
  112. package/src/app/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +134 -0
  113. package/src/app/(main)/settings/provider/(list)/ProviderGrid/index.tsx +91 -0
  114. package/src/app/(main)/settings/provider/(list)/index.tsx +19 -0
  115. package/src/app/(main)/settings/provider/ProviderMenu/AddNew.tsx +28 -0
  116. package/src/app/(main)/settings/provider/ProviderMenu/All.tsx +29 -0
  117. package/src/app/(main)/settings/provider/ProviderMenu/Item.tsx +69 -0
  118. package/src/app/(main)/settings/provider/ProviderMenu/List.tsx +76 -0
  119. package/src/app/(main)/settings/provider/ProviderMenu/SearchResult.tsx +43 -0
  120. package/src/app/(main)/settings/provider/ProviderMenu/SkeletonList.tsx +60 -0
  121. package/src/app/(main)/settings/provider/ProviderMenu/SortProviderModal/GroupItem.tsx +30 -0
  122. package/src/app/(main)/settings/provider/ProviderMenu/SortProviderModal/index.tsx +91 -0
  123. package/src/app/(main)/settings/provider/ProviderMenu/index.tsx +80 -0
  124. package/src/app/(main)/settings/provider/_layout/Desktop.tsx +37 -0
  125. package/src/app/(main)/settings/provider/_layout/Mobile.tsx +14 -0
  126. package/src/app/(main)/settings/provider/const.ts +20 -0
  127. package/src/app/(main)/settings/provider/features/CreateNewProvider/index.tsx +146 -0
  128. package/src/app/(main)/settings/provider/features/ModelList/CreateNewModelModal/Form.tsx +105 -0
  129. package/src/app/(main)/settings/provider/features/ModelList/CreateNewModelModal/index.tsx +69 -0
  130. package/src/app/(main)/settings/provider/features/ModelList/DisabledModels.tsx +29 -0
  131. package/src/app/(main)/settings/provider/features/ModelList/EmptyModels.tsx +101 -0
  132. package/src/app/(main)/settings/provider/features/ModelList/EnabledModelList/index.tsx +85 -0
  133. package/src/app/(main)/settings/provider/features/ModelList/ModelConfigModal/Form.tsx +109 -0
  134. package/src/app/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx +76 -0
  135. package/src/app/(main)/settings/provider/features/ModelList/ModelItem.tsx +346 -0
  136. package/src/app/(main)/settings/provider/features/ModelList/ModelTitle/Search.tsx +37 -0
  137. package/src/app/(main)/settings/provider/features/ModelList/ModelTitle/index.tsx +145 -0
  138. package/src/app/(main)/settings/provider/features/ModelList/SearchResult.tsx +67 -0
  139. package/src/app/(main)/settings/provider/features/ModelList/SkeletonList.tsx +63 -0
  140. package/src/app/(main)/settings/provider/features/ModelList/SortModelModal/ListItem.tsx +20 -0
  141. package/src/app/(main)/settings/provider/features/ModelList/SortModelModal/index.tsx +96 -0
  142. package/src/app/(main)/settings/provider/features/ModelList/index.tsx +59 -0
  143. package/src/app/(main)/settings/provider/features/ProviderConfig/Checker.tsx +120 -0
  144. package/src/app/(main)/settings/provider/features/ProviderConfig/SkeletonInput.tsx +5 -0
  145. package/src/app/(main)/settings/provider/features/ProviderConfig/UpdateProviderInfo/SettingModal.tsx +137 -0
  146. package/src/app/(main)/settings/provider/features/ProviderConfig/UpdateProviderInfo/index.tsx +49 -0
  147. package/src/app/(main)/settings/provider/features/ProviderConfig/index.tsx +343 -0
  148. package/src/app/(main)/settings/provider/layout.tsx +21 -0
  149. package/src/app/(main)/settings/provider/page.tsx +17 -0
  150. package/src/app/(main)/settings/provider/type.ts +5 -0
  151. package/src/app/(main)/settings/sync/features/DeviceInfo/Card.tsx +1 -1
  152. package/src/app/(main)/settings/sync/features/DeviceInfo/index.tsx +1 -1
  153. package/src/app/@modal/(.)changelog/modal/features/ReadDetail.tsx +1 -1
  154. package/src/app/@modal/(.)changelog/modal/features/VersionTag.tsx +1 -2
  155. package/src/app/@modal/(.)changelog/modal/layout.tsx +1 -1
  156. package/src/components/Cell/index.tsx +1 -1
  157. package/src/components/DragUpload/index.tsx +2 -3
  158. package/src/components/FeatureList/index.tsx +1 -1
  159. package/src/components/FileParsingStatus/EmbeddingStatus.tsx +1 -1
  160. package/src/components/FileParsingStatus/index.tsx +1 -1
  161. package/src/components/FunctionModal/style.tsx +2 -2
  162. package/src/components/GoBack/index.tsx +1 -2
  163. package/src/components/HotKeys/index.tsx +1 -1
  164. package/src/components/InstantSwitch/index.tsx +28 -0
  165. package/src/components/Menu/index.tsx +1 -1
  166. package/src/components/ModelSelect/index.tsx +2 -3
  167. package/src/components/Notification/index.tsx +2 -1
  168. package/src/components/StatisticCard/index.tsx +5 -6
  169. package/src/config/aiModels/ai21.ts +38 -0
  170. package/src/config/aiModels/ai360.ts +71 -0
  171. package/src/config/aiModels/anthropic.ts +152 -0
  172. package/src/config/aiModels/azure.ts +86 -0
  173. package/src/config/aiModels/baichuan.ts +107 -0
  174. package/src/config/aiModels/bedrock.ts +315 -0
  175. package/src/config/aiModels/cloudflare.ts +88 -0
  176. package/src/config/aiModels/deepseek.ts +27 -0
  177. package/src/config/aiModels/fireworksai.ts +232 -0
  178. package/src/config/aiModels/giteeai.ts +137 -0
  179. package/src/config/aiModels/github.ts +273 -0
  180. package/src/config/aiModels/google.ts +317 -0
  181. package/src/config/aiModels/groq.ts +202 -0
  182. package/src/config/aiModels/higress.ts +2828 -0
  183. package/src/config/aiModels/huggingface.ts +56 -0
  184. package/src/config/aiModels/hunyuan.ts +151 -0
  185. package/src/config/aiModels/index.ts +98 -0
  186. package/src/config/aiModels/internlm.ts +40 -0
  187. package/src/config/aiModels/minimax.ts +55 -0
  188. package/src/config/aiModels/mistral.ts +172 -0
  189. package/src/config/aiModels/moonshot.ts +44 -0
  190. package/src/config/aiModels/novita.ts +124 -0
  191. package/src/config/aiModels/ollama.ts +412 -0
  192. package/src/config/aiModels/openai.ts +537 -0
  193. package/src/config/aiModels/openrouter.ts +252 -0
  194. package/src/config/aiModels/perplexity.ts +67 -0
  195. package/src/config/aiModels/qwen.ts +302 -0
  196. package/src/config/aiModels/sensenova.ts +114 -0
  197. package/src/config/aiModels/siliconcloud.ts +679 -0
  198. package/src/config/aiModels/spark.ts +68 -0
  199. package/src/config/aiModels/stepfun.ts +153 -0
  200. package/src/config/aiModels/taichu.ts +19 -0
  201. package/src/config/aiModels/togetherai.ts +334 -0
  202. package/src/config/aiModels/upstage.ts +37 -0
  203. package/src/config/aiModels/wenxin.ts +171 -0
  204. package/src/config/aiModels/xai.ts +72 -0
  205. package/src/config/aiModels/zeroone.ts +156 -0
  206. package/src/config/aiModels/zhipu.ts +235 -0
  207. package/src/config/featureFlags/schema.ts +3 -0
  208. package/src/config/modelProviders/anthropic.ts +1 -0
  209. package/src/config/modelProviders/github.ts +0 -1
  210. package/src/config/modelProviders/google.ts +1 -0
  211. package/src/config/modelProviders/stepfun.ts +2 -0
  212. package/src/database/migrations/0013_add_ai_infra.sql +44 -0
  213. package/src/database/migrations/meta/0013_snapshot.json +3598 -0
  214. package/src/database/migrations/meta/_journal.json +7 -0
  215. package/src/database/repositories/aiInfra/index.ts +115 -0
  216. package/src/database/schemas/aiInfra.ts +69 -0
  217. package/src/database/schemas/index.ts +1 -0
  218. package/src/database/server/models/__tests__/aiModel.test.ts +318 -0
  219. package/src/database/server/models/__tests__/aiProvider.test.ts +373 -0
  220. package/src/database/server/models/aiModel.ts +250 -0
  221. package/src/database/server/models/aiProvider.ts +234 -0
  222. package/src/features/AgentSetting/AgentPrompt/index.tsx +2 -2
  223. package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +2 -1
  224. package/src/features/ChatInput/ActionBar/Tools/index.tsx +2 -3
  225. package/src/features/ChatInput/ActionBar/Upload/ServerMode.tsx +2 -3
  226. package/src/features/ChatInput/Desktop/FilePreview/FileItem/index.tsx +3 -2
  227. package/src/features/ChatInput/Desktop/FilePreview/FileList.tsx +2 -2
  228. package/src/features/ChatInput/Mobile/Files/FileItem/File.tsx +2 -2
  229. package/src/features/ChatInput/Mobile/InputArea/index.tsx +1 -1
  230. package/src/features/ChatInput/STT/common.tsx +1 -1
  231. package/src/features/Conversation/Error/style.tsx +2 -2
  232. package/src/features/Conversation/Messages/Assistant/FileChunks/Item/style.ts +2 -2
  233. package/src/features/Conversation/Messages/Assistant/FileChunks/index.tsx +1 -1
  234. package/src/features/Conversation/Messages/Assistant/ToolCallItem/Inspector/style.ts +2 -3
  235. package/src/features/Conversation/Messages/Assistant/ToolCallItem/style.ts +2 -3
  236. package/src/features/Conversation/Messages/User/FileListViewer/Item.tsx +0 -1
  237. package/src/features/Conversation/components/BackBottom/style.ts +2 -2
  238. package/src/features/Conversation/components/MarkdownElements/LobeArtifact/Render/Icon.tsx +2 -3
  239. package/src/features/Conversation/components/MarkdownElements/LobeArtifact/Render/index.tsx +3 -3
  240. package/src/features/Conversation/components/MarkdownElements/LobeThinking/Render.tsx +1 -1
  241. package/src/features/Conversation/components/OTPInput.tsx +2 -2
  242. package/src/features/DataImporter/Loading.tsx +1 -1
  243. package/src/features/FileManager/FileList/EmptyStatus.tsx +1 -1
  244. package/src/features/FileManager/FileList/index.tsx +1 -1
  245. package/src/features/FileManager/UploadDock/Item.tsx +1 -1
  246. package/src/features/FileManager/UploadDock/index.tsx +4 -4
  247. package/src/features/FileViewer/NotSupport/index.tsx +1 -1
  248. package/src/features/FileViewer/Renderer/MSDoc/index.tsx +0 -1
  249. package/src/features/FileViewer/Renderer/TXT/index.tsx +1 -1
  250. package/src/features/InitClientDB/EnableModal.tsx +1 -1
  251. package/src/features/InitClientDB/ErrorResult.tsx +1 -1
  252. package/src/features/InitClientDB/InitIndicator.tsx +1 -1
  253. package/src/features/KnowledgeBaseModal/AddFilesToKnowledgeBase/SelectForm.tsx +0 -1
  254. package/src/features/ModelSwitchPanel/index.tsx +2 -2
  255. package/src/features/PluginsUI/Render/Loading.tsx +0 -1
  256. package/src/features/Portal/Home/Body/Files/FileList/Item.tsx +1 -1
  257. package/src/features/Portal/Home/Body/Plugins/ArtifactList/Item/style.ts +1 -2
  258. package/src/features/Setting/SettingContainer.tsx +8 -1
  259. package/src/features/ShareModal/ShareImage/style.ts +2 -2
  260. package/src/features/ShareModal/style.ts +2 -2
  261. package/src/features/User/DataStatistics.tsx +1 -1
  262. package/src/hooks/useEnabledChatModels.ts +10 -1
  263. package/src/hooks/useModelSupportToolUse.ts +15 -0
  264. package/src/hooks/useModelSupportVision.ts +15 -0
  265. package/src/layout/AuthProvider/Clerk/useAppearance.ts +3 -3
  266. package/src/layout/GlobalProvider/AppTheme.tsx +1 -1
  267. package/src/layout/GlobalProvider/StoreInitialization.tsx +5 -0
  268. package/src/locales/default/common.ts +1 -0
  269. package/src/locales/default/modelProvider.ts +178 -0
  270. package/src/locales/default/setting.ts +1 -0
  271. package/src/server/modules/KeyVaultsEncrypt/index.ts +1 -1
  272. package/src/server/routers/lambda/aiModel.ts +128 -0
  273. package/src/server/routers/lambda/aiProvider.ts +127 -0
  274. package/src/server/routers/lambda/index.ts +4 -0
  275. package/src/services/__tests__/_auth.test.ts +16 -49
  276. package/src/services/__tests__/chat.test.ts +2 -0
  277. package/src/services/_auth.ts +42 -25
  278. package/src/services/aiModel.ts +52 -0
  279. package/src/services/aiProvider.ts +47 -0
  280. package/src/services/chat.ts +62 -18
  281. package/src/store/aiInfra/index.ts +2 -0
  282. package/src/store/aiInfra/initialState.ts +11 -0
  283. package/src/store/aiInfra/selectors.ts +2 -0
  284. package/src/store/aiInfra/slices/aiModel/action.ts +146 -0
  285. package/src/store/aiInfra/slices/aiModel/index.ts +3 -0
  286. package/src/store/aiInfra/slices/aiModel/initialState.ts +14 -0
  287. package/src/store/aiInfra/slices/aiModel/selectors.ts +63 -0
  288. package/src/store/aiInfra/slices/aiProvider/action.ts +208 -0
  289. package/src/store/aiInfra/slices/aiProvider/index.ts +3 -0
  290. package/src/store/aiInfra/slices/aiProvider/initialState.ts +32 -0
  291. package/src/store/aiInfra/slices/aiProvider/selectors.ts +99 -0
  292. package/src/store/aiInfra/store.ts +25 -0
  293. package/src/store/global/initialState.ts +1 -0
  294. package/src/store/serverConfig/selectors.test.ts +1 -0
  295. package/src/styles/global.ts +1 -1
  296. package/src/types/aiModel.ts +32 -6
  297. package/src/types/aiProvider.ts +11 -4
  298. package/src/utils/fetch/fetchSSE.ts +3 -1
@@ -0,0 +1,127 @@
1
+ import { z } from 'zod';
2
+
3
+ import { AiInfraRepos } from '@/database/repositories/aiInfra';
4
+ import { serverDB } from '@/database/server';
5
+ import { AiProviderModel } from '@/database/server/models/aiProvider';
6
+ import { UserModel } from '@/database/server/models/user';
7
+ import { authedProcedure, router } from '@/libs/trpc';
8
+ import { getServerGlobalConfig } from '@/server/globalConfig';
9
+ import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
10
+ import {
11
+ AiProviderDetailItem,
12
+ AiProviderRuntimeState,
13
+ CreateAiProviderSchema,
14
+ UpdateAiProviderConfigSchema,
15
+ } from '@/types/aiProvider';
16
+ import { ProviderConfig } from '@/types/user/settings';
17
+
18
+ const aiProviderProcedure = authedProcedure.use(async (opts) => {
19
+ const { ctx } = opts;
20
+
21
+ const { languageModel } = getServerGlobalConfig();
22
+
23
+ const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
24
+ return opts.next({
25
+ ctx: {
26
+ aiInfraRepos: new AiInfraRepos(
27
+ serverDB,
28
+ ctx.userId,
29
+ languageModel as Record<string, ProviderConfig>,
30
+ ),
31
+ aiProviderModel: new AiProviderModel(serverDB, ctx.userId),
32
+ gateKeeper,
33
+ userModel: new UserModel(serverDB, ctx.userId),
34
+ },
35
+ });
36
+ });
37
+
38
+ export const aiProviderRouter = router({
39
+ createAiProvider: aiProviderProcedure
40
+ .input(CreateAiProviderSchema)
41
+ .mutation(async ({ input, ctx }) => {
42
+ const data = await ctx.aiProviderModel.create(input, ctx.gateKeeper.encrypt);
43
+
44
+ return data?.id;
45
+ }),
46
+
47
+ getAiProviderById: aiProviderProcedure
48
+ .input(z.object({ id: z.string() }))
49
+
50
+ .query(async ({ input, ctx }): Promise<AiProviderDetailItem | undefined> => {
51
+ return ctx.aiProviderModel.getAiProviderById(input.id, KeyVaultsGateKeeper.getUserKeyVaults);
52
+ }),
53
+
54
+ getAiProviderList: aiProviderProcedure.query(async ({ ctx }) => {
55
+ return await ctx.aiInfraRepos.getAiProviderList();
56
+ }),
57
+
58
+ getAiProviderRuntimeState: aiProviderProcedure
59
+ .input(z.object({ isLogin: z.boolean().optional() }))
60
+ .query(async ({ ctx }): Promise<AiProviderRuntimeState> => {
61
+ const runtimeConfig = await ctx.aiProviderModel.getAiProviderRuntimeConfig(
62
+ KeyVaultsGateKeeper.getUserKeyVaults,
63
+ );
64
+
65
+ const enabledAiProviders = await ctx.aiInfraRepos.getUserEnabledProviderList();
66
+
67
+ const enabledAiModels = await ctx.aiInfraRepos.getEnabledModels();
68
+
69
+ return { enabledAiModels, enabledAiProviders, runtimeConfig };
70
+ }),
71
+
72
+ removeAiProvider: aiProviderProcedure
73
+ .input(z.object({ id: z.string() }))
74
+ .mutation(async ({ input, ctx }) => {
75
+ return ctx.aiProviderModel.delete(input.id);
76
+ }),
77
+
78
+ toggleProviderEnabled: aiProviderProcedure
79
+ .input(
80
+ z.object({
81
+ enabled: z.boolean(),
82
+ id: z.string(),
83
+ }),
84
+ )
85
+ .mutation(async ({ input, ctx }) => {
86
+ return ctx.aiProviderModel.toggleProviderEnabled(input.id, input.enabled);
87
+ }),
88
+
89
+ updateAiProvider: aiProviderProcedure
90
+ .input(
91
+ z.object({
92
+ id: z.string(),
93
+ value: CreateAiProviderSchema.partial(),
94
+ }),
95
+ )
96
+ .mutation(async ({ input, ctx }) => {
97
+ return ctx.aiProviderModel.update(input.id, input.value);
98
+ }),
99
+
100
+ updateAiProviderConfig: aiProviderProcedure
101
+ .input(
102
+ z.object({
103
+ id: z.string(),
104
+ value: UpdateAiProviderConfigSchema,
105
+ }),
106
+ )
107
+ .mutation(async ({ input, ctx }) => {
108
+ return ctx.aiProviderModel.updateConfig(input.id, input.value, ctx.gateKeeper.encrypt);
109
+ }),
110
+
111
+ updateAiProviderOrder: aiProviderProcedure
112
+ .input(
113
+ z.object({
114
+ sortMap: z.array(
115
+ z.object({
116
+ id: z.string(),
117
+ sort: z.number(),
118
+ }),
119
+ ),
120
+ }),
121
+ )
122
+ .mutation(async ({ input, ctx }) => {
123
+ return ctx.aiProviderModel.updateOrder(input.sortMap);
124
+ }),
125
+ });
126
+
127
+ export type AiProviderRouter = typeof aiProviderRouter;
@@ -4,6 +4,8 @@
4
4
  import { publicProcedure, router } from '@/libs/trpc';
5
5
 
6
6
  import { agentRouter } from './agent';
7
+ import { aiModelRouter } from './aiModel';
8
+ import { aiProviderRouter } from './aiProvider';
7
9
  import { chunkRouter } from './chunk';
8
10
  import { fileRouter } from './file';
9
11
  import { importerRouter } from './importer';
@@ -19,6 +21,8 @@ import { userRouter } from './user';
19
21
 
20
22
  export const lambdaRouter = router({
21
23
  agent: agentRouter,
24
+ aiModel: aiModelRouter,
25
+ aiProvider: aiProviderRouter,
22
26
  chunk: chunkRouter,
23
27
  file: fileRouter,
24
28
  healthcheck: publicProcedure.query(() => "i'm live!"),
@@ -34,29 +34,19 @@ const setModelProviderConfig = <T extends GlobalLLMProviderKey>(
34
34
 
35
35
  describe('getProviderAuthPayload', () => {
36
36
  it('should return correct payload for ZhiPu provider', () => {
37
- act(() => {
38
- setModelProviderConfig('zhipu', { apiKey: mockZhiPuAPIKey });
39
- });
40
-
41
- const payload = getProviderAuthPayload(ModelProvider.ZhiPu);
37
+ const payload = getProviderAuthPayload(ModelProvider.ZhiPu, { apiKey: mockZhiPuAPIKey });
42
38
  expect(payload).toEqual({ apiKey: mockZhiPuAPIKey });
43
39
  });
44
40
 
45
41
  it('should return correct payload for Moonshot provider', () => {
46
- act(() => {
47
- setModelProviderConfig('moonshot', { apiKey: mockMoonshotAPIKey });
48
- });
49
-
50
- const payload = getProviderAuthPayload(ModelProvider.Moonshot);
42
+ const payload = getProviderAuthPayload(ModelProvider.Moonshot, { apiKey: mockMoonshotAPIKey });
51
43
  expect(payload).toEqual({ apiKey: mockMoonshotAPIKey });
52
44
  });
53
45
 
54
46
  it('should return correct payload for Anthropic provider', () => {
55
- act(() => {
56
- setModelProviderConfig('anthropic', { apiKey: mockAnthropicAPIKey });
47
+ const payload = getProviderAuthPayload(ModelProvider.Anthropic, {
48
+ apiKey: mockAnthropicAPIKey,
57
49
  });
58
-
59
- const payload = getProviderAuthPayload(ModelProvider.Anthropic);
60
50
  expect(payload).toEqual({ apiKey: mockAnthropicAPIKey });
61
51
  });
62
52
 
@@ -65,34 +55,26 @@ describe('getProviderAuthPayload', () => {
65
55
  setModelProviderConfig('mistral', { apiKey: mockMistralAPIKey });
66
56
  });
67
57
 
68
- const payload = getProviderAuthPayload(ModelProvider.Mistral);
58
+ const payload = getProviderAuthPayload(ModelProvider.Mistral, { apiKey: mockMistralAPIKey });
69
59
  expect(payload).toEqual({ apiKey: mockMistralAPIKey });
70
60
  });
71
61
 
72
62
  it('should return correct payload for OpenRouter provider', () => {
73
- act(() => {
74
- setModelProviderConfig('openrouter', { apiKey: mockOpenRouterAPIKey });
63
+ const payload = getProviderAuthPayload(ModelProvider.OpenRouter, {
64
+ apiKey: mockOpenRouterAPIKey,
75
65
  });
76
-
77
- const payload = getProviderAuthPayload(ModelProvider.OpenRouter);
78
66
  expect(payload).toEqual({ apiKey: mockOpenRouterAPIKey });
79
67
  });
80
68
 
81
69
  it('should return correct payload for TogetherAI provider', () => {
82
- act(() => {
83
- setModelProviderConfig('togetherai', { apiKey: mockTogetherAIAPIKey });
70
+ const payload = getProviderAuthPayload(ModelProvider.TogetherAI, {
71
+ apiKey: mockTogetherAIAPIKey,
84
72
  });
85
-
86
- const payload = getProviderAuthPayload(ModelProvider.TogetherAI);
87
73
  expect(payload).toEqual({ apiKey: mockTogetherAIAPIKey });
88
74
  });
89
75
 
90
76
  it('should return correct payload for Google provider', () => {
91
- act(() => {
92
- setModelProviderConfig('google', { apiKey: mockGoogleAPIKey });
93
- });
94
-
95
- const payload = getProviderAuthPayload(ModelProvider.Google);
77
+ const payload = getProviderAuthPayload(ModelProvider.Google, { apiKey: mockGoogleAPIKey });
96
78
  expect(payload).toEqual({ apiKey: mockGoogleAPIKey });
97
79
  });
98
80
 
@@ -103,11 +85,8 @@ describe('getProviderAuthPayload', () => {
103
85
  region: 'bedrock-region',
104
86
  secretAccessKey: 'bedrock-secret-access-key',
105
87
  };
106
- act(() => {
107
- setModelProviderConfig('bedrock', mockBedrockConfig);
108
- });
109
88
 
110
- const payload = getProviderAuthPayload(ModelProvider.Bedrock);
89
+ const payload = getProviderAuthPayload(ModelProvider.Bedrock, mockBedrockConfig);
111
90
  expect(payload).toEqual({
112
91
  apiKey: mockBedrockConfig.secretAccessKey + mockBedrockConfig.accessKeyId,
113
92
  awsAccessKeyId: mockBedrockConfig.accessKeyId,
@@ -123,11 +102,8 @@ describe('getProviderAuthPayload', () => {
123
102
  apiVersion: 'azure-api-version',
124
103
  endpoint: 'azure-endpoint',
125
104
  };
126
- act(() => {
127
- setModelProviderConfig('azure', mockAzureConfig);
128
- });
129
105
 
130
- const payload = getProviderAuthPayload(ModelProvider.Azure);
106
+ const payload = getProviderAuthPayload(ModelProvider.Azure, mockAzureConfig);
131
107
  expect(payload).toEqual({
132
108
  apiKey: mockAzureConfig.apiKey,
133
109
  azureApiVersion: mockAzureConfig.apiVersion,
@@ -138,11 +114,8 @@ describe('getProviderAuthPayload', () => {
138
114
  it('should return correct payload for Ollama provider', () => {
139
115
  // 假设的 Ollama 配置
140
116
  const mockOllamaProxyUrl = 'ollama-proxy-url';
141
- act(() => {
142
- setModelProviderConfig('ollama', { baseURL: mockOllamaProxyUrl });
143
- });
144
117
 
145
- const payload = getProviderAuthPayload(ModelProvider.Ollama);
118
+ const payload = getProviderAuthPayload(ModelProvider.Ollama, { baseURL: mockOllamaProxyUrl });
146
119
  expect(payload).toEqual({
147
120
  baseURL: mockOllamaProxyUrl,
148
121
  });
@@ -156,11 +129,8 @@ describe('getProviderAuthPayload', () => {
156
129
  useAzure: true,
157
130
  azureApiVersion: 'openai-azure-api-version',
158
131
  };
159
- act(() => {
160
- setModelProviderConfig('openai', mockOpenAIConfig);
161
- });
162
132
 
163
- const payload = getProviderAuthPayload(ModelProvider.OpenAI);
133
+ const payload = getProviderAuthPayload(ModelProvider.OpenAI, mockOpenAIConfig);
164
134
  expect(payload).toEqual({
165
135
  apiKey: mockOpenAIConfig.apiKey,
166
136
  baseURL: mockOpenAIConfig.baseURL,
@@ -173,11 +143,8 @@ describe('getProviderAuthPayload', () => {
173
143
  apiKey: 'stepfun-api-key',
174
144
  baseURL: 'stepfun-baseURL',
175
145
  };
176
- act(() => {
177
- setModelProviderConfig('stepfun', mockOpenAIConfig);
178
- });
179
146
 
180
- const payload = getProviderAuthPayload(ModelProvider.Stepfun);
147
+ const payload = getProviderAuthPayload(ModelProvider.Stepfun, mockOpenAIConfig);
181
148
  expect(payload).toEqual({
182
149
  apiKey: mockOpenAIConfig.apiKey,
183
150
  baseURL: mockOpenAIConfig.baseURL,
@@ -185,7 +152,7 @@ describe('getProviderAuthPayload', () => {
185
152
  });
186
153
 
187
154
  it('should return an empty object or throw an error for an unknown provider', () => {
188
- const payload = getProviderAuthPayload('UnknownProvider');
155
+ const payload = getProviderAuthPayload('UnknownProvider', {});
189
156
  expect(payload).toEqual({});
190
157
  });
191
158
  });
@@ -60,6 +60,7 @@ beforeEach(() => {
60
60
  // 默认设置 isServerMode 为 false
61
61
  vi.mock('@/const/version', () => ({
62
62
  isServerMode: false,
63
+ isDeprecatedEdition: true,
63
64
  }));
64
65
  });
65
66
 
@@ -836,6 +837,7 @@ describe('ChatService', () => {
836
837
  // 重新模拟模块,设置 isServerMode 为 true
837
838
  vi.doMock('@/const/version', () => ({
838
839
  isServerMode: true,
840
+ isDeprecatedEdition: true,
839
841
  }));
840
842
 
841
843
  // 需要在修改模拟后重新导入相关模块
@@ -1,15 +1,29 @@
1
1
  import { JWTPayload, LOBE_CHAT_AUTH_HEADER } from '@/const/auth';
2
+ import { isServerMode } from '@/const/version';
2
3
  import { ModelProvider } from '@/libs/agent-runtime';
4
+ import { aiProviderSelectors, useAiInfraStore } from '@/store/aiInfra';
3
5
  import { useUserStore } from '@/store/user';
4
6
  import { keyVaultsConfigSelectors, userProfileSelectors } from '@/store/user/selectors';
5
- import { GlobalLLMProviderKey } from '@/types/user/settings';
7
+ import {
8
+ AWSBedrockKeyVault,
9
+ AzureOpenAIKeyVault,
10
+ CloudflareKeyVault,
11
+ OpenAICompatibleKeyVault,
12
+ WenxinKeyVault,
13
+ } from '@/types/user/settings';
6
14
  import { createJWT } from '@/utils/jwt';
7
15
 
8
- export const getProviderAuthPayload = (provider: string) => {
16
+ export const getProviderAuthPayload = (
17
+ provider: string,
18
+ keyVaults: OpenAICompatibleKeyVault &
19
+ AzureOpenAIKeyVault &
20
+ AWSBedrockKeyVault &
21
+ WenxinKeyVault &
22
+ CloudflareKeyVault,
23
+ ) => {
9
24
  switch (provider) {
10
25
  case ModelProvider.Bedrock: {
11
- const { accessKeyId, region, secretAccessKey, sessionToken } =
12
- keyVaultsConfigSelectors.bedrockConfig(useUserStore.getState());
26
+ const { accessKeyId, region, secretAccessKey, sessionToken } = keyVaults;
13
27
 
14
28
  const awsSecretAccessKey = secretAccessKey;
15
29
  const awsAccessKeyId = accessKeyId;
@@ -26,9 +40,7 @@ export const getProviderAuthPayload = (provider: string) => {
26
40
  }
27
41
 
28
42
  case ModelProvider.Wenxin: {
29
- const { secretKey, accessKey } = keyVaultsConfigSelectors.wenxinConfig(
30
- useUserStore.getState(),
31
- );
43
+ const { secretKey, accessKey } = keyVaults;
32
44
 
33
45
  const apiKey = (accessKey || '') + (secretKey || '');
34
46
 
@@ -40,36 +52,26 @@ export const getProviderAuthPayload = (provider: string) => {
40
52
  }
41
53
 
42
54
  case ModelProvider.Azure: {
43
- const azure = keyVaultsConfigSelectors.azureConfig(useUserStore.getState());
44
-
45
55
  return {
46
- apiKey: azure.apiKey,
47
- azureApiVersion: azure.apiVersion,
48
- baseURL: azure.endpoint,
56
+ apiKey: keyVaults.apiKey,
57
+ azureApiVersion: keyVaults.apiVersion,
58
+ baseURL: keyVaults.endpoint,
49
59
  };
50
60
  }
51
61
 
52
62
  case ModelProvider.Ollama: {
53
- const config = keyVaultsConfigSelectors.ollamaConfig(useUserStore.getState());
54
-
55
- return { baseURL: config?.baseURL };
63
+ return { baseURL: keyVaults?.baseURL };
56
64
  }
57
65
 
58
66
  case ModelProvider.Cloudflare: {
59
- const config = keyVaultsConfigSelectors.cloudflareConfig(useUserStore.getState());
60
-
61
67
  return {
62
- apiKey: config?.apiKey,
63
- cloudflareBaseURLOrAccountID: config?.baseURLOrAccountID,
68
+ apiKey: keyVaults?.apiKey,
69
+ cloudflareBaseURLOrAccountID: keyVaults?.baseURLOrAccountID,
64
70
  };
65
71
  }
66
72
 
67
73
  default: {
68
- const config = keyVaultsConfigSelectors.getVaultByProvider(provider as GlobalLLMProviderKey)(
69
- useUserStore.getState(),
70
- );
71
-
72
- return { apiKey: config?.apiKey, baseURL: config?.baseURL };
74
+ return { apiKey: keyVaults?.apiKey, baseURL: keyVaults?.baseURL };
73
75
  }
74
76
  }
75
77
  };
@@ -88,12 +90,27 @@ interface AuthParams {
88
90
  provider?: string;
89
91
  }
90
92
 
93
+ export const createPayloadWithKeyVaults = (provider: string) => {
94
+ let keyVaults = {};
95
+
96
+ // TODO: remove this condition in V2.0
97
+ if (!isServerMode) {
98
+ keyVaults = keyVaultsConfigSelectors.getVaultByProvider(provider as any)(
99
+ useUserStore.getState(),
100
+ );
101
+ } else {
102
+ keyVaults = aiProviderSelectors.providerKeyVaults(provider)(useAiInfraStore.getState()) || {};
103
+ }
104
+
105
+ return getProviderAuthPayload(provider, keyVaults);
106
+ };
107
+
91
108
  // eslint-disable-next-line no-undef
92
109
  export const createHeaderWithAuth = async (params?: AuthParams): Promise<HeadersInit> => {
93
110
  let payload = params?.payload || {};
94
111
 
95
112
  if (params?.provider) {
96
- payload = { ...payload, ...getProviderAuthPayload(params?.provider) };
113
+ payload = { ...payload, ...createPayloadWithKeyVaults(params?.provider) };
97
114
  }
98
115
 
99
116
  const token = await createAuthTokenWithPayload(payload);
@@ -0,0 +1,52 @@
1
+ import { lambdaClient } from '@/libs/trpc/client';
2
+ import {
3
+ AiModelSortMap,
4
+ AiProviderModelListItem,
5
+ CreateAiModelParams,
6
+ ToggleAiModelEnableParams,
7
+ UpdateAiModelParams,
8
+ } from '@/types/aiModel';
9
+
10
+ class AiModelService {
11
+ createAiModel = async (params: CreateAiModelParams) => {
12
+ return lambdaClient.aiModel.createAiModel.mutate(params);
13
+ };
14
+
15
+ getAiProviderModelList = async (id: string): Promise<AiProviderModelListItem[]> => {
16
+ return lambdaClient.aiModel.getAiProviderModelList.query({ id });
17
+ };
18
+
19
+ getAiModelById = async (id: string) => {
20
+ return lambdaClient.aiModel.getAiModelById.query({ id });
21
+ };
22
+
23
+ toggleModelEnabled = async (params: ToggleAiModelEnableParams) => {
24
+ return lambdaClient.aiModel.toggleModelEnabled.mutate(params);
25
+ };
26
+
27
+ updateAiModel = async (id: string, providerId: string, value: UpdateAiModelParams) => {
28
+ return lambdaClient.aiModel.updateAiModel.mutate({ id, providerId, value });
29
+ };
30
+
31
+ batchUpdateAiModels = async (id: string, models: AiProviderModelListItem[]) => {
32
+ return lambdaClient.aiModel.batchUpdateAiModels.mutate({ id, models });
33
+ };
34
+
35
+ batchToggleAiModels = async (id: string, models: string[], enabled: boolean) => {
36
+ return lambdaClient.aiModel.batchToggleAiModels.mutate({ enabled, id, models });
37
+ };
38
+
39
+ clearRemoteModels = async (providerId: string) => {
40
+ return lambdaClient.aiModel.clearRemoteModels.mutate({ providerId });
41
+ };
42
+
43
+ updateAiModelOrder = async (providerId: string, items: AiModelSortMap[]) => {
44
+ return lambdaClient.aiModel.updateAiModelOrder.mutate({ providerId, sortMap: items });
45
+ };
46
+
47
+ deleteAiModel = async (params: { id: string; providerId: string }) => {
48
+ return lambdaClient.aiModel.removeAiModel.mutate(params);
49
+ };
50
+ }
51
+
52
+ export const aiModelService = new AiModelService();
@@ -0,0 +1,47 @@
1
+ import { lambdaClient } from '@/libs/trpc/client';
2
+ import {
3
+ AiProviderRuntimeState,
4
+ AiProviderSortMap,
5
+ CreateAiProviderParams,
6
+ UpdateAiProviderConfigParams,
7
+ } from '@/types/aiProvider';
8
+
9
+ class AiProviderService {
10
+ createAiProvider = async (params: CreateAiProviderParams) => {
11
+ return lambdaClient.aiProvider.createAiProvider.mutate(params);
12
+ };
13
+
14
+ getAiProviderList = async () => {
15
+ return lambdaClient.aiProvider.getAiProviderList.query();
16
+ };
17
+
18
+ getAiProviderById = async (id: string) => {
19
+ return lambdaClient.aiProvider.getAiProviderById.query({ id });
20
+ };
21
+
22
+ toggleProviderEnabled = async (id: string, enabled: boolean) => {
23
+ return lambdaClient.aiProvider.toggleProviderEnabled.mutate({ enabled, id });
24
+ };
25
+
26
+ updateAiProvider = async (id: string, value: any) => {
27
+ return lambdaClient.aiProvider.updateAiProvider.mutate({ id, value });
28
+ };
29
+
30
+ updateAiProviderConfig = async (id: string, value: UpdateAiProviderConfigParams) => {
31
+ return lambdaClient.aiProvider.updateAiProviderConfig.mutate({ id, value });
32
+ };
33
+
34
+ updateAiProviderOrder = async (items: AiProviderSortMap[]) => {
35
+ return lambdaClient.aiProvider.updateAiProviderOrder.mutate({ sortMap: items });
36
+ };
37
+
38
+ deleteAiProvider = async (id: string) => {
39
+ return lambdaClient.aiProvider.removeAiProvider.mutate({ id });
40
+ };
41
+
42
+ getAiProviderRuntimeState = async (isLogin?: boolean): Promise<AiProviderRuntimeState> => {
43
+ return lambdaClient.aiProvider.getAiProviderRuntimeState.query({ isLogin });
44
+ };
45
+ }
46
+
47
+ export const aiProviderService = new AiProviderService();
@@ -16,6 +16,7 @@ import {
16
16
  } from '@/libs/agent-runtime';
17
17
  import { filesPrompts } from '@/prompts/files';
18
18
  import { BuiltinSystemRolePrompts } from '@/prompts/systemRole';
19
+ import { aiModelSelectors, aiProviderSelectors, useAiInfraStore } from '@/store/aiInfra';
19
20
  import { useSessionStore } from '@/store/session';
20
21
  import { sessionMetaSelectors } from '@/store/session/selectors';
21
22
  import { useToolStore } from '@/store/tool';
@@ -36,9 +37,50 @@ import { FetchSSEOptions, fetchSSE, getMessageError } from '@/utils/fetch';
36
37
  import { genToolCallingName } from '@/utils/toolCall';
37
38
  import { createTraceHeader, getTraceId } from '@/utils/trace';
38
39
 
39
- import { createHeaderWithAuth, getProviderAuthPayload } from './_auth';
40
+ import { createHeaderWithAuth, createPayloadWithKeyVaults } from './_auth';
40
41
  import { API_ENDPOINTS } from './_url';
41
42
 
43
+ const isCanUseFC = (model: string) => {
44
+ // TODO: remove isDeprecatedEdition condition in V2.0
45
+ if (!isServerMode) {
46
+ return modelProviderSelectors.isModelEnabledFunctionCall(model)(useUserStore.getState());
47
+ }
48
+
49
+ return aiModelSelectors.isModelSupportToolUse(model)(useAiInfraStore.getState());
50
+ };
51
+
52
+ const findAzureDeploymentName = (model: string) => {
53
+ let deploymentId = model;
54
+
55
+ // TODO: remove isDeprecatedEdition condition in V2.0
56
+ if (!isServerMode) {
57
+ const chatModelCards = modelProviderSelectors.getModelCardsById(ModelProvider.Azure)(
58
+ useUserStore.getState(),
59
+ );
60
+
61
+ const deploymentName = chatModelCards.find((i) => i.id === model)?.deploymentName;
62
+ if (deploymentName) deploymentId = deploymentName;
63
+ } else {
64
+ // find the model by id
65
+ const modelItem = useAiInfraStore.getState().enabledAiModels?.find((i) => i.id === model);
66
+
67
+ if (modelItem && modelItem.config?.deploymentName) {
68
+ deploymentId = modelItem.config?.deploymentName;
69
+ }
70
+ }
71
+
72
+ return deploymentId;
73
+ };
74
+
75
+ const isEnableFetchOnClient = (provider: string) => {
76
+ // TODO: remove this condition in V2.0
77
+ if (!isServerMode) {
78
+ return modelConfigSelectors.isProviderFetchOnClient(provider)(useUserStore.getState());
79
+ } else {
80
+ return aiProviderSelectors.isProviderFetchOnClient(provider)(useAiInfraStore.getState());
81
+ }
82
+ };
83
+
42
84
  interface FetchOptions extends FetchSSEOptions {
43
85
  historySummary?: string;
44
86
  isWelcomeQuestion?: boolean;
@@ -83,7 +125,7 @@ interface CreateAssistantMessageStream extends FetchSSEOptions {
83
125
  */
84
126
  export function initializeWithClientStore(provider: string, payload: any) {
85
127
  // add auth payload
86
- const providerAuthPayload = getProviderAuthPayload(provider);
128
+ const providerAuthPayload = { ...payload, ...createPayloadWithKeyVaults(provider) };
87
129
  const commonOptions = {
88
130
  // Some provider base openai sdk, so enable it run on browser
89
131
  dangerouslyAllowBrowser: true,
@@ -200,9 +242,8 @@ class ChatService {
200
242
  const filterTools = toolSelectors.enabledSchema(enabledPlugins)(useToolStore.getState());
201
243
 
202
244
  // check this model can use function call
203
- const canUseFC = modelProviderSelectors.isModelEnabledFunctionCall(payload.model)(
204
- useUserStore.getState(),
205
- );
245
+ const canUseFC = isCanUseFC(payload.model);
246
+
206
247
  // the rule that model can use tools:
207
248
  // 1. tools is not empty
208
249
  // 2. model can use function call
@@ -245,12 +286,7 @@ class ChatService {
245
286
 
246
287
  // if the provider is Azure, get the deployment name as the request model
247
288
  if (provider === ModelProvider.Azure) {
248
- const chatModelCards = modelProviderSelectors.getModelCardsById(provider)(
249
- useUserStore.getState(),
250
- );
251
-
252
- const deploymentName = chatModelCards.find((i) => i.id === model)?.deploymentName;
253
- if (deploymentName) model = deploymentName;
289
+ model = findAzureDeploymentName(model);
254
290
  }
255
291
 
256
292
  const payload = merge(
@@ -261,9 +297,7 @@ class ChatService {
261
297
  /**
262
298
  * Use browser agent runtime
263
299
  */
264
- const enableFetchOnClient = modelConfigSelectors.isProviderFetchOnClient(provider)(
265
- useUserStore.getState(),
266
- );
300
+ let enableFetchOnClient = isEnableFetchOnClient(provider);
267
301
 
268
302
  let fetcher: typeof fetch | undefined = undefined;
269
303
 
@@ -302,7 +336,19 @@ class ChatService {
302
336
 
303
337
  const providerConfig = DEFAULT_MODEL_PROVIDER_LIST.find((item) => item.id === provider);
304
338
 
305
- return fetchSSE(API_ENDPOINTS.chat(provider), {
339
+ let sdkType = provider;
340
+ const isBuiltin = Object.values(ModelProvider).includes(provider as any);
341
+
342
+ // TODO: remove `!isDeprecatedEdition` condition in V2.0
343
+ if (isServerMode && !isBuiltin) {
344
+ const providerConfig = aiProviderSelectors.providerConfigById(provider)(
345
+ useAiInfraStore.getState(),
346
+ );
347
+
348
+ sdkType = providerConfig?.settings.sdkType || 'openai';
349
+ }
350
+
351
+ return fetchSSE(API_ENDPOINTS.chat(sdkType), {
306
352
  body: JSON.stringify(payload),
307
353
  fetcher: fetcher,
308
354
  headers,
@@ -467,9 +513,7 @@ class ChatService {
467
513
 
468
514
  // Inject Tool SystemRole
469
515
  const hasTools = tools && tools?.length > 0;
470
- const hasFC =
471
- hasTools &&
472
- modelProviderSelectors.isModelEnabledFunctionCall(model)(useUserStore.getState());
516
+ const hasFC = hasTools && isCanUseFC(model);
473
517
  const toolsSystemRoles =
474
518
  hasFC && toolSelectors.enabledSystemRoles(tools)(useToolStore.getState());
475
519
 
@@ -0,0 +1,2 @@
1
+ export * from './selectors';
2
+ export { useAiInfraStore } from './store';
@@ -0,0 +1,11 @@
1
+ import { AIModelsState, initialAIModelState } from './slices/aiModel';
2
+ import { AIProviderState, initialAIProviderState } from './slices/aiProvider';
3
+
4
+ export interface AIProviderStoreState extends AIProviderState, AIModelsState {
5
+ /* empty */
6
+ }
7
+
8
+ export const initialState: AIProviderStoreState = {
9
+ ...initialAIProviderState,
10
+ ...initialAIModelState,
11
+ };
@@ -0,0 +1,2 @@
1
+ export * from './slices/aiModel/selectors';
2
+ export * from './slices/aiProvider/selectors';