@lobehub/chat 0.146.2 → 0.147.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 (358) hide show
  1. package/.env.example +3 -5
  2. package/.github/workflows/issue-close-require.yml +1 -1
  3. package/.github/workflows/release.yml +1 -1
  4. package/.github/workflows/test.yml +3 -1
  5. package/.i18nrc.js +13 -8
  6. package/.seorc.cjs +9 -0
  7. package/CHANGELOG.md +73 -0
  8. package/README.md +25 -25
  9. package/README.zh-CN.md +25 -25
  10. package/contributing/Home.md +1 -1
  11. package/docs/self-hosting/advanced/analytics.mdx +12 -0
  12. package/docs/self-hosting/advanced/analytics.zh-CN.mdx +10 -0
  13. package/docs/self-hosting/advanced/authentication.mdx +19 -0
  14. package/docs/self-hosting/advanced/authentication.zh-CN.mdx +15 -0
  15. package/docs/self-hosting/advanced/sso-providers/auth0.mdx +19 -2
  16. package/docs/self-hosting/advanced/sso-providers/auth0.zh-CN.mdx +15 -2
  17. package/docs/self-hosting/advanced/sso-providers/authentik.mdx +18 -3
  18. package/docs/self-hosting/advanced/sso-providers/authentik.zh-CN.mdx +14 -2
  19. package/docs/self-hosting/advanced/sso-providers/github.mdx +13 -0
  20. package/docs/self-hosting/advanced/sso-providers/github.zh-CN.mdx +13 -3
  21. package/docs/self-hosting/advanced/sso-providers/microsoft-entra-id.mdx +18 -2
  22. package/docs/self-hosting/advanced/sso-providers/microsoft-entra-id.zh-CN.mdx +15 -2
  23. package/docs/self-hosting/advanced/sso-providers/zitadel.mdx +17 -2
  24. package/docs/self-hosting/advanced/sso-providers/zitadel.zh-CN.mdx +14 -2
  25. package/docs/self-hosting/advanced/upstream-sync.mdx +13 -0
  26. package/docs/self-hosting/advanced/upstream-sync.zh-CN.mdx +10 -0
  27. package/docs/self-hosting/environment-variables/analytics.mdx +15 -0
  28. package/docs/self-hosting/environment-variables/analytics.zh-CN.mdx +13 -0
  29. package/docs/self-hosting/environment-variables/auth.mdx +14 -0
  30. package/docs/self-hosting/environment-variables/auth.zh-CN.mdx +15 -1
  31. package/docs/self-hosting/environment-variables/basic.mdx +15 -0
  32. package/docs/self-hosting/environment-variables/basic.zh-CN.mdx +11 -0
  33. package/docs/self-hosting/environment-variables/model-provider.mdx +26 -0
  34. package/docs/self-hosting/environment-variables/model-provider.zh-CN.mdx +10 -0
  35. package/docs/self-hosting/environment-variables.mdx +13 -2
  36. package/docs/self-hosting/environment-variables.zh-CN.mdx +9 -0
  37. package/docs/self-hosting/examples/azure-openai.mdx +12 -0
  38. package/docs/self-hosting/examples/azure-openai.zh-CN.mdx +12 -0
  39. package/docs/self-hosting/examples/ollama.mdx +13 -0
  40. package/docs/self-hosting/examples/ollama.zh-CN.mdx +11 -0
  41. package/docs/self-hosting/faq/no-v1-suffix.mdx +12 -0
  42. package/docs/self-hosting/faq/no-v1-suffix.zh-CN.mdx +9 -0
  43. package/docs/self-hosting/faq/proxy-with-unable-to-verify-leaf-signature.mdx +14 -0
  44. package/docs/self-hosting/faq/proxy-with-unable-to-verify-leaf-signature.zh-CN.mdx +11 -0
  45. package/docs/self-hosting/platform/docker-compose.mdx +21 -5
  46. package/docs/self-hosting/platform/docker-compose.zh-CN.mdx +18 -5
  47. package/docs/self-hosting/platform/docker.mdx +26 -8
  48. package/docs/self-hosting/platform/docker.zh-CN.mdx +27 -9
  49. package/docs/self-hosting/platform/netlify.mdx +18 -2
  50. package/docs/self-hosting/platform/netlify.zh-CN.mdx +14 -1
  51. package/docs/self-hosting/platform/railway.mdx +12 -0
  52. package/docs/self-hosting/platform/railway.zh-CN.mdx +11 -0
  53. package/docs/self-hosting/platform/repocloud.mdx +12 -0
  54. package/docs/self-hosting/platform/repocloud.zh-CN.mdx +10 -0
  55. package/docs/self-hosting/platform/sealos.mdx +11 -0
  56. package/docs/self-hosting/platform/sealos.zh-CN.mdx +10 -0
  57. package/docs/self-hosting/platform/vercel.mdx +12 -0
  58. package/docs/self-hosting/platform/vercel.zh-CN.mdx +11 -0
  59. package/docs/self-hosting/platform/zeabur.mdx +11 -0
  60. package/docs/self-hosting/platform/zeabur.zh-CN.mdx +10 -0
  61. package/docs/self-hosting/start.mdx +12 -0
  62. package/docs/self-hosting/start.zh-CN.mdx +13 -0
  63. package/docs/usage/agents/concepts.mdx +13 -0
  64. package/docs/usage/agents/concepts.zh-CN.mdx +10 -0
  65. package/docs/usage/agents/custom-agent.mdx +16 -2
  66. package/docs/usage/agents/custom-agent.zh-CN.mdx +14 -2
  67. package/docs/usage/agents/model.mdx +11 -2
  68. package/docs/usage/agents/model.zh-CN.mdx +12 -0
  69. package/docs/usage/agents/prompt.mdx +15 -0
  70. package/docs/usage/agents/prompt.zh-CN.mdx +10 -0
  71. package/docs/usage/agents/topics.mdx +13 -0
  72. package/docs/usage/agents/topics.zh-CN.mdx +11 -0
  73. package/docs/usage/features/agent-market.mdx +11 -1
  74. package/docs/usage/features/agent-market.zh-CN.mdx +13 -0
  75. package/docs/usage/features/local-llm.mdx +12 -2
  76. package/docs/usage/features/local-llm.zh-CN.mdx +3 -3
  77. package/docs/usage/features/mobile.mdx +10 -1
  78. package/docs/usage/features/mobile.zh-CN.mdx +11 -0
  79. package/docs/usage/features/more.mdx +13 -0
  80. package/docs/usage/features/more.zh-CN.mdx +10 -0
  81. package/docs/usage/features/multi-ai-providers.mdx +14 -1
  82. package/docs/usage/features/multi-ai-providers.zh-CN.mdx +16 -0
  83. package/docs/usage/features/plugin-system.mdx +12 -1
  84. package/docs/usage/features/plugin-system.zh-CN.mdx +9 -0
  85. package/docs/usage/features/pwa.mdx +11 -1
  86. package/docs/usage/features/pwa.zh-CN.mdx +13 -0
  87. package/docs/usage/features/text-to-image.mdx +11 -1
  88. package/docs/usage/features/text-to-image.zh-CN.mdx +13 -0
  89. package/docs/usage/features/theme.mdx +12 -1
  90. package/docs/usage/features/theme.zh-CN.mdx +11 -0
  91. package/docs/usage/features/tts.mdx +14 -1
  92. package/docs/usage/features/tts.zh-CN.mdx +12 -0
  93. package/docs/usage/features/vision.mdx +11 -1
  94. package/docs/usage/features/vision.zh-CN.mdx +10 -0
  95. package/docs/usage/plugins/basic-usage.mdx +12 -0
  96. package/docs/usage/plugins/basic-usage.zh-CN.mdx +10 -0
  97. package/docs/usage/plugins/custom-plugin.mdx +12 -0
  98. package/docs/usage/plugins/custom-plugin.zh-CN.mdx +10 -0
  99. package/docs/usage/plugins/development.mdx +18 -0
  100. package/docs/usage/plugins/development.zh-CN.mdx +12 -0
  101. package/docs/usage/plugins/store.mdx +12 -0
  102. package/docs/usage/plugins/store.zh-CN.mdx +9 -0
  103. package/docs/usage/providers/groq.mdx +14 -2
  104. package/docs/usage/providers/groq.zh-CN.mdx +12 -2
  105. package/docs/usage/providers/ollama/gemma.mdx +13 -3
  106. package/docs/usage/providers/ollama/gemma.zh-CN.mdx +12 -3
  107. package/docs/usage/providers/ollama/qwen.mdx +12 -4
  108. package/docs/usage/providers/ollama/qwen.zh-CN.mdx +10 -3
  109. package/docs/usage/providers/ollama.mdx +19 -9
  110. package/docs/usage/providers/ollama.zh-CN.mdx +20 -9
  111. package/docs/usage/start.mdx +13 -2
  112. package/docs/usage/start.zh-CN.mdx +11 -2
  113. package/locales/ar/common.json +0 -26
  114. package/locales/ar/components.json +15 -0
  115. package/locales/ar/error.json +1 -52
  116. package/locales/ar/modelProvider.json +226 -0
  117. package/locales/ar/setting.json +48 -199
  118. package/locales/bg-BG/common.json +0 -26
  119. package/locales/bg-BG/components.json +15 -0
  120. package/locales/bg-BG/error.json +1 -52
  121. package/locales/bg-BG/modelProvider.json +226 -0
  122. package/locales/bg-BG/setting.json +48 -199
  123. package/locales/de-DE/common.json +0 -26
  124. package/locales/de-DE/components.json +15 -0
  125. package/locales/de-DE/error.json +1 -52
  126. package/locales/de-DE/modelProvider.json +226 -0
  127. package/locales/de-DE/setting.json +48 -199
  128. package/locales/en-US/common.json +0 -26
  129. package/locales/en-US/components.json +15 -0
  130. package/locales/en-US/error.json +1 -52
  131. package/locales/en-US/modelProvider.json +226 -0
  132. package/locales/en-US/setting.json +48 -199
  133. package/locales/es-ES/common.json +0 -26
  134. package/locales/es-ES/components.json +15 -0
  135. package/locales/es-ES/error.json +1 -52
  136. package/locales/es-ES/modelProvider.json +226 -0
  137. package/locales/es-ES/setting.json +48 -199
  138. package/locales/fr-FR/common.json +0 -26
  139. package/locales/fr-FR/components.json +15 -0
  140. package/locales/fr-FR/error.json +1 -52
  141. package/locales/fr-FR/modelProvider.json +226 -0
  142. package/locales/fr-FR/setting.json +48 -199
  143. package/locales/it-IT/common.json +0 -26
  144. package/locales/it-IT/components.json +15 -0
  145. package/locales/it-IT/error.json +1 -52
  146. package/locales/it-IT/modelProvider.json +226 -0
  147. package/locales/it-IT/setting.json +59 -210
  148. package/locales/ja-JP/common.json +0 -26
  149. package/locales/ja-JP/components.json +15 -0
  150. package/locales/ja-JP/error.json +1 -52
  151. package/locales/ja-JP/modelProvider.json +226 -0
  152. package/locales/ja-JP/setting.json +59 -210
  153. package/locales/ko-KR/common.json +0 -26
  154. package/locales/ko-KR/components.json +15 -0
  155. package/locales/ko-KR/error.json +1 -52
  156. package/locales/ko-KR/modelProvider.json +226 -0
  157. package/locales/ko-KR/setting.json +48 -199
  158. package/locales/nl-NL/common.json +0 -26
  159. package/locales/nl-NL/components.json +15 -0
  160. package/locales/nl-NL/error.json +4 -55
  161. package/locales/nl-NL/modelProvider.json +226 -0
  162. package/locales/nl-NL/setting.json +49 -200
  163. package/locales/pl-PL/common.json +0 -26
  164. package/locales/pl-PL/components.json +15 -0
  165. package/locales/pl-PL/error.json +1 -52
  166. package/locales/pl-PL/modelProvider.json +226 -0
  167. package/locales/pl-PL/setting.json +48 -199
  168. package/locales/pt-BR/common.json +0 -26
  169. package/locales/pt-BR/components.json +15 -0
  170. package/locales/pt-BR/error.json +1 -52
  171. package/locales/pt-BR/modelProvider.json +226 -0
  172. package/locales/pt-BR/setting.json +48 -199
  173. package/locales/ru-RU/common.json +0 -26
  174. package/locales/ru-RU/components.json +15 -0
  175. package/locales/ru-RU/error.json +1 -52
  176. package/locales/ru-RU/modelProvider.json +226 -0
  177. package/locales/ru-RU/setting.json +48 -199
  178. package/locales/tr-TR/common.json +0 -26
  179. package/locales/tr-TR/components.json +15 -0
  180. package/locales/tr-TR/error.json +1 -52
  181. package/locales/tr-TR/modelProvider.json +226 -0
  182. package/locales/tr-TR/setting.json +48 -199
  183. package/locales/vi-VN/common.json +0 -26
  184. package/locales/vi-VN/components.json +15 -0
  185. package/locales/vi-VN/error.json +1 -52
  186. package/locales/vi-VN/modelProvider.json +226 -0
  187. package/locales/vi-VN/setting.json +48 -199
  188. package/locales/zh-CN/common.json +0 -26
  189. package/locales/zh-CN/components.json +15 -0
  190. package/locales/zh-CN/error.json +2 -53
  191. package/locales/zh-CN/modelProvider.json +226 -0
  192. package/locales/zh-CN/setting.json +48 -199
  193. package/locales/zh-TW/common.json +0 -26
  194. package/locales/zh-TW/components.json +15 -0
  195. package/locales/zh-TW/error.json +1 -52
  196. package/locales/zh-TW/modelProvider.json +226 -0
  197. package/locales/zh-TW/setting.json +48 -199
  198. package/package.json +120 -116
  199. package/scripts/mdxWorkflow/index.ts +48 -0
  200. package/src/app/api/chat/[provider]/route.test.ts +4 -9
  201. package/src/app/api/chat/[provider]/route.ts +6 -23
  202. package/src/app/api/chat/{[provider]/agentRuntime.test.ts → agentRuntime.test.ts} +12 -12
  203. package/src/app/api/chat/{[provider]/agentRuntime.ts → agentRuntime.ts} +11 -30
  204. package/src/app/api/chat/auth/index.ts +42 -0
  205. package/src/app/api/chat/models/[provider]/route.ts +45 -0
  206. package/src/app/api/config/__snapshots__/route.test.ts.snap +127 -0
  207. package/src/app/api/config/route.test.ts +170 -0
  208. package/src/app/api/config/route.ts +46 -11
  209. package/src/app/api/plugin/gateway/route.ts +1 -1
  210. package/src/app/settings/llm/Azure/index.tsx +36 -43
  211. package/src/app/settings/llm/Bedrock/index.tsx +12 -20
  212. package/src/app/settings/llm/Ollama/index.tsx +2 -2
  213. package/src/app/settings/llm/OpenAI/index.tsx +9 -121
  214. package/src/app/settings/llm/OpenRouter/index.tsx +1 -1
  215. package/src/app/settings/llm/TogetherAI/index.tsx +0 -1
  216. package/src/app/settings/llm/components/ProviderConfig/index.tsx +48 -32
  217. package/src/app/settings/llm/components/ProviderModelList/CustomModelOption.tsx +94 -0
  218. package/src/app/settings/llm/components/ProviderModelList/MaxTokenSlider.tsx +88 -0
  219. package/src/app/settings/llm/components/ProviderModelList/ModelConfigModal.tsx +128 -0
  220. package/src/app/settings/llm/components/ProviderModelList/ModelFetcher.tsx +81 -0
  221. package/src/app/settings/llm/components/ProviderModelList/Option.tsx +38 -0
  222. package/src/app/settings/llm/components/ProviderModelList/index.tsx +142 -0
  223. package/src/app/settings/llm/const.ts +1 -1
  224. package/src/app/settings/llm/index.tsx +7 -6
  225. package/src/app/settings/tts/TTS/index.tsx +1 -1
  226. package/src/components/AntdStaticMethods/index.test.tsx +43 -0
  227. package/src/components/ModelIcon/index.tsx +25 -7
  228. package/src/components/ModelSelect/index.tsx +67 -56
  229. package/src/config/modelProviders/anthropic.ts +6 -1
  230. package/src/config/modelProviders/azure.ts +42 -0
  231. package/src/config/modelProviders/bedrock.ts +4 -1
  232. package/src/config/modelProviders/google.ts +2 -14
  233. package/src/config/modelProviders/groq.ts +3 -0
  234. package/src/config/modelProviders/index.ts +19 -14
  235. package/src/config/modelProviders/mistral.ts +5 -0
  236. package/src/config/modelProviders/moonshot.ts +3 -1
  237. package/src/config/modelProviders/ollama.ts +6 -17
  238. package/src/config/modelProviders/openai.ts +9 -13
  239. package/src/config/modelProviders/openrouter.ts +6 -1
  240. package/src/config/modelProviders/perplexity.ts +2 -0
  241. package/src/config/modelProviders/togetherai.ts +11 -0
  242. package/src/config/modelProviders/zeroone.ts +3 -0
  243. package/src/config/modelProviders/zhipu.ts +3 -0
  244. package/src/config/server/provider.ts +52 -7
  245. package/src/const/auth.ts +0 -1
  246. package/src/const/{settings.ts → settings/index.ts} +31 -4
  247. package/src/const/url.ts +1 -1
  248. package/src/database/core/db.ts +14 -0
  249. package/src/database/schemas/user.ts +1 -25
  250. package/src/features/AgentSetting/AgentConfig/ModelSelect.tsx +7 -11
  251. package/src/features/ChatInput/STT/common.tsx +80 -78
  252. package/src/features/ChatInput/STT/index.tsx +8 -6
  253. package/src/features/Conversation/Error/APIKeyForm/Bedrock.tsx +8 -8
  254. package/src/features/Conversation/Error/APIKeyForm/ProviderApiKeyForm.tsx +73 -0
  255. package/src/features/Conversation/Error/APIKeyForm/ProviderAvatar.tsx +74 -0
  256. package/src/features/Conversation/Error/APIKeyForm/index.tsx +25 -49
  257. package/src/features/ModelSwitchPanel/index.tsx +40 -13
  258. package/src/hooks/_header.ts +5 -20
  259. package/src/libs/agent-runtime/BaseAI.ts +17 -1
  260. package/src/libs/agent-runtime/anthropic/index.ts +3 -7
  261. package/src/libs/agent-runtime/azureOpenai/index.test.ts +166 -0
  262. package/src/libs/agent-runtime/azureOpenai/index.ts +16 -8
  263. package/src/libs/agent-runtime/bedrock/index.test.ts +199 -22
  264. package/src/libs/agent-runtime/bedrock/index.ts +11 -18
  265. package/src/libs/agent-runtime/groq/index.test.ts +350 -0
  266. package/src/libs/agent-runtime/groq/index.ts +14 -77
  267. package/src/libs/agent-runtime/mistral/index.test.ts +25 -19
  268. package/src/libs/agent-runtime/mistral/index.ts +24 -86
  269. package/src/libs/agent-runtime/moonshot/index.test.ts +2 -2
  270. package/src/libs/agent-runtime/moonshot/index.ts +14 -77
  271. package/src/libs/agent-runtime/openai/__snapshots__/index.test.ts.snap +99 -0
  272. package/src/libs/agent-runtime/openai/fixtures/openai-models.json +170 -0
  273. package/src/libs/agent-runtime/openai/index.test.ts +15 -50
  274. package/src/libs/agent-runtime/openai/index.ts +15 -107
  275. package/src/libs/agent-runtime/openrouter/__snapshots__/index.test.ts.snap +82 -0
  276. package/src/libs/agent-runtime/openrouter/fixtures/models.json +62 -0
  277. package/src/libs/agent-runtime/openrouter/index.test.ts +25 -9
  278. package/src/libs/agent-runtime/openrouter/index.ts +42 -84
  279. package/src/libs/agent-runtime/openrouter/type.ts +28 -0
  280. package/src/libs/agent-runtime/togetherai/index.test.ts +12 -9
  281. package/src/libs/agent-runtime/togetherai/index.ts +20 -85
  282. package/src/libs/agent-runtime/utils/anthropicHelpers.test.ts +14 -22
  283. package/src/libs/agent-runtime/utils/anthropicHelpers.ts +4 -10
  284. package/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts +147 -0
  285. package/src/libs/agent-runtime/zeroone/index.test.ts +350 -0
  286. package/src/libs/agent-runtime/zeroone/index.ts +14 -77
  287. package/src/locales/default/common.ts +0 -28
  288. package/src/locales/default/components.ts +15 -0
  289. package/src/locales/default/error.ts +2 -54
  290. package/src/locales/default/index.ts +4 -0
  291. package/src/locales/default/modelProvider.ts +229 -0
  292. package/src/locales/default/setting.ts +51 -202
  293. package/src/migrations/FromV3ToV4/fixtures/azure-input-v3.json +79 -0
  294. package/src/migrations/FromV3ToV4/fixtures/azure-output-v4.json +75 -0
  295. package/src/migrations/FromV3ToV4/fixtures/ollama-input-v3.json +85 -0
  296. package/src/migrations/FromV3ToV4/fixtures/ollama-output-v4.json +86 -0
  297. package/src/migrations/FromV3ToV4/fixtures/openai-input-v3.json +77 -0
  298. package/src/migrations/FromV3ToV4/fixtures/openai-output-v4.json +79 -0
  299. package/src/migrations/FromV3ToV4/fixtures/openrouter-input-v3.json +82 -0
  300. package/src/migrations/FromV3ToV4/fixtures/openrouter-output-v4.json +89 -0
  301. package/src/migrations/FromV3ToV4/fixtures/output-v4-from-v1.json +203 -0
  302. package/src/migrations/FromV3ToV4/index.ts +96 -0
  303. package/src/migrations/FromV3ToV4/migrations.test.ts +195 -0
  304. package/src/migrations/FromV3ToV4/types/v3.ts +59 -0
  305. package/src/migrations/FromV3ToV4/types/v4.ts +37 -0
  306. package/src/migrations/index.ts +11 -3
  307. package/src/services/_auth.test.ts +4 -6
  308. package/src/services/_auth.ts +8 -60
  309. package/src/services/_header.ts +5 -22
  310. package/src/services/_url.ts +1 -0
  311. package/src/services/chat.ts +16 -6
  312. package/src/services/global.ts +1 -1
  313. package/src/services/models.ts +23 -0
  314. package/src/services/ollama.ts +2 -2
  315. package/src/store/chat/slices/share/action.test.ts +113 -0
  316. package/src/store/chat/slices/share/action.ts +1 -1
  317. package/src/store/global/slices/common/action.test.ts +166 -1
  318. package/src/store/global/slices/common/action.ts +2 -1
  319. package/src/store/global/slices/settings/{action.test.ts → actions/general.test.ts} +1 -19
  320. package/src/store/global/slices/settings/{action.ts → actions/general.ts} +4 -19
  321. package/src/store/global/slices/settings/actions/index.ts +18 -0
  322. package/src/store/global/slices/settings/actions/llm.test.ts +60 -0
  323. package/src/store/global/slices/settings/actions/llm.ts +88 -0
  324. package/src/store/global/slices/settings/initialState.ts +3 -1
  325. package/src/store/global/slices/settings/reducers/customModelCard.test.ts +204 -0
  326. package/src/store/global/slices/settings/reducers/customModelCard.ts +64 -0
  327. package/src/store/global/slices/settings/selectors/index.ts +1 -0
  328. package/src/store/global/slices/settings/selectors/modelConfig.test.ts +189 -0
  329. package/src/store/global/slices/settings/selectors/modelConfig.ts +179 -0
  330. package/src/store/global/slices/settings/selectors/modelProvider.test.ts +47 -138
  331. package/src/store/global/slices/settings/selectors/modelProvider.ts +102 -243
  332. package/src/store/global/store.ts +1 -1
  333. package/src/types/llm.ts +12 -1
  334. package/src/types/serverConfig.ts +22 -0
  335. package/src/types/settings/index.ts +0 -12
  336. package/src/types/settings/modelProvider.ts +34 -90
  337. package/src/utils/client/switchLang.test.ts +34 -0
  338. package/src/utils/difference.test.ts +46 -0
  339. package/src/utils/difference.ts +15 -2
  340. package/src/utils/fetch.ts +1 -3
  341. package/src/utils/parseModels.ts +62 -0
  342. package/vercel.json +1 -1
  343. package/docs/package.json +0 -5
  344. package/src/features/Conversation/Error/APIKeyForm/Anthropic.tsx +0 -40
  345. package/src/features/Conversation/Error/APIKeyForm/Google.tsx +0 -61
  346. package/src/features/Conversation/Error/APIKeyForm/Groq.tsx +0 -60
  347. package/src/features/Conversation/Error/APIKeyForm/Mistral.tsx +0 -60
  348. package/src/features/Conversation/Error/APIKeyForm/Moonshot.tsx +0 -60
  349. package/src/features/Conversation/Error/APIKeyForm/OpenAI.tsx +0 -63
  350. package/src/features/Conversation/Error/APIKeyForm/OpenRouter.tsx +0 -40
  351. package/src/features/Conversation/Error/APIKeyForm/Perplexity.tsx +0 -60
  352. package/src/features/Conversation/Error/APIKeyForm/TogetherAI.tsx +0 -40
  353. package/src/features/Conversation/Error/APIKeyForm/ZeroOne.tsx +0 -60
  354. package/src/features/Conversation/Error/APIKeyForm/Zhipu.tsx +0 -62
  355. package/src/libs/agent-runtime/utils/env.ts +0 -1
  356. package/src/store/global/slices/settings/selectors/__snapshots__/modelProvider.test.ts.snap +0 -230
  357. /package/src/app/api/chat/{auth.ts → auth/utils.ts} +0 -0
  358. /package/src/components/{AntdStaticMethods.tsx → AntdStaticMethods/index.tsx} +0 -0
@@ -0,0 +1,88 @@
1
+ import { InputNumber, Slider, SliderSingleProps } from 'antd';
2
+ import { memo } from 'react';
3
+ import { Flexbox } from 'react-layout-kit';
4
+ import useMergeState from 'use-merge-value';
5
+
6
+ const exponent = (num: number) => Math.log2(num);
7
+ const getRealValue = (num: number) => Math.round(Math.pow(2, num));
8
+
9
+ const marks: SliderSingleProps['marks'] = {
10
+ [exponent(1)]: '1k',
11
+ [exponent(2)]: '2k',
12
+ [exponent(4)]: '4k',
13
+ [exponent(8)]: '8k',
14
+ [exponent(16)]: '16k',
15
+ [exponent(32)]: '32k',
16
+ [exponent(64)]: '64k',
17
+ [exponent(128)]: '128k',
18
+ [exponent(200)]: '200k',
19
+ [exponent(1000)]: '1M',
20
+ };
21
+
22
+ interface MaxTokenSliderProps {
23
+ defaultValue?: number;
24
+ onChange?: (value: number) => void;
25
+ value?: number;
26
+ }
27
+
28
+ const MaxTokenSlider = memo<MaxTokenSliderProps>(({ value, onChange, defaultValue }) => {
29
+ const [token, setTokens] = useMergeState(0, {
30
+ defaultValue,
31
+ onChange,
32
+ value: value,
33
+ });
34
+
35
+ const [powValue, setPowValue] = useMergeState(0, {
36
+ defaultValue: exponent(typeof defaultValue === 'undefined' ? 0 : defaultValue / 1000),
37
+ value: exponent(typeof value === 'undefined' ? 0 : value / 1000),
38
+ });
39
+
40
+ const updateWithPowValue = (value: number) => {
41
+ setPowValue(value);
42
+
43
+ setTokens(getRealValue(value) * 1024);
44
+ };
45
+ const updateWithRealValue = (value: number) => {
46
+ setTokens(value);
47
+
48
+ setPowValue(exponent(value / 1024));
49
+ };
50
+
51
+ return (
52
+ <Flexbox align={'center'} gap={12} horizontal>
53
+ <Flexbox flex={1}>
54
+ <Slider
55
+ marks={marks}
56
+ max={exponent(1000)}
57
+ min={0}
58
+ onChange={updateWithPowValue}
59
+ step={1}
60
+ tooltip={{
61
+ formatter: (x) => {
62
+ if (typeof x === 'undefined') return;
63
+
64
+ const value = getRealValue(x);
65
+
66
+ if (value < 1000) return value.toFixed(0) + 'K';
67
+
68
+ return (value / 1000).toFixed(0) + 'M';
69
+ },
70
+ }}
71
+ value={powValue}
72
+ />
73
+ </Flexbox>
74
+ <div>
75
+ <InputNumber
76
+ onChange={(e) => {
77
+ if (!e) return;
78
+
79
+ updateWithRealValue(e);
80
+ }}
81
+ step={1024}
82
+ value={token}
83
+ />
84
+ </div>
85
+ </Flexbox>
86
+ );
87
+ });
88
+ export default MaxTokenSlider;
@@ -0,0 +1,128 @@
1
+ import { Modal } from '@lobehub/ui';
2
+ import { Checkbox, Form, Input } from 'antd';
3
+ import isEqual from 'fast-deep-equal';
4
+ import { memo } from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ import { useGlobalStore } from '@/store/global';
8
+ import { modelConfigSelectors } from '@/store/global/slices/settings/selectors';
9
+
10
+ import MaxTokenSlider from './MaxTokenSlider';
11
+
12
+ interface ModelConfigModalProps {
13
+ provider?: string;
14
+ showAzureDeployName?: boolean;
15
+ }
16
+ const ModelConfigModal = memo<ModelConfigModalProps>(({ showAzureDeployName, provider }) => {
17
+ const [formInstance] = Form.useForm();
18
+ const { t } = useTranslation('setting');
19
+
20
+ const [open, id, editingProvider, dispatchCustomModelCards, toggleEditingCustomModelCard] =
21
+ useGlobalStore((s) => [
22
+ !!s.editingCustomCardModel && provider === s.editingCustomCardModel?.provider,
23
+ s.editingCustomCardModel?.id,
24
+ s.editingCustomCardModel?.provider,
25
+ s.dispatchCustomModelCards,
26
+ s.toggleEditingCustomModelCard,
27
+ ]);
28
+
29
+ const modelCard = useGlobalStore(
30
+ modelConfigSelectors.getCustomModelCardById({ id, provider: editingProvider }),
31
+ isEqual,
32
+ );
33
+
34
+ const closeModal = () => {
35
+ toggleEditingCustomModelCard(undefined);
36
+ };
37
+
38
+ return (
39
+ <Modal
40
+ destroyOnClose
41
+ maskClosable
42
+ onCancel={() => {
43
+ closeModal();
44
+ }}
45
+ onOk={() => {
46
+ if (!editingProvider || !id) return;
47
+ const data = formInstance.getFieldsValue();
48
+
49
+ dispatchCustomModelCards(editingProvider as any, { id, type: 'update', value: data });
50
+
51
+ closeModal();
52
+ }}
53
+ open={open}
54
+ title={t('llm.customModelCards.modelConfig.modalTitle')}
55
+ >
56
+ <div
57
+ onClick={(e) => {
58
+ e.stopPropagation();
59
+ }}
60
+ onKeyDown={(e) => {
61
+ e.stopPropagation();
62
+ }}
63
+ >
64
+ <Form
65
+ colon={false}
66
+ form={formInstance}
67
+ initialValues={modelCard}
68
+ labelCol={{ span: 4 }}
69
+ style={{ marginTop: 16 }}
70
+ wrapperCol={{ offset: 1, span: 18 }}
71
+ >
72
+ <Form.Item
73
+ extra={t('llm.customModelCards.modelConfig.id.extra')}
74
+ label={t('llm.customModelCards.modelConfig.id.title')}
75
+ name={'id'}
76
+ >
77
+ <Input placeholder={t('llm.customModelCards.modelConfig.id.placeholder')} />
78
+ </Form.Item>
79
+ {showAzureDeployName && (
80
+ <Form.Item
81
+ extra={t('llm.customModelCards.modelConfig.azureDeployName.extra')}
82
+ label={t('llm.customModelCards.modelConfig.azureDeployName.title')}
83
+ name={'deploymentName'}
84
+ >
85
+ <Input
86
+ placeholder={t('llm.customModelCards.modelConfig.azureDeployName.placeholder')}
87
+ />
88
+ </Form.Item>
89
+ )}
90
+ <Form.Item
91
+ label={t('llm.customModelCards.modelConfig.displayName.title')}
92
+ name={'displayName'}
93
+ >
94
+ <Input placeholder={t('llm.customModelCards.modelConfig.displayName.placeholder')} />
95
+ </Form.Item>
96
+ <Form.Item label={t('llm.customModelCards.modelConfig.tokens.title')} name={'tokens'}>
97
+ <MaxTokenSlider />
98
+ </Form.Item>
99
+ <Form.Item
100
+ extra={t('llm.customModelCards.modelConfig.functionCall.extra')}
101
+ label={t('llm.customModelCards.modelConfig.functionCall.title')}
102
+ name={'functionCall'}
103
+ valuePropName={'checked'}
104
+ >
105
+ <Checkbox />
106
+ </Form.Item>
107
+ <Form.Item
108
+ extra={t('llm.customModelCards.modelConfig.vision.extra')}
109
+ label={t('llm.customModelCards.modelConfig.vision.title')}
110
+ name={'vision'}
111
+ valuePropName={'checked'}
112
+ >
113
+ <Checkbox />
114
+ </Form.Item>
115
+ <Form.Item
116
+ extra={t('llm.customModelCards.modelConfig.files.extra')}
117
+ label={t('llm.customModelCards.modelConfig.files.title')}
118
+ name={'files'}
119
+ valuePropName={'checked'}
120
+ >
121
+ <Checkbox />
122
+ </Form.Item>
123
+ </Form>
124
+ </div>
125
+ </Modal>
126
+ );
127
+ });
128
+ export default ModelConfigModal;
@@ -0,0 +1,81 @@
1
+ import { Icon, Tooltip } from '@lobehub/ui';
2
+ import { Typography } from 'antd';
3
+ import { createStyles } from 'antd-style';
4
+ import dayjs from 'dayjs';
5
+ import { LucideLoaderCircle, LucideRefreshCcwDot } from 'lucide-react';
6
+ import { memo } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+ import { Flexbox } from 'react-layout-kit';
9
+
10
+ import { useGlobalStore } from '@/store/global';
11
+ import { modelConfigSelectors } from '@/store/global/selectors';
12
+ import { GlobalLLMProviderKey } from '@/types/settings';
13
+
14
+ const useStyles = createStyles(({ css, token }) => ({
15
+ hover: css`
16
+ cursor: pointer;
17
+ padding: 4px 8px;
18
+ border-radius: ${token.borderRadius}px;
19
+ transition: all 0.2s ease-in-out;
20
+
21
+ &:hover {
22
+ color: ${token.colorText};
23
+ background-color: ${token.colorFillSecondary};
24
+ }
25
+ `,
26
+ }));
27
+
28
+ interface ModelFetcherProps {
29
+ provider: GlobalLLMProviderKey;
30
+ }
31
+
32
+ const ModelFetcher = memo<ModelFetcherProps>(({ provider }) => {
33
+ const { styles } = useStyles();
34
+ const { t } = useTranslation('setting');
35
+ const [useFetchProviderModelList] = useGlobalStore((s) => [
36
+ s.useFetchProviderModelList,
37
+ s.setModelProviderConfig,
38
+ ]);
39
+ const enabledAutoFetch = useGlobalStore(modelConfigSelectors.enabledAutoFetchModels(provider));
40
+ const latestFetchTime = useGlobalStore(
41
+ (s) => modelConfigSelectors.providerConfig(provider)(s)?.latestFetchTime,
42
+ );
43
+ const totalModels = useGlobalStore(
44
+ (s) => modelConfigSelectors.providerModelCards(provider)(s).length,
45
+ );
46
+
47
+ const { mutate, isValidating } = useFetchProviderModelList(provider, enabledAutoFetch);
48
+
49
+ return (
50
+ <Typography.Text style={{ fontSize: 12 }} type={'secondary'}>
51
+ <Flexbox align={'center'} gap={0} horizontal justify={'space-between'}>
52
+ <div>{t('llm.modelList.total', { count: totalModels })}</div>
53
+ <Tooltip
54
+ title={
55
+ latestFetchTime
56
+ ? t('llm.fetcher.latestTime', {
57
+ time: dayjs(latestFetchTime).format('YYYY-MM-DD HH:mm:ss'),
58
+ })
59
+ : t('llm.fetcher.noLatestTime')
60
+ }
61
+ >
62
+ <Flexbox
63
+ align={'center'}
64
+ className={styles.hover}
65
+ gap={4}
66
+ horizontal
67
+ onClick={() => mutate()}
68
+ >
69
+ <Icon
70
+ icon={isValidating ? LucideLoaderCircle : LucideRefreshCcwDot}
71
+ size={'small'}
72
+ spin={isValidating}
73
+ />
74
+ <div>{isValidating ? t('llm.fetcher.fetching') : t('llm.fetcher.fetch')}</div>
75
+ </Flexbox>
76
+ </Tooltip>
77
+ </Flexbox>
78
+ </Typography.Text>
79
+ );
80
+ });
81
+ export default ModelFetcher;
@@ -0,0 +1,38 @@
1
+ import { Typography } from 'antd';
2
+ import isEqual from 'fast-deep-equal';
3
+ import { memo } from 'react';
4
+ import { Flexbox } from 'react-layout-kit';
5
+
6
+ import ModelIcon from '@/components/ModelIcon';
7
+ import { ModelInfoTags } from '@/components/ModelSelect';
8
+ import { useGlobalStore } from '@/store/global';
9
+ import { modelProviderSelectors } from '@/store/global/selectors';
10
+ import { GlobalLLMProviderKey } from '@/types/settings';
11
+
12
+ import CustomModelOption from './CustomModelOption';
13
+
14
+ const OptionRender = memo<{ displayName: string; id: string; provider: GlobalLLMProviderKey }>(
15
+ ({ displayName, id, provider }) => {
16
+ const model = useGlobalStore((s) => modelProviderSelectors.modelCardById(id)(s), isEqual);
17
+
18
+ // if there is no model, it means it is a user custom model
19
+ if (!model) return <CustomModelOption id={id} provider={provider} />;
20
+
21
+ return (
22
+ <Flexbox align={'center'} gap={8} horizontal>
23
+ <ModelIcon model={id} size={32} />
24
+ <Flexbox>
25
+ <Flexbox align={'center'} gap={8} horizontal>
26
+ {displayName}
27
+ <ModelInfoTags directionReverse placement={'top'} {...model!} />
28
+ </Flexbox>
29
+ <Typography.Text style={{ fontSize: 12 }} type={'secondary'}>
30
+ {id}
31
+ </Typography.Text>
32
+ </Flexbox>
33
+ </Flexbox>
34
+ );
35
+ },
36
+ );
37
+
38
+ export default OptionRender;
@@ -0,0 +1,142 @@
1
+ import { ActionIcon } from '@lobehub/ui';
2
+ import { Select } from 'antd';
3
+ import { css, cx } from 'antd-style';
4
+ import isEqual from 'fast-deep-equal';
5
+ import { RotateCwIcon } from 'lucide-react';
6
+ import { ReactNode, memo } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+ import { Flexbox } from 'react-layout-kit';
9
+
10
+ import { useGlobalStore } from '@/store/global';
11
+ import { modelConfigSelectors, modelProviderSelectors } from '@/store/global/selectors';
12
+ import { GlobalLLMProviderKey } from '@/types/settings';
13
+
14
+ import ModelConfigModal from './ModelConfigModal';
15
+ import ModelFetcher from './ModelFetcher';
16
+ import OptionRender from './Option';
17
+
18
+ const styles = {
19
+ popup: css`
20
+ &.ant-select-dropdown {
21
+ .ant-select-item-option-selected {
22
+ font-weight: normal;
23
+ }
24
+ }
25
+ `,
26
+ reset: css`
27
+ position: absolute;
28
+ z-index: 20;
29
+ top: 50%;
30
+ inset-inline-end: 28px;
31
+ transform: translateY(-50%);
32
+ `,
33
+ };
34
+
35
+ interface CustomModelSelectProps {
36
+ notFoundContent?: ReactNode;
37
+ placeholder?: string;
38
+ provider: GlobalLLMProviderKey;
39
+ showAzureDeployName?: boolean;
40
+ showModelFetcher?: boolean;
41
+ }
42
+
43
+ const ProviderModelListSelect = memo<CustomModelSelectProps>(
44
+ ({ showModelFetcher = false, provider, showAzureDeployName, notFoundContent, placeholder }) => {
45
+ const { t } = useTranslation('common');
46
+ const { t: transSetting } = useTranslation('setting');
47
+ const [setModelProviderConfig, dispatchCustomModelCards] = useGlobalStore((s) => [
48
+ s.setModelProviderConfig,
49
+ s.dispatchCustomModelCards,
50
+ s.useFetchProviderModelList,
51
+ ]);
52
+
53
+ const chatModelCards = useGlobalStore(
54
+ modelConfigSelectors.providerModelCards(provider),
55
+ isEqual,
56
+ );
57
+
58
+ const defaultEnableModel = useGlobalStore(
59
+ modelProviderSelectors.defaultEnabledProviderModels(provider),
60
+ isEqual,
61
+ );
62
+ const enabledModels = useGlobalStore(
63
+ modelConfigSelectors.providerEnableModels(provider),
64
+ isEqual,
65
+ );
66
+
67
+ const showReset = !!enabledModels && !isEqual(defaultEnableModel, enabledModels);
68
+
69
+ return (
70
+ <>
71
+ <Flexbox gap={8}>
72
+ <div style={{ position: 'relative' }}>
73
+ <div className={cx(styles.reset)}>
74
+ {showReset && (
75
+ <ActionIcon
76
+ icon={RotateCwIcon}
77
+ onClick={() => {
78
+ setModelProviderConfig(provider, { enabledModels: null });
79
+ }}
80
+ size={'small'}
81
+ title={t('reset')}
82
+ />
83
+ )}
84
+ </div>
85
+ <Select<string[]>
86
+ allowClear
87
+ mode="tags"
88
+ notFoundContent={notFoundContent}
89
+ onChange={(value, options) => {
90
+ setModelProviderConfig(provider, { enabledModels: value.filter(Boolean) });
91
+
92
+ // if there is a new model, add it to `customModelCards`
93
+ options.forEach((option: { label?: string; value?: string }, index: number) => {
94
+ // if is a known model, it should have value
95
+ // if is an unknown model, the option will be {}
96
+ if (option.value) return;
97
+
98
+ const modelId = value[index];
99
+
100
+ dispatchCustomModelCards(provider, {
101
+ modelCard: { id: modelId },
102
+ type: 'add',
103
+ });
104
+ });
105
+ }}
106
+ optionFilterProp="label"
107
+ optionRender={({ label, value }) => {
108
+ // model is in the chatModels
109
+ if (chatModelCards.some((c) => c.id === value))
110
+ return (
111
+ <OptionRender
112
+ displayName={label as string}
113
+ id={value as string}
114
+ provider={provider}
115
+ />
116
+ );
117
+
118
+ // model is defined by user in client
119
+ return (
120
+ <Flexbox align={'center'} gap={8} horizontal>
121
+ {transSetting('llm.customModelCards.addNew', { id: value })}
122
+ </Flexbox>
123
+ );
124
+ }}
125
+ options={chatModelCards.map((model) => ({
126
+ label: model.displayName || model.id,
127
+ value: model.id,
128
+ }))}
129
+ placeholder={placeholder}
130
+ popupClassName={cx(styles.popup)}
131
+ value={enabledModels ?? defaultEnableModel}
132
+ />
133
+ </div>
134
+ {showModelFetcher && <ModelFetcher provider={provider} />}
135
+ </Flexbox>
136
+ <ModelConfigModal provider={provider} showAzureDeployName={showAzureDeployName} />
137
+ </>
138
+ );
139
+ },
140
+ );
141
+
142
+ export default ProviderModelListSelect;
@@ -16,4 +16,4 @@ export const LLMProviderBaseUrlKey = 'endpoint';
16
16
  * we use this key to define the custom model name
17
17
  * equal CUSTOM_MODELS
18
18
  */
19
- export const LLMProviderCustomModelKey = 'customModelName';
19
+ export const LLMProviderModelListKey = 'enabledModels';
@@ -9,6 +9,7 @@ import { MORE_MODEL_PROVIDER_REQUEST_URL } from '@/const/url';
9
9
 
10
10
  import Footer from '../features/Footer';
11
11
  import Anthropic from './Anthropic';
12
+ import Azure from './Azure';
12
13
  import Bedrock from './Bedrock';
13
14
  import Google from './Google';
14
15
  import Groq from './Groq';
@@ -29,19 +30,19 @@ export default memo<{ showOllama: boolean }>(({ showOllama }) => {
29
30
  <>
30
31
  <PageTitle title={t('tab.llm')} />
31
32
  <OpenAI />
32
- {/*<AzureOpenAI />*/}
33
+ <Azure />
33
34
  {showOllama && <Ollama />}
34
- <Anthropic />
35
35
  <Google />
36
- <Groq />
36
+ <Anthropic />
37
37
  <Bedrock />
38
+ <OpenRouter />
39
+ <TogetherAI />
40
+ <Groq />
38
41
  <Perplexity />
39
42
  <Mistral />
40
- <OpenRouter />
41
43
  <Moonshot />
42
- <ZeroOne />
43
44
  <Zhipu />
44
- <TogetherAI />
45
+ <ZeroOne />
45
46
  <Footer>
46
47
  <Trans i18nKey="llm.waitingForMore" ns={'setting'}>
47
48
  更多模型正在
@@ -57,7 +57,7 @@ const TTS = memo(() => {
57
57
  },
58
58
  ],
59
59
  icon: Webhook,
60
- title: t('llm.openai.title'),
60
+ title: t('settingTTS.openai.title'),
61
61
  };
62
62
 
63
63
  return (
@@ -0,0 +1,43 @@
1
+ // EntryComponent.test.tsx
2
+ import { render } from '@testing-library/react';
3
+ import { App } from 'antd';
4
+ import { describe, expect, it, vi } from 'vitest';
5
+
6
+ import EntryComponent, { message, modal, notification } from './index';
7
+
8
+ // 模拟 App.useApp 方法返回的对象
9
+ const mockUseApp = {
10
+ message: { success: vi.fn() },
11
+ modal: { confirm: vi.fn() },
12
+ notification: { open: vi.fn() },
13
+ };
14
+
15
+ vi.mock('antd', () => ({
16
+ App: {
17
+ useApp: vi.fn(() => mockUseApp),
18
+ },
19
+ }));
20
+
21
+ describe('EntryComponent', () => {
22
+ it('should correctly initialize message, modal, and notification', () => {
23
+ render(<EntryComponent />);
24
+
25
+ // 验证 App.useApp 是否被调用
26
+ expect(App.useApp).toHaveBeenCalled();
27
+
28
+ // 验证 message, modal, 和 notification 是否被正确赋值
29
+ expect(message).toBeDefined();
30
+ expect(modal).toBeDefined();
31
+ expect(notification).toBeDefined();
32
+
33
+ // 验证是否赋值的对象与模拟的对象匹配
34
+ expect(message).toEqual(mockUseApp.message);
35
+ expect(modal).toEqual(mockUseApp.modal);
36
+ expect(notification).toEqual(mockUseApp.notification);
37
+ });
38
+
39
+ it('should render without crashing', () => {
40
+ const { container } = render(<EntryComponent />);
41
+ expect(container).toBeDefined();
42
+ });
43
+ });
@@ -3,16 +3,21 @@ import {
3
3
  Baichuan,
4
4
  ChatGLM,
5
5
  Claude,
6
+ Cohere,
6
7
  Gemini,
7
8
  Gemma,
9
+ Hunyuan,
8
10
  LLaVA,
9
11
  Meta,
10
12
  Minimax,
11
13
  Mistral,
12
14
  Moonshot,
13
15
  OpenAI,
16
+ OpenRouter,
14
17
  Perplexity,
18
+ Spark,
15
19
  Tongyi,
20
+ Wenxin,
16
21
  Yi,
17
22
  } from '@lobehub/icons';
18
23
  import { memo } from 'react';
@@ -22,12 +27,15 @@ interface ModelProviderIconProps {
22
27
  size?: number;
23
28
  }
24
29
 
25
- const ModelIcon = memo<ModelProviderIconProps>(({ model, size = 12 }) => {
26
- if (!model) return;
30
+ const ModelIcon = memo<ModelProviderIconProps>(({ model: originModel, size = 12 }) => {
31
+ if (!originModel) return;
27
32
 
28
- if (model.startsWith('gpt-3')) return <OpenAI.Avatar size={size} type={'gpt3'} />;
29
- if (model.startsWith('gpt-4')) return <OpenAI.Avatar size={size} type={'gpt4'} />;
30
- if (model.startsWith('glm')) return <ChatGLM.Avatar size={size} />;
33
+ // lower case the origin model so to better match more model id case
34
+ const model = originModel.toLowerCase();
35
+
36
+ if (model.includes('gpt-3')) return <OpenAI.Avatar size={size} type={'gpt3'} />;
37
+ if (model.includes('gpt-4')) return <OpenAI.Avatar size={size} type={'gpt4'} />;
38
+ if (model.startsWith('glm') || model.includes('chatglm')) return <ChatGLM.Avatar size={size} />;
31
39
  if (model.includes('claude')) return <Claude.Avatar size={size} />;
32
40
  if (model.includes('titan')) return <Aws.Avatar size={size} />;
33
41
  if (model.includes('llama')) return <Meta.Avatar size={size} />;
@@ -39,9 +47,19 @@ const ModelIcon = memo<ModelProviderIconProps>(({ model, size = 12 }) => {
39
47
  if (model.includes('moonshot')) return <Moonshot.Avatar size={size} />;
40
48
  if (model.includes('baichuan'))
41
49
  return <Baichuan.Avatar background={Baichuan.colorPrimary} size={size} />;
50
+
42
51
  if (model.includes('mistral') || model.includes('mixtral')) return <Mistral.Avatar size={size} />;
43
- if (model.includes('pplx')) return <Perplexity.Avatar size={size} />;
44
- if (model.startsWith('yi-')) return <Yi.Avatar size={size} />;
52
+
53
+ if (model.includes('pplx') || model.includes('sonar')) return <Perplexity.Avatar size={size} />;
54
+
55
+ if (model.includes('yi-')) return <Yi.Avatar size={size} />;
56
+ if (model.includes('openrouter')) return <OpenRouter.Avatar size={size} />;
57
+ if (model.includes('command')) return <Cohere.Color size={size} />;
58
+
59
+ if (model.includes('ernie')) return <Wenxin.Avatar size={size} />;
60
+ if (model.includes('spark')) return <Spark.Avatar size={size} />;
61
+ if (model.includes('hunyuan')) return <Hunyuan.Avatar size={size} />;
62
+ if (model.includes('abab')) return <Minimax.Avatar size={size} />;
45
63
  });
46
64
 
47
65
  export default ModelIcon;