@lobehub/chat 0.132.2 → 0.133.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 (84) hide show
  1. package/.env.example +5 -0
  2. package/CHANGELOG.md +50 -0
  3. package/Dockerfile +3 -0
  4. package/README.md +5 -1
  5. package/README.zh-CN.md +5 -1
  6. package/docs/self-hosting/environment-variables/model-provider.mdx +8 -0
  7. package/docs/self-hosting/environment-variables/model-provider.zh-CN.mdx +10 -1
  8. package/locales/ar/common.json +1 -0
  9. package/locales/ar/error.json +6 -0
  10. package/locales/ar/setting.json +8 -0
  11. package/locales/de-DE/common.json +1 -0
  12. package/locales/de-DE/error.json +6 -0
  13. package/locales/de-DE/setting.json +8 -0
  14. package/locales/en-US/common.json +1 -0
  15. package/locales/en-US/error.json +6 -0
  16. package/locales/en-US/setting.json +8 -0
  17. package/locales/es-ES/common.json +1 -0
  18. package/locales/es-ES/error.json +6 -0
  19. package/locales/es-ES/setting.json +8 -0
  20. package/locales/fr-FR/common.json +1 -0
  21. package/locales/fr-FR/error.json +6 -0
  22. package/locales/fr-FR/setting.json +8 -0
  23. package/locales/it-IT/common.json +1 -0
  24. package/locales/it-IT/error.json +6 -0
  25. package/locales/it-IT/setting.json +8 -0
  26. package/locales/ja-JP/common.json +1 -0
  27. package/locales/ja-JP/error.json +6 -0
  28. package/locales/ja-JP/setting.json +8 -0
  29. package/locales/ko-KR/common.json +1 -0
  30. package/locales/ko-KR/error.json +6 -0
  31. package/locales/ko-KR/setting.json +8 -0
  32. package/locales/nl-NL/common.json +1 -0
  33. package/locales/nl-NL/error.json +6 -0
  34. package/locales/nl-NL/setting.json +8 -0
  35. package/locales/pl-PL/common.json +1 -0
  36. package/locales/pl-PL/error.json +6 -0
  37. package/locales/pl-PL/setting.json +8 -0
  38. package/locales/pt-BR/common.json +1 -0
  39. package/locales/pt-BR/error.json +6 -0
  40. package/locales/pt-BR/setting.json +8 -0
  41. package/locales/ru-RU/common.json +1 -0
  42. package/locales/ru-RU/error.json +6 -0
  43. package/locales/ru-RU/setting.json +8 -0
  44. package/locales/tr-TR/common.json +1 -0
  45. package/locales/tr-TR/error.json +6 -0
  46. package/locales/tr-TR/setting.json +8 -0
  47. package/locales/vi-VN/common.json +1 -0
  48. package/locales/vi-VN/error.json +6 -0
  49. package/locales/vi-VN/setting.json +8 -0
  50. package/locales/zh-CN/common.json +1 -0
  51. package/locales/zh-CN/error.json +6 -0
  52. package/locales/zh-CN/setting.json +8 -0
  53. package/locales/zh-TW/common.json +1 -0
  54. package/locales/zh-TW/error.json +6 -0
  55. package/locales/zh-TW/setting.json +8 -0
  56. package/next-sitemap.config.mjs +2 -3
  57. package/package.json +1 -1
  58. package/src/app/api/chat/[provider]/agentRuntime.test.ts +52 -0
  59. package/src/app/api/chat/[provider]/agentRuntime.ts +13 -0
  60. package/src/app/api/config/route.ts +2 -0
  61. package/src/app/api/errorResponse.test.ts +15 -0
  62. package/src/app/api/errorResponse.ts +3 -0
  63. package/src/app/settings/llm/Mistral/index.tsx +52 -0
  64. package/src/app/settings/llm/index.tsx +2 -0
  65. package/src/config/modelProviders/index.ts +3 -0
  66. package/src/config/modelProviders/mistral.ts +34 -0
  67. package/src/config/server/provider.ts +8 -0
  68. package/src/const/settings.ts +4 -0
  69. package/src/features/Conversation/Error/APIKeyForm/Mistral.tsx +60 -0
  70. package/src/features/Conversation/Error/APIKeyForm/index.tsx +5 -0
  71. package/src/features/Conversation/Error/index.tsx +1 -0
  72. package/src/libs/agent-runtime/anthropic/index.test.ts +78 -0
  73. package/src/libs/agent-runtime/error.ts +3 -0
  74. package/src/libs/agent-runtime/index.ts +1 -0
  75. package/src/libs/agent-runtime/mistral/index.test.ts +378 -0
  76. package/src/libs/agent-runtime/mistral/index.ts +87 -0
  77. package/src/locales/default/common.ts +1 -0
  78. package/src/locales/default/error.ts +7 -0
  79. package/src/locales/default/setting.ts +8 -0
  80. package/src/services/_auth.test.ts +20 -0
  81. package/src/services/_auth.ts +4 -0
  82. package/src/store/global/slices/settings/selectors/modelProvider.ts +9 -0
  83. package/src/types/settings/modelProvider.ts +6 -0
  84. package/public/robots.txt +0 -4
@@ -0,0 +1,87 @@
1
+ import { OpenAIStream, StreamingTextResponse } from 'ai';
2
+ import OpenAI, { ClientOptions } from 'openai';
3
+
4
+ import { LobeRuntimeAI } from '../BaseAI';
5
+ import { AgentRuntimeErrorType } from '../error';
6
+ import { ChatCompetitionOptions, ChatStreamPayload, ModelProvider } from '../types';
7
+ import { AgentRuntimeError } from '../utils/createError';
8
+ import { debugStream } from '../utils/debugStream';
9
+ import { desensitizeUrl } from '../utils/desensitizeUrl';
10
+ import { handleOpenAIError } from '../utils/handleOpenAIError';
11
+
12
+ const DEFAULT_BASE_URL = 'https://api.mistral.ai/v1';
13
+
14
+ export class LobeMistralAI implements LobeRuntimeAI {
15
+ private client: OpenAI;
16
+
17
+ baseURL: string;
18
+
19
+ constructor({ apiKey, baseURL = DEFAULT_BASE_URL, ...res }: ClientOptions) {
20
+ if (!apiKey) throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidMistralAPIKey);
21
+
22
+ this.client = new OpenAI({ apiKey, baseURL, ...res });
23
+ this.baseURL = this.client.baseURL;
24
+ }
25
+
26
+ async chat(payload: ChatStreamPayload, options?: ChatCompetitionOptions) {
27
+ try {
28
+ // Pick supported properties from payload
29
+ const chatPayload = {
30
+ max_tokens: payload.max_tokens,
31
+ messages: payload.messages,
32
+ model: payload.model,
33
+ stream: true,
34
+ temperature: payload.temperature,
35
+ top_p: payload.top_p,
36
+ };
37
+ const response = await this.client.chat.completions.create(
38
+ chatPayload as unknown as OpenAI.ChatCompletionCreateParamsStreaming,
39
+ );
40
+ const [prod, debug] = response.tee();
41
+
42
+ if (process.env.DEBUG_MISTRAL_CHAT_COMPLETION === '1') {
43
+ debugStream(debug.toReadableStream()).catch(console.error);
44
+ }
45
+
46
+ return new StreamingTextResponse(OpenAIStream(prod, options?.callback), {
47
+ headers: options?.headers,
48
+ });
49
+ } catch (error) {
50
+ let desensitizedEndpoint = this.baseURL;
51
+
52
+ if (this.baseURL !== DEFAULT_BASE_URL) {
53
+ desensitizedEndpoint = desensitizeUrl(this.baseURL);
54
+ }
55
+
56
+ if ('status' in (error as any)) {
57
+ switch ((error as Response).status) {
58
+ case 401: {
59
+ throw AgentRuntimeError.chat({
60
+ endpoint: desensitizedEndpoint,
61
+ error: error as any,
62
+ errorType: AgentRuntimeErrorType.InvalidMistralAPIKey,
63
+ provider: ModelProvider.Mistral,
64
+ });
65
+ }
66
+
67
+ default: {
68
+ break;
69
+ }
70
+ }
71
+ }
72
+
73
+ const { errorResult, RuntimeError } = handleOpenAIError(error);
74
+
75
+ const errorType = RuntimeError || AgentRuntimeErrorType.MistralBizError;
76
+
77
+ throw AgentRuntimeError.chat({
78
+ endpoint: desensitizedEndpoint,
79
+ error: errorResult,
80
+ errorType,
81
+ provider: ModelProvider.Mistral,
82
+ });
83
+ }
84
+ }
85
+ }
86
+
87
+ export default LobeMistralAI;
@@ -104,6 +104,7 @@ export default {
104
104
  azure: 'Azure',
105
105
  bedrock: 'AWS Bedrock',
106
106
  google: 'Google',
107
+ mistral: 'Mistral AI',
107
108
  moonshot: 'Moonshot AI',
108
109
  ollama: 'Ollama',
109
110
  oneapi: 'One API',
@@ -61,6 +61,9 @@ export default {
61
61
  ZhipuBizError: '请求智谱服务出错,请根据以下信息排查或重试',
62
62
  InvalidZhipuAPIKey: 'Zhipu API Key 不正确或为空,请检查 Zhipu API Key 后重试',
63
63
 
64
+ MistralBizError: '请求 Mistral AI 服务出错,请根据以下信息排查或重试',
65
+ InvalidMistralAPIKey: 'Mistral AI API Key 不正确或为空,请检查 Mistral API Key 后重试',
66
+
64
67
  MoonshotBizError: '请求月之暗面服务出错,请根据以下信息排查或重试',
65
68
  InvalidMoonshotAPIKey: 'Moonshot AI API Key 不正确或为空,请检查 Moonshot API Key 后重试',
66
69
 
@@ -107,6 +110,10 @@ export default {
107
110
  description: '输入你的 Google API Key 即可开始会话。应用不会记录你的 API Key',
108
111
  title: '使用自定义 Google API Key',
109
112
  },
113
+ Mistral: {
114
+ description: '输入你的 Mistral AI API Key 即可开始会话。应用不会记录你的 API Key',
115
+ title: '使用自定义 Mistral AI API Key',
116
+ },
110
117
  Moonshot: {
111
118
  description: '输入你的 Moonshot AI API Key 即可开始会话。应用不会记录你的 API Key',
112
119
  title: '使用自定义 Moonshot AI API Key',
@@ -95,6 +95,14 @@ export default {
95
95
  title: 'API Key',
96
96
  },
97
97
  },
98
+ Mistral: {
99
+ title: 'Mistral AI',
100
+ token: {
101
+ desc: '填入来自 Mistral AI 的 API Key',
102
+ placeholder: 'Mistral AI API Key',
103
+ title: 'API Key',
104
+ },
105
+ },
98
106
  Moonshot: {
99
107
  title: '月之暗面',
100
108
  token: {
@@ -11,6 +11,8 @@ import { getProviderAuthPayload } from './_auth';
11
11
  const mockZhiPuAPIKey = 'zhipu-api-key';
12
12
  const mockMoonshotAPIKey = 'moonshot-api-key';
13
13
  const mockGoogleAPIKey = 'google-api-key';
14
+ const mockAnthropicAPIKey = 'anthropic-api-key';
15
+ const mockMistralAPIKey = 'mistral-api-key';
14
16
 
15
17
  // mock the traditional zustand
16
18
  vi.mock('zustand/traditional');
@@ -43,6 +45,24 @@ describe('getProviderAuthPayload', () => {
43
45
  expect(payload).toEqual({ apiKey: mockMoonshotAPIKey });
44
46
  });
45
47
 
48
+ it('should return correct payload for Anthropic provider', () => {
49
+ act(() => {
50
+ setModelProviderConfig('anthropic', { apiKey: mockAnthropicAPIKey });
51
+ });
52
+
53
+ const payload = getProviderAuthPayload(ModelProvider.Anthropic);
54
+ expect(payload).toEqual({ apiKey: mockAnthropicAPIKey });
55
+ });
56
+
57
+ it('should return correct payload for Mistral provider', () => {
58
+ act(() => {
59
+ setModelProviderConfig('mistral', { apiKey: mockMistralAPIKey });
60
+ });
61
+
62
+ const payload = getProviderAuthPayload(ModelProvider.Mistral);
63
+ expect(payload).toEqual({ apiKey: mockMistralAPIKey });
64
+ });
65
+
46
66
  it('should return correct payload for Google provider', () => {
47
67
  act(() => {
48
68
  setModelProviderConfig('google', { apiKey: mockGoogleAPIKey });
@@ -55,6 +55,10 @@ export const getProviderAuthPayload = (provider: string) => {
55
55
  case ModelProvider.Anthropic: {
56
56
  return { apiKey: modelProviderSelectors.anthropicAPIKey(useGlobalStore.getState()) };
57
57
  }
58
+
59
+ case ModelProvider.Mistral: {
60
+ return { apiKey: modelProviderSelectors.mistralAPIKey(useGlobalStore.getState()) };
61
+ }
58
62
 
59
63
  default:
60
64
  case ModelProvider.OpenAI: {
@@ -5,6 +5,7 @@ import {
5
5
  BedrockProvider,
6
6
  GoogleProvider,
7
7
  LOBE_DEFAULT_MODEL_LIST,
8
+ MistralProvider,
8
9
  MoonshotProvider,
9
10
  OllamaProvider,
10
11
  OpenAIProvider,
@@ -41,6 +42,9 @@ const googleProxyUrl = (s: GlobalStore) => modelProvider(s).google.endpoint;
41
42
  const enableAzure = (s: GlobalStore) => modelProvider(s).openAI.useAzure;
42
43
  const azureConfig = (s: GlobalStore) => modelProvider(s).azure;
43
44
 
45
+ const enableMistral = (s: GlobalStore) => modelProvider(s).mistral.enabled;
46
+ const mistralAPIKey = (s: GlobalStore) => modelProvider(s).mistral.apiKey;
47
+
44
48
  const enableMoonshot = (s: GlobalStore) => modelProvider(s).moonshot.enabled;
45
49
  const moonshotAPIKey = (s: GlobalStore) => modelProvider(s).moonshot.apiKey;
46
50
 
@@ -143,6 +147,7 @@ const modelSelectList = (s: GlobalStore): ModelProviderCard[] => {
143
147
  { ...OllamaProvider, chatModels: ollamaChatModels, enabled: enableOllama(s) },
144
148
  { ...PerplexityProvider, enabled: enablePerplexity(s) },
145
149
  { ...AnthropicProvider, enabled: enableAnthropic(s) },
150
+ { ...MistralProvider, enabled: enableMistral(s) },
146
151
  ];
147
152
  };
148
153
 
@@ -221,4 +226,8 @@ export const modelProviderSelectors = {
221
226
  // Anthropic
222
227
  enableAnthropic,
223
228
  anthropicAPIKey,
229
+
230
+ // Mistral
231
+ enableMistral,
232
+ mistralAPIKey,
224
233
  };
@@ -65,11 +65,17 @@ export interface AnthropicConfig {
65
65
  enabled: boolean;
66
66
  }
67
67
 
68
+ export interface MistralConfig {
69
+ apiKey?: string;
70
+ enabled: boolean;
71
+ }
72
+
68
73
  export interface GlobalLLMConfig {
69
74
  anthropic: AnthropicConfig;
70
75
  azure: AzureOpenAIConfig;
71
76
  bedrock: AWSBedrockConfig;
72
77
  google: GoogleConfig;
78
+ mistral: MistralConfig;
73
79
  moonshot: MoonshotConfig;
74
80
  ollama: OllamaConfig;
75
81
  openAI: OpenAIConfig;
package/public/robots.txt DELETED
@@ -1,4 +0,0 @@
1
- User-agent: *
2
- Allow: /
3
- Disallow: /settings
4
- Disallow: /chat