@lobehub/chat 0.122.9 → 0.123.1

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 (231) hide show
  1. package/.env.example +22 -2
  2. package/.eslintrc.js +1 -0
  3. package/CHANGELOG.md +59 -0
  4. package/Dockerfile +7 -1
  5. package/README.md +12 -10
  6. package/README.zh-CN.md +12 -10
  7. package/docs/Deployment/Docker-Deployment.md +1 -1
  8. package/docs/Deployment/Docker-Deployment.zh-CN.md +1 -1
  9. package/docs/Deployment/Environment-Variable.md +65 -23
  10. package/docs/Deployment/Environment-Variable.zh-CN.md +64 -22
  11. package/locales/ar/chat.json +12 -1
  12. package/locales/ar/common.json +16 -0
  13. package/locales/ar/error.json +35 -6
  14. package/locales/ar/setting.json +53 -6
  15. package/locales/de-DE/chat.json +12 -1
  16. package/locales/de-DE/common.json +16 -0
  17. package/locales/de-DE/error.json +35 -6
  18. package/locales/de-DE/setting.json +53 -6
  19. package/locales/en-US/chat.json +13 -2
  20. package/locales/en-US/common.json +16 -0
  21. package/locales/en-US/error.json +35 -6
  22. package/locales/en-US/setting.json +53 -6
  23. package/locales/es-ES/chat.json +12 -1
  24. package/locales/es-ES/common.json +16 -0
  25. package/locales/es-ES/error.json +35 -6
  26. package/locales/es-ES/setting.json +53 -6
  27. package/locales/fr-FR/chat.json +13 -2
  28. package/locales/fr-FR/common.json +16 -0
  29. package/locales/fr-FR/error.json +35 -6
  30. package/locales/fr-FR/setting.json +53 -6
  31. package/locales/it-IT/chat.json +12 -1
  32. package/locales/it-IT/common.json +16 -0
  33. package/locales/it-IT/error.json +35 -6
  34. package/locales/it-IT/setting.json +53 -6
  35. package/locales/ja-JP/chat.json +12 -1
  36. package/locales/ja-JP/common.json +16 -0
  37. package/locales/ja-JP/error.json +35 -6
  38. package/locales/ja-JP/setting.json +53 -6
  39. package/locales/ko-KR/chat.json +12 -1
  40. package/locales/ko-KR/common.json +16 -0
  41. package/locales/ko-KR/error.json +35 -6
  42. package/locales/ko-KR/setting.json +53 -6
  43. package/locales/nl-NL/chat.json +12 -1
  44. package/locales/nl-NL/common.json +16 -0
  45. package/locales/nl-NL/error.json +35 -6
  46. package/locales/nl-NL/setting.json +53 -6
  47. package/locales/pl-PL/chat.json +12 -1
  48. package/locales/pl-PL/common.json +16 -0
  49. package/locales/pl-PL/error.json +35 -6
  50. package/locales/pl-PL/setting.json +53 -6
  51. package/locales/pt-BR/chat.json +12 -1
  52. package/locales/pt-BR/common.json +16 -0
  53. package/locales/pt-BR/error.json +35 -6
  54. package/locales/pt-BR/setting.json +53 -6
  55. package/locales/ru-RU/chat.json +12 -1
  56. package/locales/ru-RU/common.json +16 -0
  57. package/locales/ru-RU/error.json +35 -6
  58. package/locales/ru-RU/setting.json +53 -6
  59. package/locales/tr-TR/chat.json +12 -1
  60. package/locales/tr-TR/common.json +16 -0
  61. package/locales/tr-TR/error.json +35 -6
  62. package/locales/tr-TR/setting.json +53 -6
  63. package/locales/vi-VN/chat.json +12 -1
  64. package/locales/vi-VN/common.json +16 -0
  65. package/locales/vi-VN/error.json +35 -6
  66. package/locales/vi-VN/setting.json +53 -6
  67. package/locales/zh-CN/chat.json +12 -1
  68. package/locales/zh-CN/common.json +16 -0
  69. package/locales/zh-CN/error.json +34 -5
  70. package/locales/zh-CN/setting.json +59 -12
  71. package/locales/zh-TW/chat.json +12 -1
  72. package/locales/zh-TW/common.json +16 -0
  73. package/locales/zh-TW/error.json +35 -6
  74. package/locales/zh-TW/setting.json +53 -6
  75. package/next.config.mjs +8 -2
  76. package/package.json +8 -2
  77. package/src/app/api/chat/[provider]/agentRuntime.ts +129 -0
  78. package/src/app/api/chat/[provider]/route.ts +64 -0
  79. package/src/app/api/chat/auth.ts +42 -0
  80. package/src/app/api/chat/google/route.ts +86 -0
  81. package/src/app/api/config/route.ts +6 -1
  82. package/src/app/api/config.ts +3 -3
  83. package/src/app/api/errorResponse.test.ts +8 -8
  84. package/src/app/api/errorResponse.ts +43 -6
  85. package/src/app/api/openai/createBizOpenAI/createAzureOpenai.ts +1 -1
  86. package/src/app/api/openai/createBizOpenAI/createOpenai.ts +1 -1
  87. package/src/app/api/openai/createBizOpenAI/index.ts +2 -2
  88. package/src/app/api/plugin/gateway/route.ts +4 -1
  89. package/src/app/chat/(desktop)/features/ChatHeader.tsx +6 -4
  90. package/src/app/chat/(desktop)/features/ChatInput/Footer/index.tsx +13 -3
  91. package/src/app/chat/(desktop)/features/ChatInput/Header/index.tsx +16 -24
  92. package/src/app/chat/(desktop)/features/SideBar/index.tsx +1 -0
  93. package/src/app/chat/features/ChatHeader/ShareButton/Preview.tsx +3 -3
  94. package/src/app/chat/features/SessionListContent/List/Item/index.tsx +2 -3
  95. package/src/app/settings/llm/Azure/index.tsx +145 -0
  96. package/src/app/settings/llm/Bedrock/index.tsx +109 -0
  97. package/src/app/settings/llm/{LLM/Checker.tsx → Checker.tsx} +11 -14
  98. package/src/app/settings/llm/Google/index.tsx +74 -0
  99. package/src/app/settings/llm/{LLM → OpenAI}/index.tsx +26 -44
  100. package/src/app/settings/llm/Zhipu/index.tsx +78 -0
  101. package/src/app/settings/llm/const.ts +13 -0
  102. package/src/app/settings/llm/page.tsx +42 -2
  103. package/src/app/settings/llm/useSyncSettings.ts +23 -0
  104. package/src/chains/__tests__/langDetect.test.ts +2 -2
  105. package/src/chains/__tests__/pickEmoji.test.ts +2 -2
  106. package/src/chains/langDetect.ts +2 -2
  107. package/src/chains/pickEmoji.ts +2 -2
  108. package/src/chains/summaryAgentName.ts +2 -2
  109. package/src/chains/summaryDescription.ts +2 -2
  110. package/src/chains/summaryTags.ts +2 -2
  111. package/src/chains/summaryTitle.ts +2 -2
  112. package/src/chains/translate.ts +2 -2
  113. package/src/components/ModelIcon/index.tsx +37 -0
  114. package/src/components/ModelProviderIcon/index.tsx +44 -0
  115. package/src/components/ModelSelect/index.tsx +133 -0
  116. package/src/components/ModelTag/ModelIcon.tsx +35 -0
  117. package/src/components/ModelTag/index.tsx +13 -0
  118. package/src/config/modelProviders/bedrock.ts +43 -0
  119. package/src/config/modelProviders/google.ts +20 -0
  120. package/src/config/modelProviders/index.ts +18 -0
  121. package/src/config/modelProviders/openai.ts +110 -0
  122. package/src/config/modelProviders/zhipu.ts +34 -0
  123. package/src/config/{server.ts → server/app.ts} +1 -24
  124. package/src/config/server/index.ts +13 -0
  125. package/src/config/server/provider.ts +78 -0
  126. package/src/const/auth.ts +30 -0
  127. package/src/const/fetch.ts +3 -0
  128. package/src/const/settings.ts +24 -4
  129. package/src/database/core/migrations/migrateSettingsToUser/index.test.ts +2 -1
  130. package/src/database/core/migrations/migrateSettingsToUser/index.ts +1 -18
  131. package/src/database/core/migrations/migrateSettingsToUser/type.ts +100 -0
  132. package/src/database/models/message.ts +3 -1
  133. package/src/database/schemas/message.ts +1 -0
  134. package/src/database/schemas/session.ts +1 -0
  135. package/src/features/AgentSetting/AgentConfig/ModelSelect.tsx +71 -0
  136. package/src/features/AgentSetting/AgentConfig/index.tsx +171 -161
  137. package/src/features/AgentSetting/AgentConfig/useSyncConfig.ts +23 -0
  138. package/src/features/AgentSetting/AgentPrompt/TokenTag.tsx +39 -0
  139. package/src/features/AgentSetting/AgentPrompt/index.tsx +4 -26
  140. package/src/features/AgentSetting/store/index.ts +10 -2
  141. package/src/features/ChatInput/ActionBar/FileUpload.tsx +15 -5
  142. package/src/features/ChatInput/ActionBar/ModelSwitch.tsx +56 -14
  143. package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +42 -7
  144. package/src/features/ChatInput/ActionBar/Token/index.tsx +5 -2
  145. package/src/features/ChatInput/ActionBar/Tools/index.tsx +11 -1
  146. package/src/features/ChatInput/useChatInput.ts +5 -1
  147. package/src/features/Conversation/Error/APIKeyForm/Bedrock.tsx +80 -0
  148. package/src/features/Conversation/Error/APIKeyForm/Google.tsx +61 -0
  149. package/src/features/Conversation/Error/APIKeyForm/OpenAI.tsx +63 -0
  150. package/src/features/Conversation/Error/APIKeyForm/Zhipu.tsx +62 -0
  151. package/src/features/Conversation/Error/APIKeyForm/index.tsx +72 -0
  152. package/src/features/Conversation/Error/AccessCodeForm.tsx +63 -0
  153. package/src/features/Conversation/Error/ErrorJsonViewer.tsx +26 -0
  154. package/src/features/Conversation/Error/InvalidAPIKey.tsx +16 -0
  155. package/src/features/Conversation/Error/InvalidAccessCode.tsx +50 -0
  156. package/src/features/Conversation/Error/OpenAiBizError.tsx +9 -17
  157. package/src/features/Conversation/Error/{Plugin/PluginSettings.tsx → PluginSettings.tsx} +8 -3
  158. package/src/features/Conversation/Error/index.tsx +75 -70
  159. package/src/features/Conversation/Error/style.tsx +9 -3
  160. package/src/features/Conversation/Extras/Assistant.tsx +2 -3
  161. package/src/features/Conversation/Plugins/Inspector/index.tsx +8 -2
  162. package/src/features/Conversation/components/ChatItem/index.tsx +9 -24
  163. package/src/features/Conversation/types/index.tsx +2 -5
  164. package/src/hooks/_header.ts +35 -0
  165. package/src/libs/agent-runtime/BaseAI.ts +9 -0
  166. package/src/libs/agent-runtime/azureOpenai/index.ts +72 -0
  167. package/src/libs/agent-runtime/bedrock/index.ts +134 -0
  168. package/src/libs/agent-runtime/error.ts +26 -0
  169. package/src/libs/agent-runtime/google/index.ts +160 -0
  170. package/src/libs/agent-runtime/index.ts +9 -0
  171. package/src/libs/agent-runtime/openai/index.test.ts +176 -0
  172. package/src/libs/agent-runtime/openai/index.ts +107 -0
  173. package/src/libs/agent-runtime/types/chat.ts +119 -0
  174. package/src/libs/agent-runtime/types/index.ts +2 -0
  175. package/src/libs/agent-runtime/types/type.ts +34 -0
  176. package/src/libs/agent-runtime/utils/createError.ts +10 -0
  177. package/src/libs/agent-runtime/utils/debugStream.ts +18 -0
  178. package/src/libs/agent-runtime/utils/env.ts +1 -0
  179. package/src/libs/agent-runtime/utils/handleOpenAIError.ts +39 -0
  180. package/src/libs/agent-runtime/utils/uriParser.ts +16 -0
  181. package/src/libs/agent-runtime/zhipu/authToken.ts +22 -0
  182. package/src/libs/agent-runtime/zhipu/index.ts +125 -0
  183. package/src/locales/default/chat.ts +12 -2
  184. package/src/locales/default/common.ts +16 -0
  185. package/src/locales/default/error.ts +42 -5
  186. package/src/locales/default/setting.ts +61 -12
  187. package/src/services/__tests__/chat.test.ts +8 -2
  188. package/src/services/__tests__/message.test.ts +1 -1
  189. package/src/services/_auth.ts +106 -0
  190. package/src/services/_header.ts +1 -0
  191. package/src/services/_url.ts +0 -2
  192. package/src/services/chat.ts +34 -14
  193. package/src/store/chat/slices/message/action.ts +9 -6
  194. package/src/store/global/slices/common/action.ts +8 -2
  195. package/src/store/global/slices/settings/action.test.ts +2 -2
  196. package/src/store/global/slices/settings/action.ts +11 -4
  197. package/src/store/global/slices/settings/selectors/__snapshots__/modelProvider.test.ts.snap +24 -92
  198. package/src/store/global/slices/settings/selectors/__snapshots__/selectors.test.ts.snap +2 -0
  199. package/src/store/global/slices/settings/selectors/modelProvider.test.ts +127 -50
  200. package/src/store/global/slices/settings/selectors/modelProvider.ts +145 -43
  201. package/src/store/session/slices/agent/selectors.test.ts +0 -48
  202. package/src/store/session/slices/agent/selectors.ts +7 -12
  203. package/src/types/agent/index.ts +6 -2
  204. package/src/types/fetch.ts +4 -2
  205. package/src/types/files.ts +3 -3
  206. package/src/types/llm.ts +34 -0
  207. package/src/types/message/index.ts +7 -3
  208. package/src/types/openai/chat.ts +6 -11
  209. package/src/types/settings/index.ts +1 -0
  210. package/src/types/settings/modelProvider.ts +37 -1
  211. package/src/utils/__snapshots__/parseModels.test.ts.snap +63 -0
  212. package/src/utils/parseModels.test.ts +24 -0
  213. package/src/utils/parseModels.ts +37 -0
  214. package/src/app/api/openai/chat/createChatCompletion.test.ts +0 -166
  215. package/src/app/api/openai/chat/createChatCompletion.ts +0 -76
  216. package/src/app/api/openai/chat/route.ts +0 -19
  217. package/src/app/api/openai/models/route.ts +0 -17
  218. package/src/app/settings/llm/LLM/ModelList.tsx +0 -51
  219. package/src/app/settings/llm/LLM/getModelList.ts +0 -9
  220. package/src/app/settings/llm/index.tsx +0 -36
  221. package/src/const/llm.ts +0 -32
  222. package/src/features/Conversation/Error/ApiKeyForm.tsx +0 -87
  223. package/src/features/Conversation/Error/ErrorActionContainer.tsx +0 -23
  224. package/src/features/Conversation/Error/InvalidAccess.tsx +0 -90
  225. package/src/features/Conversation/Error/OpenAPIKey.tsx +0 -13
  226. package/src/features/Conversation/Error/Plugin/PluginError.tsx +0 -30
  227. package/src/services/modelList.ts +0 -15
  228. /package/src/app/chat/(desktop)/features/ChatInput/{Header → Footer}/DragUpload.tsx +0 -0
  229. /package/src/{app/api/openai/chat → libs/agent-runtime/utils}/desensitizeUrl.test.ts +0 -0
  230. /package/src/{app/api/openai/chat → libs/agent-runtime/utils}/desensitizeUrl.ts +0 -0
  231. /package/src/types/{translate.ts → message/translate.ts} +0 -0
@@ -1,12 +1,12 @@
1
- import { Highlighter } from '@lobehub/ui';
2
1
  import { memo } from 'react';
3
- import { Flexbox } from 'react-layout-kit';
4
2
 
5
- import { RenderErrorMessage } from '../types';
6
- import OpenAPIKey from './OpenAPIKey';
3
+ import { ChatMessage } from '@/types/message';
4
+
5
+ import ErrorJsonViewer from './ErrorJsonViewer';
6
+ import InvalidAPIKey from './InvalidAPIKey';
7
7
 
8
8
  interface OpenAIError {
9
- code: 'invalid_api_key' | string;
9
+ code: 'invalid_api_key' | 'insufficient_quota' | string;
10
10
  message: string;
11
11
  param?: any;
12
12
  type: string;
@@ -16,22 +16,14 @@ interface OpenAIErrorResponse {
16
16
  error: OpenAIError;
17
17
  }
18
18
 
19
- const OpenAiBizError: RenderErrorMessage['Render'] = memo(({ error, id, ...props }) => {
19
+ const OpenAiBizError = memo<ChatMessage>(({ error, id }) => {
20
20
  const errorBody: OpenAIErrorResponse = (error as any)?.body;
21
21
 
22
22
  const errorCode = errorBody.error?.code;
23
23
 
24
- if (errorCode === 'invalid_api_key')
25
- // @ts-ignore
26
- return <OpenAPIKey error={error} id={id} {...props} />;
27
-
28
- return (
29
- <Flexbox style={{ maxWidth: 600 }}>
30
- <Highlighter copyButtonSize={'small'} language={'json'}>
31
- {JSON.stringify(errorBody, null, 2)}
32
- </Highlighter>
33
- </Flexbox>
34
- );
24
+ if (errorCode === 'invalid_api_key') return <InvalidAPIKey id={id} />;
25
+
26
+ return <ErrorJsonViewer error={error} id={id} />;
35
27
  });
36
28
 
37
29
  export default OpenAiBizError;
@@ -10,11 +10,16 @@ import PluginSettingsConfig from '@/features/PluginSettings';
10
10
  import { useChatStore } from '@/store/chat';
11
11
  import { pluginHelpers, useToolStore } from '@/store/tool';
12
12
  import { pluginSelectors } from '@/store/tool/selectors';
13
+ import { ChatPluginPayload } from '@/types/message';
13
14
 
14
- import { RenderErrorMessage } from '../../types';
15
- import { ErrorActionContainer, useStyles } from '../style';
15
+ import { ErrorActionContainer, useStyles } from './style';
16
16
 
17
- const PluginSettings: RenderErrorMessage['Render'] = memo(({ id, plugin }) => {
17
+ interface PluginSettingsProps {
18
+ id: string;
19
+ plugin?: ChatPluginPayload;
20
+ }
21
+
22
+ const PluginSettings = memo<PluginSettingsProps>(({ id, plugin }) => {
18
23
  const { styles } = useStyles();
19
24
  const { t } = useTranslation('error');
20
25
  const theme = useTheme();
@@ -1,78 +1,83 @@
1
- import { PluginErrorType } from '@lobehub/chat-plugin-sdk';
1
+ import { IPluginErrorType, PluginErrorType } from '@lobehub/chat-plugin-sdk';
2
+ import type { AlertProps } from '@lobehub/ui';
3
+ import { memo } from 'react';
2
4
 
3
- import { ChatErrorType } from '@/types/fetch';
5
+ import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '@/libs/agent-runtime';
6
+ import { ChatErrorType, ErrorType } from '@/types/fetch';
7
+ import { ChatMessage, ChatMessageError } from '@/types/message';
4
8
 
5
- import { RenderErrorMessage } from '../types';
6
- import InvalidAccess from './InvalidAccess';
7
- import OpenAPIKey from './OpenAPIKey';
9
+ import ErrorJsonViewer from './ErrorJsonViewer';
10
+ import InvalidAPIKey from './InvalidAPIKey';
11
+ import InvalidAccessCode from './InvalidAccessCode';
8
12
  import OpenAiBizError from './OpenAiBizError';
9
- import PluginError from './Plugin/PluginError';
10
- import PluginSettings from './Plugin/PluginSettings';
13
+ import PluginSettings from './PluginSettings';
11
14
 
12
- export const renderErrorMessages: Record<string, RenderErrorMessage> = {
13
- [PluginErrorType.PluginMarketIndexNotFound]: {
14
- Render: PluginError,
15
- },
16
- [PluginErrorType.PluginMarketIndexInvalid]: {
17
- Render: PluginError,
18
- },
19
- [PluginErrorType.PluginMetaInvalid]: {
20
- Render: PluginError,
21
- },
22
- [PluginErrorType.PluginMetaNotFound]: {
23
- Render: PluginError,
24
- },
25
- [PluginErrorType.PluginManifestInvalid]: {
26
- Render: PluginError,
27
- },
28
- [PluginErrorType.PluginManifestNotFound]: {
29
- Render: PluginError,
30
- },
31
- [PluginErrorType.PluginApiNotFound]: {
32
- Render: PluginError,
33
- },
34
- [PluginErrorType.PluginApiParamsError]: {
35
- Render: PluginError,
36
- },
37
- [PluginErrorType.PluginServerError]: {
38
- Render: PluginError,
39
- },
40
- [PluginErrorType.PluginGatewayError]: {
41
- Render: PluginError,
42
- },
43
- [PluginErrorType.PluginOpenApiInitError]: {
44
- Render: PluginError,
45
- },
46
- [PluginErrorType.PluginSettingsInvalid]: {
47
- Render: PluginSettings,
48
- config: {
15
+ // Config for the errorMessage display
16
+ export const getErrorAlertConfig = (
17
+ errorType?: IPluginErrorType | ILobeAgentRuntimeErrorType | ErrorType,
18
+ ): AlertProps | undefined => {
19
+ // OpenAIBizError / ZhipuBizError / GoogleBizError / ...
20
+ if (typeof errorType === 'string' && errorType.includes('Biz'))
21
+ return {
49
22
  extraDefaultExpand: true,
50
23
  extraIsolate: true,
51
24
  type: 'warning',
52
- },
53
- },
54
- [ChatErrorType.InvalidAccessCode]: {
55
- Render: InvalidAccess,
56
- config: {
57
- extraDefaultExpand: true,
58
- extraIsolate: true,
59
- type: 'warning',
60
- },
61
- },
62
- [ChatErrorType.NoAPIKey]: {
63
- Render: OpenAPIKey,
64
- config: {
65
- extraDefaultExpand: true,
66
- extraIsolate: true,
67
- type: 'warning',
68
- },
69
- },
70
- [ChatErrorType.OpenAIBizError]: {
71
- Render: OpenAiBizError,
72
- config: {
73
- extraDefaultExpand: true,
74
- extraIsolate: true,
75
- type: 'warning',
76
- },
77
- },
25
+ };
26
+
27
+ switch (errorType) {
28
+ case AgentRuntimeErrorType.LocationNotSupportError: {
29
+ return {
30
+ type: 'warning',
31
+ };
32
+ }
33
+
34
+ case PluginErrorType.PluginSettingsInvalid:
35
+ case ChatErrorType.InvalidAccessCode:
36
+ case AgentRuntimeErrorType.NoOpenAIAPIKey:
37
+ case AgentRuntimeErrorType.InvalidBedrockCredentials:
38
+ case AgentRuntimeErrorType.InvalidGoogleAPIKey:
39
+ case AgentRuntimeErrorType.InvalidZhipuAPIKey: {
40
+ return {
41
+ extraDefaultExpand: true,
42
+ extraIsolate: true,
43
+ type: 'warning',
44
+ };
45
+ }
46
+
47
+ default: {
48
+ return undefined;
49
+ }
50
+ }
78
51
  };
52
+
53
+ const ErrorMessageExtra = memo<{ data: ChatMessage }>(({ data }) => {
54
+ const error = data.error as ChatMessageError;
55
+ if (!error?.type) return;
56
+
57
+ switch (error.type) {
58
+ case PluginErrorType.PluginSettingsInvalid: {
59
+ return <PluginSettings id={data.id} plugin={data.plugin} />;
60
+ }
61
+
62
+ case AgentRuntimeErrorType.OpenAIBizError: {
63
+ return <OpenAiBizError {...data} />;
64
+ }
65
+
66
+ case ChatErrorType.InvalidAccessCode: {
67
+ return <InvalidAccessCode id={data.id} provider={data.error?.body?.provider} />;
68
+ }
69
+
70
+ case AgentRuntimeErrorType.InvalidBedrockCredentials:
71
+ case AgentRuntimeErrorType.InvalidZhipuAPIKey:
72
+ case AgentRuntimeErrorType.InvalidGoogleAPIKey:
73
+ case AgentRuntimeErrorType.NoOpenAIAPIKey: {
74
+ return <InvalidAPIKey id={data.id} provider={data.error?.body?.provider} />;
75
+ }
76
+
77
+ default: {
78
+ return <ErrorJsonViewer error={data.error} id={data.id} />;
79
+ }
80
+ }
81
+ });
82
+
83
+ export default ErrorMessageExtra;
@@ -27,16 +27,22 @@ export const ErrorActionContainer = memo<{ children: ReactNode }>(({ children })
27
27
  });
28
28
 
29
29
  export const FormAction = memo<{
30
- avatar: string;
30
+ avatar: ReactNode;
31
+ background?: string;
31
32
  children: ReactNode;
32
33
  description: string;
33
34
  title: string;
34
- }>(({ children, title, description, avatar }) => {
35
+ }>(({ children, background, title, description, avatar }) => {
35
36
  const { styles, theme } = useStyles();
36
37
 
37
38
  return (
38
39
  <Center gap={16} style={{ maxWidth: 300 }}>
39
- <Avatar avatar={avatar} background={theme.colorFillContent} gap={12} size={80} />
40
+ <Avatar
41
+ avatar={avatar}
42
+ background={background ?? theme.colorFillContent}
43
+ gap={12}
44
+ size={80}
45
+ />
40
46
  <Flexbox style={{ fontSize: 20 }}>{title}</Flexbox>
41
47
  <Flexbox className={styles.desc}>{description}</Flexbox>
42
48
  {children}
@@ -1,8 +1,7 @@
1
- import { SiOpenai } from '@icons-pack/react-simple-icons';
2
- import { Tag } from '@lobehub/ui';
3
1
  import { memo } from 'react';
4
2
  import { Flexbox } from 'react-layout-kit';
5
3
 
4
+ import ModelTag from '@/components/ModelTag';
6
5
  import { useChatStore } from '@/store/chat';
7
6
  import { useSessionStore } from '@/store/session';
8
7
  import { agentSelectors } from '@/store/session/selectors';
@@ -30,7 +29,7 @@ export const AssistantMessageExtra: RenderMessageExtra = memo<ChatMessage>(
30
29
  <Flexbox gap={8} style={{ marginTop: 8 }}>
31
30
  {showModelTag && (
32
31
  <div>
33
- <Tag icon={<SiOpenai size={'1em'} />}>{extra?.fromModel as string}</Tag>
32
+ <ModelTag model={extra?.fromModel as string} />
34
33
  </div>
35
34
  )}
36
35
  <>
@@ -60,8 +60,14 @@ const Inspector = memo<InspectorProps>(
60
60
  <Icon icon={LucideToyBrick} />
61
61
  );
62
62
 
63
- const args = JSON.stringify(command, null, 2);
64
- const params = JSON.stringify(JSON.parse(requestArgs), null, 2);
63
+ let args, params;
64
+ try {
65
+ args = JSON.stringify(command, null, 2);
66
+ params = JSON.stringify(JSON.parse(requestArgs), null, 2);
67
+ } catch {
68
+ args = '';
69
+ params = '';
70
+ }
65
71
 
66
72
  return (
67
73
  <Flexbox gap={8}>
@@ -1,4 +1,4 @@
1
- import { type AlertProps, ChatItem } from '@lobehub/ui';
1
+ import { AlertProps, ChatItem } from '@lobehub/ui';
2
2
  import { createStyles } from 'antd-style';
3
3
  import isEqual from 'fast-deep-equal';
4
4
  import { ReactNode, memo, useCallback, useMemo, useState } from 'react';
@@ -10,7 +10,7 @@ import { useSessionStore } from '@/store/session';
10
10
  import { agentSelectors } from '@/store/session/selectors';
11
11
  import { ChatMessage } from '@/types/message';
12
12
 
13
- import { renderErrorMessages } from '../../Error';
13
+ import ErrorMessageExtra, { getErrorAlertConfig } from '../../Error';
14
14
  import { renderMessagesExtra } from '../../Extras';
15
15
  import { renderMessages, useAvatarsClick } from '../../Messages';
16
16
  import ActionsBar from './ActionsBar';
@@ -81,28 +81,13 @@ const Item = memo<ChatListItemProps>(({ index, id }) => {
81
81
  [item?.role],
82
82
  );
83
83
 
84
- const ErrorMessage = useCallback(
85
- ({ data }: { data: ChatMessage }) => {
86
- if (!renderErrorMessages || !item?.error?.type) return;
87
- let RenderFunction;
88
- if (renderErrorMessages?.[item.error.type])
89
- RenderFunction = renderErrorMessages[item.error.type].Render;
90
- if (!RenderFunction && renderErrorMessages?.['default'])
91
- RenderFunction = renderErrorMessages['default'].Render;
92
- if (!RenderFunction) return;
93
- return <RenderFunction {...data} />;
94
- },
95
- [item?.error],
96
- );
97
-
98
- const error = useMemo(() => {
84
+ const error = useMemo<AlertProps | undefined>(() => {
99
85
  if (!item?.error) return;
100
- const message = item.error?.message;
101
- let alertConfig = {};
102
- if (item.error.type && renderErrorMessages?.[item.error.type]) {
103
- alertConfig = renderErrorMessages[item.error.type]?.config as AlertProps;
104
- }
105
- return { message, ...alertConfig };
86
+ const messageError = item.error;
87
+
88
+ const alertConfig = getErrorAlertConfig(messageError.type);
89
+
90
+ return { message: t(`response.${messageError.type}` as any, { ns: 'error' }), ...alertConfig };
106
91
  }, [item?.error]);
107
92
 
108
93
  const enableHistoryDivider = useSessionStore((s) => {
@@ -124,7 +109,7 @@ const Item = memo<ChatListItemProps>(({ index, id }) => {
124
109
  className={styles.message}
125
110
  editing={editing}
126
111
  error={error}
127
- errorMessage={<ErrorMessage data={item} />}
112
+ errorMessage={<ErrorMessageExtra data={item} />}
128
113
  loading={loading}
129
114
  message={item.content}
130
115
  messageExtra={<MessageExtra data={item} />}
@@ -1,4 +1,4 @@
1
- import { type AlertProps, type ChatItemProps } from '@lobehub/ui';
1
+ import { type ChatItemProps } from '@lobehub/ui';
2
2
  import { ActionEvent } from '@lobehub/ui';
3
3
  import { FC, ReactNode } from 'react';
4
4
 
@@ -12,10 +12,7 @@ export type OnAvatarsClick = (role: RenderRole) => ChatItemProps['onAvatarClick'
12
12
  export type RenderRole = LLMRoleType | 'default' | string;
13
13
  export type RenderMessage = FC<ChatMessage & { editableContent: ReactNode }>;
14
14
  export type RenderMessageExtra = FC<ChatMessage>;
15
- export interface RenderErrorMessage {
16
- Render?: FC<ChatMessage>;
17
- config?: AlertProps;
18
- }
15
+
19
16
  export type RenderAction = FC<ActionsBarProps & ChatMessage>;
20
17
 
21
18
  export type RenderItem = FC<{ key: string } & ChatMessage & ListItemProps>;
@@ -0,0 +1,35 @@
1
+ import {
2
+ AZURE_OPENAI_API_VERSION,
3
+ LOBE_CHAT_ACCESS_CODE,
4
+ OPENAI_API_KEY_HEADER_KEY,
5
+ OPENAI_END_POINT,
6
+ USE_AZURE_OPENAI,
7
+ } from '@/const/fetch';
8
+ import { useGlobalStore } from '@/store/global';
9
+ import { modelProviderSelectors, settingsSelectors } from '@/store/global/selectors';
10
+
11
+ // TODO: Need to be removed after tts refactor
12
+ // eslint-disable-next-line no-undef
13
+ export const createHeaderWithOpenAI = (header?: HeadersInit): HeadersInit => {
14
+ const openai = modelProviderSelectors.openAIConfig(useGlobalStore.getState());
15
+
16
+ const apiKey = openai.OPENAI_API_KEY || '';
17
+ const endpoint = openai.endpoint || '';
18
+
19
+ // eslint-disable-next-line no-undef
20
+ const result: HeadersInit = {
21
+ ...header,
22
+ [LOBE_CHAT_ACCESS_CODE]: settingsSelectors.password(useGlobalStore.getState()),
23
+ [OPENAI_API_KEY_HEADER_KEY]: apiKey,
24
+ [OPENAI_END_POINT]: endpoint,
25
+ };
26
+
27
+ if (openai.useAzure) {
28
+ Object.assign(result, {
29
+ [AZURE_OPENAI_API_VERSION]: openai.azureApiVersion || '',
30
+ [USE_AZURE_OPENAI]: '1',
31
+ });
32
+ }
33
+
34
+ return result;
35
+ };
@@ -0,0 +1,9 @@
1
+ import { StreamingTextResponse } from 'ai';
2
+
3
+ import { ChatStreamPayload } from '@/types/openai/chat';
4
+
5
+ export interface LobeRuntimeAI {
6
+ baseURL?: string;
7
+
8
+ chat(payload: ChatStreamPayload): Promise<StreamingTextResponse>;
9
+ }
@@ -0,0 +1,72 @@
1
+ import {
2
+ AzureKeyCredential,
3
+ ChatRequestMessage,
4
+ GetChatCompletionsOptions,
5
+ OpenAIClient,
6
+ } from '@azure/openai';
7
+ import { OpenAIStream, StreamingTextResponse } from 'ai';
8
+
9
+ import { LobeRuntimeAI } from '../BaseAI';
10
+ import { AgentRuntimeErrorType } from '../error';
11
+ import { ChatStreamPayload, ModelProvider } from '../types';
12
+ import { AgentRuntimeError } from '../utils/createError';
13
+ import { debugStream } from '../utils/debugStream';
14
+ import { DEBUG_CHAT_COMPLETION } from '../utils/env';
15
+
16
+ export class LobeAzureOpenAI implements LobeRuntimeAI {
17
+ private _client: OpenAIClient;
18
+
19
+ constructor(endpoint?: string, apikey?: string, apiVersion?: string) {
20
+ if (!apikey || !endpoint)
21
+ throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidAzureAPIKey);
22
+
23
+ this._client = new OpenAIClient(endpoint, new AzureKeyCredential(apikey), { apiVersion });
24
+
25
+ this.baseURL = endpoint;
26
+ }
27
+
28
+ baseURL: string;
29
+
30
+ async chat(payload: ChatStreamPayload) {
31
+ // ============ 1. preprocess messages ============ //
32
+ const { messages, model, ...params } = payload;
33
+
34
+ // ============ 2. send api ============ //
35
+
36
+ try {
37
+ const response = await this._client.streamChatCompletions(
38
+ model,
39
+ messages as ChatRequestMessage[],
40
+ params as GetChatCompletionsOptions,
41
+ );
42
+
43
+ const stream = OpenAIStream(response);
44
+
45
+ const [debug, prod] = stream.tee();
46
+
47
+ if (DEBUG_CHAT_COMPLETION) {
48
+ debugStream(debug).catch(console.error);
49
+ }
50
+
51
+ return new StreamingTextResponse(prod);
52
+ } catch (e) {
53
+ let error = e as { [key: string]: any; code: string; message: string };
54
+
55
+ switch (error.code) {
56
+ case 'DeploymentNotFound': {
57
+ error = { ...error, deployId: model };
58
+ }
59
+ }
60
+
61
+ const errorType = error.code
62
+ ? AgentRuntimeErrorType.AzureBizError
63
+ : AgentRuntimeErrorType.AgentRuntimeError;
64
+
65
+ throw AgentRuntimeError.chat({
66
+ error,
67
+ errorType,
68
+ provider: ModelProvider.Azure,
69
+ });
70
+ }
71
+ }
72
+ }
@@ -0,0 +1,134 @@
1
+ import {
2
+ BedrockRuntimeClient,
3
+ InvokeModelWithResponseStreamCommand,
4
+ } from '@aws-sdk/client-bedrock-runtime';
5
+ import { AWSBedrockAnthropicStream, AWSBedrockLlama2Stream, StreamingTextResponse } from 'ai';
6
+ import { experimental_buildAnthropicPrompt, experimental_buildLlama2Prompt } from 'ai/prompts';
7
+
8
+ import { LobeRuntimeAI } from '../BaseAI';
9
+ import { AgentRuntimeErrorType } from '../error';
10
+ import { ChatStreamPayload, ModelProvider } from '../types';
11
+ import { AgentRuntimeError } from '../utils/createError';
12
+ import { debugStream } from '../utils/debugStream';
13
+ import { DEBUG_CHAT_COMPLETION } from '../utils/env';
14
+
15
+ export interface LobeBedrockAIParams {
16
+ accessKeyId?: string;
17
+ accessKeySecret?: string;
18
+ region?: string;
19
+ }
20
+
21
+ export class LobeBedrockAI implements LobeRuntimeAI {
22
+ private client: BedrockRuntimeClient;
23
+
24
+ region: string;
25
+
26
+ constructor({ region, accessKeyId, accessKeySecret }: LobeBedrockAIParams) {
27
+ if (!(accessKeyId && accessKeySecret))
28
+ throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidBedrockCredentials);
29
+
30
+ this.region = region ?? 'us-east-1';
31
+
32
+ this.client = new BedrockRuntimeClient({
33
+ credentials: {
34
+ accessKeyId: accessKeyId,
35
+ secretAccessKey: accessKeySecret,
36
+ },
37
+ region: this.region,
38
+ });
39
+ }
40
+
41
+ async chat(payload: ChatStreamPayload) {
42
+ if (payload.model.startsWith('meta')) return this.invokeLlamaModel(payload);
43
+
44
+ return this.invokeClaudeModel(payload);
45
+ }
46
+
47
+ private invokeClaudeModel = async (
48
+ payload: ChatStreamPayload,
49
+ ): Promise<StreamingTextResponse> => {
50
+ const command = new InvokeModelWithResponseStreamCommand({
51
+ accept: 'application/json',
52
+ body: JSON.stringify({
53
+ max_tokens_to_sample: payload.max_tokens || 400,
54
+ prompt: experimental_buildAnthropicPrompt(payload.messages as any),
55
+ }),
56
+ contentType: 'application/json',
57
+ modelId: payload.model,
58
+ });
59
+
60
+ try {
61
+ // Ask Claude for a streaming chat completion given the prompt
62
+ const bedrockResponse = await this.client.send(command);
63
+
64
+ // Convert the response into a friendly text-stream
65
+ const stream = AWSBedrockAnthropicStream(bedrockResponse);
66
+
67
+ const [debug, output] = stream.tee();
68
+
69
+ if (DEBUG_CHAT_COMPLETION) {
70
+ debugStream(debug).catch(console.error);
71
+ }
72
+
73
+ // Respond with the stream
74
+ return new StreamingTextResponse(output);
75
+ } catch (e) {
76
+ const err = e as Error & { $metadata: any };
77
+
78
+ throw AgentRuntimeError.chat({
79
+ error: {
80
+ body: err.$metadata,
81
+ message: err.message,
82
+ type: err.name,
83
+ },
84
+ errorType: AgentRuntimeErrorType.BedrockBizError,
85
+ provider: ModelProvider.Bedrock,
86
+ region: this.region,
87
+ });
88
+ }
89
+ };
90
+
91
+ private invokeLlamaModel = async (payload: ChatStreamPayload) => {
92
+ const command = new InvokeModelWithResponseStreamCommand({
93
+ accept: 'application/json',
94
+ body: JSON.stringify({
95
+ max_gen_len: payload.max_tokens || 400,
96
+ prompt: experimental_buildLlama2Prompt(payload.messages as any),
97
+ }),
98
+ contentType: 'application/json',
99
+ modelId: payload.model,
100
+ });
101
+
102
+ try {
103
+ // Ask Claude for a streaming chat completion given the prompt
104
+ const bedrockResponse = await this.client.send(command);
105
+
106
+ // Convert the response into a friendly text-stream
107
+ const stream = AWSBedrockLlama2Stream(bedrockResponse);
108
+
109
+ const [debug, output] = stream.tee();
110
+
111
+ if (DEBUG_CHAT_COMPLETION) {
112
+ debugStream(debug).catch(console.error);
113
+ }
114
+ // Respond with the stream
115
+ return new StreamingTextResponse(output);
116
+ } catch (e) {
117
+ const err = e as Error & { $metadata: any };
118
+
119
+ throw AgentRuntimeError.chat({
120
+ error: {
121
+ body: err.$metadata,
122
+ message: err.message,
123
+ region: this.region,
124
+ type: err.name,
125
+ },
126
+ errorType: AgentRuntimeErrorType.BedrockBizError,
127
+ provider: ModelProvider.Bedrock,
128
+ region: this.region,
129
+ });
130
+ }
131
+ };
132
+ }
133
+
134
+ export default LobeBedrockAI;
@@ -0,0 +1,26 @@
1
+ /* eslint-disable sort-keys-fix/sort-keys-fix */
2
+
3
+ // ******* Runtime Biz Error ******* //
4
+ export const AgentRuntimeErrorType = {
5
+ AgentRuntimeError: 'AgentRuntimeError', // Agent Runtime 模块运行时错误
6
+ LocationNotSupportError: 'LocationNotSupportError',
7
+
8
+ OpenAIBizError: 'OpenAIBizError', // OpenAI 返回的业务错误
9
+
10
+ NoOpenAIAPIKey: 'NoOpenAIAPIKey',
11
+
12
+ InvalidAzureAPIKey: 'InvalidAzureAPIKey',
13
+ AzureBizError: 'AzureBizError', // Azure 返回的业务错误
14
+
15
+ InvalidZhipuAPIKey: 'InvalidZhipuAPIKey',
16
+ ZhipuBizError: 'ZhipuBizError',
17
+
18
+ InvalidGoogleAPIKey: 'InvalidGoogleAPIKey',
19
+ GoogleBizError: 'GoogleBizError',
20
+
21
+ InvalidBedrockCredentials: 'InvalidBedrockCredentials',
22
+ BedrockBizError: 'BedrockBizError', // Bedrock 返回的业务错误
23
+ } as const;
24
+
25
+ export type ILobeAgentRuntimeErrorType =
26
+ (typeof AgentRuntimeErrorType)[keyof typeof AgentRuntimeErrorType];