@lobehub/chat 0.138.2 → 0.139.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +6 -0
- package/CHANGELOG.md +25 -0
- package/Dockerfile +3 -0
- package/docs/self-hosting/environment-variables/model-provider.mdx +14 -4
- package/docs/self-hosting/environment-variables/model-provider.zh-CN.mdx +8 -0
- package/locales/ar/common.json +2 -1
- package/locales/ar/error.json +7 -1
- package/locales/ar/setting.json +16 -0
- package/locales/de-DE/common.json +2 -1
- package/locales/de-DE/error.json +7 -1
- package/locales/de-DE/setting.json +16 -0
- package/locales/en-US/common.json +2 -1
- package/locales/en-US/error.json +7 -1
- package/locales/en-US/setting.json +16 -0
- package/locales/es-ES/common.json +2 -1
- package/locales/es-ES/error.json +7 -1
- package/locales/es-ES/setting.json +16 -0
- package/locales/fr-FR/common.json +2 -1
- package/locales/fr-FR/error.json +7 -1
- package/locales/fr-FR/setting.json +16 -0
- package/locales/it-IT/common.json +2 -1
- package/locales/it-IT/error.json +7 -1
- package/locales/it-IT/setting.json +16 -0
- package/locales/ja-JP/common.json +2 -1
- package/locales/ja-JP/error.json +7 -1
- package/locales/ja-JP/setting.json +16 -0
- package/locales/ko-KR/common.json +2 -1
- package/locales/ko-KR/error.json +7 -1
- package/locales/ko-KR/setting.json +16 -0
- package/locales/nl-NL/common.json +2 -1
- package/locales/nl-NL/error.json +7 -1
- package/locales/nl-NL/setting.json +16 -0
- package/locales/pl-PL/common.json +2 -1
- package/locales/pl-PL/error.json +7 -1
- package/locales/pl-PL/setting.json +16 -0
- package/locales/pt-BR/common.json +2 -1
- package/locales/pt-BR/error.json +7 -1
- package/locales/pt-BR/setting.json +16 -0
- package/locales/ru-RU/common.json +2 -1
- package/locales/ru-RU/error.json +7 -1
- package/locales/ru-RU/setting.json +16 -0
- package/locales/tr-TR/common.json +2 -1
- package/locales/tr-TR/error.json +7 -1
- package/locales/tr-TR/setting.json +16 -0
- package/locales/vi-VN/common.json +2 -1
- package/locales/vi-VN/error.json +7 -1
- package/locales/vi-VN/setting.json +16 -0
- package/locales/zh-CN/common.json +2 -1
- package/locales/zh-CN/error.json +7 -1
- package/locales/zh-CN/setting.json +16 -0
- package/locales/zh-TW/common.json +2 -1
- package/locales/zh-TW/error.json +7 -1
- package/locales/zh-TW/setting.json +16 -0
- package/package.json +1 -1
- package/src/app/api/chat/[provider]/agentRuntime.test.ts +26 -0
- package/src/app/api/chat/[provider]/agentRuntime.ts +14 -0
- package/src/app/api/config/route.ts +2 -0
- package/src/app/api/errorResponse.test.ts +7 -0
- package/src/app/api/errorResponse.ts +3 -0
- package/src/app/settings/llm/OpenRouter/index.tsx +64 -0
- package/src/app/settings/llm/index.tsx +2 -0
- package/src/config/modelProviders/index.ts +3 -0
- package/src/config/modelProviders/openrouter.ts +44 -0
- package/src/config/server/provider.ts +8 -0
- package/src/const/settings.ts +4 -0
- package/src/features/Conversation/Error/APIKeyForm/OpenRouter.tsx +40 -0
- package/src/features/Conversation/Error/APIKeyForm/index.tsx +5 -0
- package/src/features/Conversation/Error/index.tsx +1 -0
- package/src/libs/agent-runtime/error.ts +3 -0
- package/src/libs/agent-runtime/index.ts +1 -0
- package/src/libs/agent-runtime/openrouter/index.test.ts +347 -0
- package/src/libs/agent-runtime/openrouter/index.ts +86 -0
- package/src/libs/agent-runtime/types/type.ts +1 -0
- package/src/locales/default/common.ts +1 -0
- package/src/locales/default/error.ts +7 -0
- package/src/locales/default/setting.ts +16 -0
- package/src/services/_auth.test.ts +10 -0
- package/src/services/_auth.ts +4 -0
- package/src/store/global/slices/settings/selectors/modelProvider.ts +14 -0
- package/src/types/settings/modelProvider.ts +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.139.0",
|
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
LobeMoonshotAI,
|
|
17
17
|
LobeOllamaAI,
|
|
18
18
|
LobeOpenAI,
|
|
19
|
+
LobeOpenRouterAI,
|
|
19
20
|
LobePerplexityAI,
|
|
20
21
|
LobeZhipuAI,
|
|
21
22
|
ModelProvider,
|
|
@@ -42,6 +43,7 @@ vi.mock('@/config/server', () => ({
|
|
|
42
43
|
PERPLEXITY_API_KEY: 'test-perplexity-key',
|
|
43
44
|
ANTHROPIC_API_KEY: 'test-anthropic-key',
|
|
44
45
|
MISTRAL_API_KEY: 'test-mistral-key',
|
|
46
|
+
OPENROUTER_API_KEY: 'test-openrouter-key',
|
|
45
47
|
})),
|
|
46
48
|
}));
|
|
47
49
|
|
|
@@ -313,6 +315,30 @@ describe('AgentRuntime', () => {
|
|
|
313
315
|
});
|
|
314
316
|
});
|
|
315
317
|
|
|
318
|
+
describe('OpenRouter AI provider', () => {
|
|
319
|
+
it('should initialize correctly', async () => {
|
|
320
|
+
const jwtPayload: JWTPayload = { apiKey: 'user-openrouter-key' };
|
|
321
|
+
const runtime = await AgentRuntime.initializeWithUserPayload(
|
|
322
|
+
ModelProvider.OpenRouter,
|
|
323
|
+
jwtPayload,
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
// 假设 LobeOpenRouterAI 是 OpenRouter 提供者的实现类
|
|
327
|
+
expect(runtime['_runtime']).toBeInstanceOf(LobeOpenRouterAI);
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it('should initialize correctly without apiKey', async () => {
|
|
331
|
+
const jwtPayload: JWTPayload = {};
|
|
332
|
+
const runtime = await AgentRuntime.initializeWithUserPayload(
|
|
333
|
+
ModelProvider.OpenRouter,
|
|
334
|
+
jwtPayload,
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
// 假设 LobeOpenRouterAI 是 OpenRouter 提供者的实现类
|
|
338
|
+
expect(runtime['_runtime']).toBeInstanceOf(LobeOpenRouterAI);
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
|
|
316
342
|
it('should handle unknown provider gracefully', async () => {
|
|
317
343
|
const jwtPayload: JWTPayload = {};
|
|
318
344
|
const runtime = await AgentRuntime.initializeWithUserPayload('unknown', jwtPayload);
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
LobeMoonshotAI,
|
|
19
19
|
LobeOllamaAI,
|
|
20
20
|
LobeOpenAI,
|
|
21
|
+
LobeOpenRouterAI,
|
|
21
22
|
LobePerplexityAI,
|
|
22
23
|
LobeRuntimeAI,
|
|
23
24
|
LobeZhipuAI,
|
|
@@ -173,6 +174,11 @@ class AgentRuntime {
|
|
|
173
174
|
runtimeModel = this.initGroq(payload);
|
|
174
175
|
break;
|
|
175
176
|
}
|
|
177
|
+
|
|
178
|
+
case ModelProvider.OpenRouter: {
|
|
179
|
+
runtimeModel = this.initOpenRouter(payload);
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
176
182
|
}
|
|
177
183
|
|
|
178
184
|
return new AgentRuntime(runtimeModel);
|
|
@@ -281,6 +287,14 @@ class AgentRuntime {
|
|
|
281
287
|
|
|
282
288
|
return new LobeGroq({ apiKey });
|
|
283
289
|
}
|
|
290
|
+
|
|
291
|
+
private static initOpenRouter(payload: JWTPayload) {
|
|
292
|
+
const { OPENROUTER_API_KEY } = getServerConfig();
|
|
293
|
+
const apiKey = apiKeyManager.pick(payload?.apiKey || OPENROUTER_API_KEY);
|
|
294
|
+
|
|
295
|
+
return new LobeOpenRouterAI({ apiKey });
|
|
296
|
+
}
|
|
297
|
+
|
|
284
298
|
}
|
|
285
299
|
|
|
286
300
|
export default AgentRuntime;
|
|
@@ -22,6 +22,7 @@ export const GET = async () => {
|
|
|
22
22
|
ENABLED_PERPLEXITY,
|
|
23
23
|
ENABLED_ANTHROPIC,
|
|
24
24
|
ENABLED_MISTRAL,
|
|
25
|
+
ENABLED_OPENROUTER,
|
|
25
26
|
DEFAULT_AGENT_CONFIG,
|
|
26
27
|
OLLAMA_CUSTOM_MODELS,
|
|
27
28
|
} = getServerConfig();
|
|
@@ -41,6 +42,7 @@ export const GET = async () => {
|
|
|
41
42
|
mistral: { enabled: ENABLED_MISTRAL },
|
|
42
43
|
moonshot: { enabled: ENABLED_MOONSHOT },
|
|
43
44
|
ollama: { customModelName: OLLAMA_CUSTOM_MODELS, enabled: ENABLE_OLLAMA },
|
|
45
|
+
openrouter: { enabled: ENABLED_OPENROUTER },
|
|
44
46
|
perplexity: { enabled: ENABLED_PERPLEXITY },
|
|
45
47
|
zhipu: { enabled: ENABLED_ZHIPU },
|
|
46
48
|
},
|
|
@@ -86,6 +86,13 @@ describe('createErrorResponse', () => {
|
|
|
86
86
|
expect(response.status).toBe(476);
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
+
// 测试 OpenRouterBizError 错误类型返回477状态码
|
|
90
|
+
it('returns a 477 status for OpenRouterBizError error type', () => {
|
|
91
|
+
const errorType = AgentRuntimeErrorType.OpenRouterBizError;
|
|
92
|
+
const response = createErrorResponse(errorType);
|
|
93
|
+
expect(response.status).toBe(477);
|
|
94
|
+
});
|
|
95
|
+
|
|
89
96
|
// 测试 OllamaBizError 错误类型返回478状态码
|
|
90
97
|
it('returns a 478 status for OllamaBizError error type', () => {
|
|
91
98
|
const errorType = AgentRuntimeErrorType.OllamaBizError;
|
|
@@ -37,6 +37,9 @@ const getStatus = (errorType: ILobeAgentRuntimeErrorType | ErrorType) => {
|
|
|
37
37
|
case AgentRuntimeErrorType.MoonshotBizError: {
|
|
38
38
|
return 476;
|
|
39
39
|
}
|
|
40
|
+
case AgentRuntimeErrorType.OpenRouterBizError: {
|
|
41
|
+
return 477;
|
|
42
|
+
}
|
|
40
43
|
case ChatErrorType.OllamaServiceUnavailable:
|
|
41
44
|
case AgentRuntimeErrorType.OllamaBizError: {
|
|
42
45
|
return 478;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { OpenRouter } from '@lobehub/icons';
|
|
2
|
+
import { Input } from 'antd';
|
|
3
|
+
import { useTheme } from 'antd-style';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
|
|
7
|
+
import { ModelProvider } from '@/libs/agent-runtime';
|
|
8
|
+
|
|
9
|
+
import Checker from '../components/Checker';
|
|
10
|
+
import ProviderConfig from '../components/ProviderConfig';
|
|
11
|
+
import { LLMProviderApiTokenKey, LLMProviderConfigKey } from '../const';
|
|
12
|
+
|
|
13
|
+
const providerKey = 'openrouter';
|
|
14
|
+
|
|
15
|
+
const OpenRouterProvider = memo(() => {
|
|
16
|
+
const { t } = useTranslation('setting');
|
|
17
|
+
|
|
18
|
+
const theme = useTheme();
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<ProviderConfig
|
|
22
|
+
configItems={[
|
|
23
|
+
{
|
|
24
|
+
children: (
|
|
25
|
+
<Input.Password
|
|
26
|
+
autoComplete={'new-password'}
|
|
27
|
+
placeholder={t('llm.OpenRouter.token.placeholder')}
|
|
28
|
+
/>
|
|
29
|
+
),
|
|
30
|
+
desc: t('llm.OpenRouter.token.desc'),
|
|
31
|
+
label: t('llm.OpenRouter.token.title'),
|
|
32
|
+
name: [LLMProviderConfigKey, providerKey, LLMProviderApiTokenKey],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
children: (
|
|
36
|
+
<Input.TextArea
|
|
37
|
+
allowClear
|
|
38
|
+
placeholder={t('llm.OpenRouter.customModelName.placeholder')}
|
|
39
|
+
style={{ height: 100 }}
|
|
40
|
+
/>
|
|
41
|
+
),
|
|
42
|
+
desc: t('llm.OpenRouter.customModelName.desc'),
|
|
43
|
+
label: t('llm.OpenRouter.customModelName.title'),
|
|
44
|
+
name: [LLMProviderConfigKey, providerKey, 'customModelName'],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
children: <Checker model={'mistralai/mistral-7b-instruct:free'} provider={ModelProvider.OpenRouter} />,
|
|
48
|
+
desc: t('llm.checker.desc'),
|
|
49
|
+
label: t('llm.checker.title'),
|
|
50
|
+
minWidth: '100%',
|
|
51
|
+
},
|
|
52
|
+
]}
|
|
53
|
+
provider={providerKey}
|
|
54
|
+
title={
|
|
55
|
+
<OpenRouter.Combine
|
|
56
|
+
color={theme.isDarkMode ? theme.colorText : OpenRouter.colorPrimary}
|
|
57
|
+
size={24}
|
|
58
|
+
/>
|
|
59
|
+
}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export default OpenRouterProvider;
|
|
@@ -16,6 +16,7 @@ import Mistral from './Mistral';
|
|
|
16
16
|
import Moonshot from './Moonshot';
|
|
17
17
|
import Ollama from './Ollama';
|
|
18
18
|
import OpenAI from './OpenAI';
|
|
19
|
+
import OpenRouter from './OpenRouter';
|
|
19
20
|
import Perplexity from './Perplexity';
|
|
20
21
|
import Zhipu from './Zhipu';
|
|
21
22
|
|
|
@@ -34,6 +35,7 @@ export default memo<{ showOllama: boolean }>(({ showOllama }) => {
|
|
|
34
35
|
<Bedrock />
|
|
35
36
|
<Perplexity />
|
|
36
37
|
<Mistral />
|
|
38
|
+
<OpenRouter />
|
|
37
39
|
<Moonshot />
|
|
38
40
|
<Zhipu />
|
|
39
41
|
<Footer>
|
|
@@ -8,6 +8,7 @@ import MistralProvider from './mistral';
|
|
|
8
8
|
import MoonshotProvider from './moonshot';
|
|
9
9
|
import OllamaProvider from './ollama';
|
|
10
10
|
import OpenAIProvider from './openai';
|
|
11
|
+
import OpenRouterProvider from './openrouter';
|
|
11
12
|
import PerplexityProvider from './perplexity';
|
|
12
13
|
import ZhiPuProvider from './zhipu';
|
|
13
14
|
|
|
@@ -20,6 +21,7 @@ export const LOBE_DEFAULT_MODEL_LIST: ChatModelCard[] = [
|
|
|
20
21
|
MistralProvider.chatModels,
|
|
21
22
|
MoonshotProvider.chatModels,
|
|
22
23
|
OllamaProvider.chatModels,
|
|
24
|
+
OpenRouterProvider.chatModels,
|
|
23
25
|
PerplexityProvider.chatModels,
|
|
24
26
|
AnthropicProvider.chatModels,
|
|
25
27
|
].flat();
|
|
@@ -32,5 +34,6 @@ export { default as MistralProvider } from './mistral';
|
|
|
32
34
|
export { default as MoonshotProvider } from './moonshot';
|
|
33
35
|
export { default as OllamaProvider } from './ollama';
|
|
34
36
|
export { default as OpenAIProvider } from './openai';
|
|
37
|
+
export { default as OpenRouterProvider } from './openrouter';
|
|
35
38
|
export { default as PerplexityProvider } from './perplexity';
|
|
36
39
|
export { default as ZhiPuProvider } from './zhipu';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ModelProviderCard } from '@/types/llm';
|
|
2
|
+
|
|
3
|
+
const OpenRouter: ModelProviderCard = {
|
|
4
|
+
chatModels: [
|
|
5
|
+
{
|
|
6
|
+
displayName: 'Mistral 7B Instruct (free)',
|
|
7
|
+
functionCall: false,
|
|
8
|
+
id: 'mistralai/mistral-7b-instruct:free',
|
|
9
|
+
tokens: 32_768,
|
|
10
|
+
vision: false,
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
displayName: 'Google: Gemma 7B (free)',
|
|
14
|
+
functionCall: false,
|
|
15
|
+
id: 'google/gemma-7b-it:free',
|
|
16
|
+
tokens: 8192,
|
|
17
|
+
vision: false,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
displayName: 'OpenChat 3.5 (free)',
|
|
21
|
+
functionCall: false,
|
|
22
|
+
id: 'openchat/openchat-7b:free',
|
|
23
|
+
tokens: 8192,
|
|
24
|
+
vision: false,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
displayName: 'Nous: Capybara 7B (free)',
|
|
28
|
+
functionCall: false,
|
|
29
|
+
id: 'nousresearch/nous-capybara-7b:free',
|
|
30
|
+
tokens: 4096,
|
|
31
|
+
vision: false,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
displayName: 'Hugging Face: Zephyr 7B (free)',
|
|
35
|
+
functionCall: false,
|
|
36
|
+
id: 'huggingfaceh4/zephyr-7b-beta:free',
|
|
37
|
+
tokens: 4096,
|
|
38
|
+
vision: false,
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
id: 'openrouter',
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default OpenRouter;
|
|
@@ -42,6 +42,9 @@ declare global {
|
|
|
42
42
|
|
|
43
43
|
// Groq Provider
|
|
44
44
|
GROQ_API_KEY?: string;
|
|
45
|
+
|
|
46
|
+
// OpenRouter Provider
|
|
47
|
+
OPENROUTER_API_KEY?: string;
|
|
45
48
|
|
|
46
49
|
// AWS Credentials
|
|
47
50
|
AWS_REGION?: string;
|
|
@@ -74,6 +77,8 @@ export const getProviderConfig = () => {
|
|
|
74
77
|
const MISTRAL_API_KEY = process.env.MISTRAL_API_KEY || '';
|
|
75
78
|
|
|
76
79
|
const GROQ_API_KEY = process.env.GROQ_API_KEY || '';
|
|
80
|
+
|
|
81
|
+
const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY || '';
|
|
77
82
|
|
|
78
83
|
// region format: iad1,sfo1
|
|
79
84
|
let regions: string[] = [];
|
|
@@ -106,6 +111,9 @@ export const getProviderConfig = () => {
|
|
|
106
111
|
ENABLED_MISTRAL: !!MISTRAL_API_KEY,
|
|
107
112
|
MISTRAL_API_KEY,
|
|
108
113
|
|
|
114
|
+
ENABLED_OPENROUTER: !!OPENROUTER_API_KEY,
|
|
115
|
+
OPENROUTER_API_KEY,
|
|
116
|
+
|
|
109
117
|
ENABLED_MOONSHOT: !!MOONSHOT_API_KEY,
|
|
110
118
|
MOONSHOT_API_KEY,
|
|
111
119
|
MOONSHOT_PROXY_URL: process.env.MOONSHOT_PROXY_URL,
|
package/src/const/settings.ts
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { OpenRouter } from '@lobehub/icons';
|
|
2
|
+
import { Input } from 'antd';
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
|
|
6
|
+
import { ModelProvider } from '@/libs/agent-runtime';
|
|
7
|
+
import { useGlobalStore } from '@/store/global';
|
|
8
|
+
import { modelProviderSelectors } from '@/store/global/selectors';
|
|
9
|
+
|
|
10
|
+
import { FormAction } from '../style';
|
|
11
|
+
|
|
12
|
+
const OpenRouterForm = memo(() => {
|
|
13
|
+
const { t } = useTranslation('error');
|
|
14
|
+
// const [showProxy, setShow] = useState(false);
|
|
15
|
+
|
|
16
|
+
const [apiKey, setConfig] = useGlobalStore((s) => [
|
|
17
|
+
modelProviderSelectors.openrouterAPIKey(s),
|
|
18
|
+
s.setModelProviderConfig,
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<FormAction
|
|
23
|
+
avatar={<OpenRouter size={56} />}
|
|
24
|
+
description={t('unlock.apikey.OpenRouter.description')}
|
|
25
|
+
title={t('unlock.apikey.OpenRouter.title')}
|
|
26
|
+
>
|
|
27
|
+
<Input.Password
|
|
28
|
+
autoComplete={'new-password'}
|
|
29
|
+
onChange={(e) => {
|
|
30
|
+
setConfig(ModelProvider.OpenRouter, { apiKey: e.target.value });
|
|
31
|
+
}}
|
|
32
|
+
placeholder={'*********************************'}
|
|
33
|
+
type={'block'}
|
|
34
|
+
value={apiKey}
|
|
35
|
+
/>
|
|
36
|
+
</FormAction>
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export default OpenRouterForm;
|
|
@@ -13,6 +13,7 @@ import GroqForm from './Groq';
|
|
|
13
13
|
import MistralForm from './Mistral';
|
|
14
14
|
import MoonshotForm from './Moonshot';
|
|
15
15
|
import OpenAIForm from './OpenAI';
|
|
16
|
+
import OpenRouterForm from './OpenRouter';
|
|
16
17
|
import PerplexityForm from './Perplexity';
|
|
17
18
|
import ZhipuForm from './Zhipu';
|
|
18
19
|
|
|
@@ -59,6 +60,10 @@ const APIKeyForm = memo<APIKeyFormProps>(({ id, provider }) => {
|
|
|
59
60
|
case ModelProvider.Groq: {
|
|
60
61
|
return <GroqForm />;
|
|
61
62
|
}
|
|
63
|
+
|
|
64
|
+
case ModelProvider.OpenRouter: {
|
|
65
|
+
return <OpenRouterForm />;
|
|
66
|
+
}
|
|
62
67
|
|
|
63
68
|
default:
|
|
64
69
|
case ModelProvider.OpenAI: {
|
|
@@ -75,6 +75,7 @@ const ErrorMessageExtra = memo<{ data: ChatMessage }>(({ data }) => {
|
|
|
75
75
|
case AgentRuntimeErrorType.InvalidPerplexityAPIKey:
|
|
76
76
|
case AgentRuntimeErrorType.InvalidAnthropicAPIKey:
|
|
77
77
|
case AgentRuntimeErrorType.InvalidGroqAPIKey:
|
|
78
|
+
case AgentRuntimeErrorType.InvalidOpenRouterAPIKey:
|
|
78
79
|
case AgentRuntimeErrorType.NoOpenAIAPIKey: {
|
|
79
80
|
return <InvalidAPIKey id={data.id} provider={data.error?.body?.provider} />;
|
|
80
81
|
}
|
|
@@ -37,6 +37,9 @@ export const AgentRuntimeErrorType = {
|
|
|
37
37
|
|
|
38
38
|
InvalidGroqAPIKey: 'InvalidGroqAPIKey',
|
|
39
39
|
GroqBizError: 'GroqBizError',
|
|
40
|
+
|
|
41
|
+
InvalidOpenRouterAPIKey: 'InvalidOpenRouterAPIKey',
|
|
42
|
+
OpenRouterBizError: 'OpenRouterBizError',
|
|
40
43
|
} as const;
|
|
41
44
|
|
|
42
45
|
export type ILobeAgentRuntimeErrorType =
|
|
@@ -9,6 +9,7 @@ export { LobeMistralAI } from './mistral';
|
|
|
9
9
|
export { LobeMoonshotAI } from './moonshot';
|
|
10
10
|
export { LobeOllamaAI } from './ollama';
|
|
11
11
|
export { LobeOpenAI } from './openai';
|
|
12
|
+
export { LobeOpenRouterAI } from './openrouter';
|
|
12
13
|
export { LobePerplexityAI } from './perplexity';
|
|
13
14
|
export * from './types';
|
|
14
15
|
export { AgentRuntimeError } from './utils/createError';
|