@lobehub/chat 1.68.6 → 1.68.7

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/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 1.68.7](https://github.com/lobehub/lobe-chat/compare/v1.68.6...v1.68.7)
6
+
7
+ <sup>Released on **2025-03-05**</sup>
8
+
9
+ #### ♻ Code Refactoring
10
+
11
+ - **misc**: Refactor agent runtime to better code format.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Code refactoring
19
+
20
+ - **misc**: Refactor agent runtime to better code format, closes [#6284](https://github.com/lobehub/lobe-chat/issues/6284) ([fc1ed4a](https://github.com/lobehub/lobe-chat/commit/fc1ed4a))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 1.68.6](https://github.com/lobehub/lobe-chat/compare/v1.68.5...v1.68.6)
6
31
 
7
32
  <sup>Released on **2025-03-05**</sup>
package/changelog/v1.json CHANGED
@@ -1,4 +1,13 @@
1
1
  [
2
+ {
3
+ "children": {
4
+ "improvements": [
5
+ "Refactor agent runtime to better code format."
6
+ ]
7
+ },
8
+ "date": "2025-03-05",
9
+ "version": "1.68.7"
10
+ },
2
11
  {
3
12
  "children": {
4
13
  "fixes": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.68.6",
3
+ "version": "1.68.7",
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",
@@ -71,7 +71,7 @@ describe('POST handler', () => {
71
71
 
72
72
  // migrate to new AgentRuntime init api
73
73
  const spy = vi
74
- .spyOn(AgentRuntime, 'initializeWithProviderOptions')
74
+ .spyOn(AgentRuntime, 'initializeWithProvider')
75
75
  .mockResolvedValue(new AgentRuntime(mockRuntime));
76
76
 
77
77
  // 调用 POST 函数
@@ -117,7 +117,7 @@ describe('POST handler', () => {
117
117
 
118
118
  const mockRuntime: LobeRuntimeAI = { baseURL: 'abc', chat: vi.fn() };
119
119
 
120
- vi.spyOn(AgentRuntime, 'initializeWithProviderOptions').mockResolvedValue(
120
+ vi.spyOn(AgentRuntime, 'initializeWithProvider').mockResolvedValue(
121
121
  new AgentRuntime(mockRuntime),
122
122
  );
123
123
 
@@ -1,265 +1,96 @@
1
1
  // @vitest-environment node
2
2
  import { Langfuse } from 'langfuse';
3
3
  import { LangfuseGenerationClient, LangfuseTraceClient } from 'langfuse-core';
4
- import { ClientOptions } from 'openai';
5
4
  import { beforeEach, describe, expect, it, vi } from 'vitest';
6
5
 
7
6
  import * as langfuseCfg from '@/config/langfuse';
8
7
  import { JWTPayload } from '@/const/auth';
9
8
  import { TraceNameMap } from '@/const/trace';
10
- import {
11
- AgentRuntime,
12
- ChatStreamPayload,
13
- LobeAnthropicAI,
14
- LobeAzureOpenAI,
15
- LobeBedrockAI,
16
- LobeGoogleAI,
17
- LobeMistralAI,
18
- LobeMoonshotAI,
19
- LobeOllamaAI,
20
- LobeOpenAI,
21
- LobeOpenRouterAI,
22
- LobePerplexityAI,
23
- LobeRuntimeAI,
24
- LobeTogetherAI,
25
- LobeZhipuAI,
26
- ModelProvider,
27
- } from '@/libs/agent-runtime';
28
- import { LobeStepfunAI } from '@/libs/agent-runtime/stepfun';
9
+ import { AgentRuntime, ChatStreamPayload, LobeOpenAI, ModelProvider } from '@/libs/agent-runtime';
10
+ import { providerRuntimeMap } from '@/libs/agent-runtime/runtimeMap';
29
11
  import { createTraceOptions } from '@/server/modules/AgentRuntime';
30
12
 
31
13
  import { AgentChatOptions } from './AgentRuntime';
32
- import { LobeBedrockAIParams } from './bedrock';
33
-
34
- // 模拟依赖项
35
- vi.mock('@/config/server', () => ({
36
- getServerConfig: vi.fn(() => ({
37
- // 确保为每个provider提供必要的配置信息
38
- OPENAI_API_KEY: 'test-openai-key',
39
- GOOGLE_API_KEY: 'test-google-key',
40
-
41
- AZURE_API_KEY: 'test-azure-key',
42
- AZURE_ENDPOINT: 'endpoint',
43
-
44
- ZHIPU_API_KEY: 'test.zhipu-key',
45
- MOONSHOT_API_KEY: 'test-moonshot-key',
46
- AWS_SECRET_ACCESS_KEY: 'test-aws-secret',
47
- AWS_ACCESS_KEY_ID: 'test-aws-id',
48
- AWS_REGION: 'test-aws-region',
49
- OLLAMA_PROXY_URL: 'test-ollama-url',
50
- PERPLEXITY_API_KEY: 'test-perplexity-key',
51
- ANTHROPIC_API_KEY: 'test-anthropic-key',
52
- MISTRAL_API_KEY: 'test-mistral-key',
53
- OPENROUTER_API_KEY: 'test-openrouter-key',
54
- TOGETHERAI_API_KEY: 'test-togetherai-key',
55
- })),
56
- }));
57
14
 
58
- describe('AgentRuntime', () => {
59
- describe('should initialize with various providers', () => {
60
- describe('OpenAI provider', () => {
61
- it('should initialize correctly', async () => {
62
- const jwtPayload: ClientOptions = { apiKey: 'user-openai-key', baseURL: 'user-endpoint' };
63
-
64
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.OpenAI, {
65
- openai: jwtPayload,
66
- });
67
-
68
- expect(runtime).toBeInstanceOf(AgentRuntime);
69
- expect(runtime['_runtime']).toBeInstanceOf(LobeOpenAI);
70
- expect(runtime['_runtime'].baseURL).toBe('user-endpoint');
71
- });
72
- });
73
-
74
- describe('Azure OpenAI provider', () => {
75
- it('should initialize correctly', async () => {
76
- const jwtPayload = {
77
- apiKey: 'user-azure-key',
78
- baseURL: 'user-azure-endpoint',
79
- apiVersion: '2024-06-01',
80
- };
81
-
82
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Azure, {
83
- azure: jwtPayload,
84
- });
85
-
86
- expect(runtime).toBeInstanceOf(AgentRuntime);
87
- expect(runtime['_runtime']).toBeInstanceOf(LobeAzureOpenAI);
88
- expect(runtime['_runtime'].baseURL).toBe('user-azure-endpoint');
89
- });
90
- it('should initialize with azureOpenAIParams correctly', async () => {
91
- const jwtPayload = {
92
- apiKey: 'user-openai-key',
93
- baseURL: 'user-endpoint',
94
- apiVersion: 'custom-version',
95
- };
96
-
97
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Azure, {
98
- azure: jwtPayload,
99
- });
100
-
101
- expect(runtime).toBeInstanceOf(AgentRuntime);
102
- const openAIRuntime = runtime['_runtime'] as LobeRuntimeAI;
103
- expect(openAIRuntime).toBeInstanceOf(LobeAzureOpenAI);
104
- });
105
-
106
- it('should initialize with AzureAI correctly', async () => {
107
- const jwtPayload = {
108
- apiKey: 'user-azure-key',
109
- baseURL: 'user-azure-endpoint',
110
- apiVersion: '2024-06-01',
111
- };
112
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Azure, {
113
- azure: jwtPayload,
114
- });
115
-
116
- expect(runtime['_runtime']).toBeInstanceOf(LobeAzureOpenAI);
117
- });
118
- });
119
-
120
- describe('ZhiPu AI provider', () => {
121
- it('should initialize correctly', async () => {
122
- const jwtPayload: JWTPayload = { apiKey: 'zhipu.user-key' };
123
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.ZhiPu, {
124
- zhipu: jwtPayload,
125
- });
126
-
127
- // 假设 LobeZhipuAI 是 ZhiPu 提供者的实现类
128
- expect(runtime['_runtime']).toBeInstanceOf(LobeZhipuAI);
129
- });
130
- });
131
-
132
- describe('Google provider', () => {
133
- it('should initialize correctly', async () => {
134
- const jwtPayload: JWTPayload = { apiKey: 'user-google-key' };
135
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Google, {
136
- google: jwtPayload,
137
- });
138
-
139
- // 假设 LobeGoogleAI 是 Google 提供者的实现类
140
- expect(runtime['_runtime']).toBeInstanceOf(LobeGoogleAI);
141
- });
142
- });
143
-
144
- describe('Moonshot AI provider', () => {
145
- it('should initialize correctly', async () => {
146
- const jwtPayload: JWTPayload = { apiKey: 'user-moonshot-key' };
147
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Moonshot, {
148
- moonshot: jwtPayload,
149
- });
150
-
151
- // 假设 LobeMoonshotAI 是 Moonshot 提供者的实现类
152
- expect(runtime['_runtime']).toBeInstanceOf(LobeMoonshotAI);
153
- });
154
- });
155
-
156
- describe('Bedrock AI provider', () => {
157
- it('should initialize correctly with payload apiKey', async () => {
158
- const jwtPayload: LobeBedrockAIParams = {
159
- accessKeyId: 'user-aws-id',
160
- accessKeySecret: 'user-aws-secret',
161
- region: 'user-aws-region',
162
- };
163
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Bedrock, {
164
- bedrock: jwtPayload,
165
- });
166
-
167
- // 假设 LobeBedrockAI 是 Bedrock 提供者的实现类
168
- expect(runtime['_runtime']).toBeInstanceOf(LobeBedrockAI);
169
- });
170
- });
171
-
172
- describe('Ollama provider', () => {
173
- it('should initialize correctly', async () => {
174
- const jwtPayload: JWTPayload = { baseURL: 'https://user-ollama-url' };
175
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Ollama, {
176
- ollama: jwtPayload,
177
- });
178
-
179
- // 假设 LobeOllamaAI 是 Ollama 提供者的实现类
180
- expect(runtime['_runtime']).toBeInstanceOf(LobeOllamaAI);
181
- });
182
- });
183
-
184
- describe('Perplexity AI provider', () => {
185
- it('should initialize correctly', async () => {
186
- const jwtPayload: JWTPayload = { apiKey: 'user-perplexity-key' };
187
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Perplexity, {
188
- perplexity: jwtPayload,
189
- });
190
-
191
- // 假设 LobePerplexityAI 是 Perplexity 提供者的实现类
192
- expect(runtime['_runtime']).toBeInstanceOf(LobePerplexityAI);
193
- });
194
- });
195
-
196
- describe('Anthropic AI provider', () => {
197
- it('should initialize correctly', async () => {
198
- const jwtPayload: JWTPayload = { apiKey: 'user-anthropic-key' };
199
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Anthropic, {
200
- anthropic: jwtPayload,
201
- });
202
-
203
- // 假设 LobeAnthropicAI 是 Anthropic 提供者的实现类
204
- expect(runtime['_runtime']).toBeInstanceOf(LobeAnthropicAI);
205
- });
206
- });
207
-
208
- describe('Mistral AI provider', () => {
209
- it('should initialize correctly', async () => {
210
- const jwtPayload: JWTPayload = { apiKey: 'user-mistral-key' };
211
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Mistral, {
212
- mistral: jwtPayload,
213
- });
214
-
215
- // 假设 LobeMistralAI 是 Mistral 提供者的实现类
216
- expect(runtime['_runtime']).toBeInstanceOf(LobeMistralAI);
217
- });
15
+ const specialProviders = [
16
+ { id: 'openai', payload: { apiKey: 'user-openai-key', baseURL: 'user-endpoint' } },
17
+ {
18
+ id: ModelProvider.Azure,
19
+ payload: {
20
+ apiKey: 'user-azure-key',
21
+ baseURL: 'user-azure-endpoint',
22
+ apiVersion: '2024-06-01',
23
+ },
24
+ },
25
+ {
26
+ id: ModelProvider.AzureAI,
27
+ payload: {
28
+ apiKey: 'user-azure-key',
29
+ baseURL: 'user-azure-endpoint',
30
+ },
31
+ },
32
+ {
33
+ id: ModelProvider.Bedrock,
34
+ payload: {
35
+ accessKeyId: 'user-aws-id',
36
+ accessKeySecret: 'user-aws-secret',
37
+ region: 'user-aws-region',
38
+ },
39
+ },
40
+ {
41
+ id: ModelProvider.Ollama,
42
+ payload: { baseURL: 'https://user-ollama-url' },
43
+ },
44
+ {
45
+ id: ModelProvider.Cloudflare,
46
+ payload: { baseURLOrAccountID: 'https://user-ollama-url' },
47
+ },
48
+ ];
49
+
50
+ const testRuntime = (providerId: string, payload?: any) => {
51
+ describe(`${providerId} provider runtime`, () => {
52
+ it('should initialize correctly', async () => {
53
+ const jwtPayload: JWTPayload = { apiKey: 'user-key', ...payload };
54
+ const runtime = await AgentRuntime.initializeWithProvider(providerId, jwtPayload);
55
+
56
+ // @ts-ignore
57
+ expect(runtime['_runtime']).toBeInstanceOf(providerRuntimeMap[providerId]);
58
+
59
+ if (payload?.baseURL) {
60
+ expect(runtime['_runtime'].baseURL).toBe(payload.baseURL);
61
+ }
218
62
  });
63
+ });
64
+ };
65
+
66
+ let mockModelRuntime: AgentRuntime;
67
+ beforeEach(async () => {
68
+ const jwtPayload: JWTPayload = { apiKey: 'user-openai-key', baseURL: 'user-endpoint' };
69
+ mockModelRuntime = await AgentRuntime.initializeWithProvider(
70
+ ModelProvider.OpenAI,
71
+ jwtPayload,
72
+ );
73
+ });
219
74
 
220
- describe('OpenRouter AI provider', () => {
221
- it('should initialize correctly', async () => {
222
- const jwtPayload: JWTPayload = { apiKey: 'user-openrouter-key' };
223
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.OpenRouter, {
224
- openrouter: jwtPayload,
225
- });
75
+ describe('AgentRuntime', () => {
76
+ describe('should initialize with various providers', () => {
77
+ const providers = Object.values(ModelProvider);
226
78
 
227
- // 假设 LobeOpenRouterAI OpenRouter 提供者的实现类
228
- expect(runtime['_runtime']).toBeInstanceOf(LobeOpenRouterAI);
229
- });
230
- });
79
+ const specialProviderIds = [ModelProvider.VertexAI, ...specialProviders.map((p) => p.id)];
231
80
 
232
- describe('Stepfun AI provider', () => {
233
- it('should initialize correctly', async () => {
234
- const jwtPayload: JWTPayload = { apiKey: 'user-stepfun-key' };
235
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.Stepfun, {
236
- stepfun: jwtPayload,
237
- });
81
+ const generalTestProviders = providers.filter(
82
+ (provider) => !specialProviderIds.includes(provider),
83
+ );
238
84
 
239
- expect(runtime['_runtime']).toBeInstanceOf(LobeStepfunAI);
240
- });
85
+ generalTestProviders.forEach((provider) => {
86
+ testRuntime(provider);
241
87
  });
242
88
 
243
- describe('Together AI provider', () => {
244
- it('should initialize correctly', async () => {
245
- const jwtPayload: JWTPayload = { apiKey: 'user-togetherai-key' };
246
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.TogetherAI, {
247
- togetherai: jwtPayload,
248
- });
249
-
250
- // 假设 LobeTogetherAI 是 TogetherAI 提供者的实现类
251
- expect(runtime['_runtime']).toBeInstanceOf(LobeTogetherAI);
252
- });
253
- });
89
+ specialProviders.forEach(({ id, payload }) => testRuntime(id, payload));
254
90
  });
255
91
 
256
92
  describe('AgentRuntime chat method', () => {
257
93
  it('should run correctly', async () => {
258
- const jwtPayload: JWTPayload = { apiKey: 'user-openai-key', baseURL: 'user-endpoint' };
259
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.OpenAI, {
260
- openai: jwtPayload,
261
- });
262
-
263
94
  const payload: ChatStreamPayload = {
264
95
  messages: [{ role: 'user', content: 'Hello, world!' }],
265
96
  model: 'text-davinci-002',
@@ -268,14 +99,9 @@ describe('AgentRuntime', () => {
268
99
 
269
100
  vi.spyOn(LobeOpenAI.prototype, 'chat').mockResolvedValue(new Response(''));
270
101
 
271
- await runtime.chat(payload);
102
+ await mockModelRuntime.chat(payload);
272
103
  });
273
104
  it('should handle options correctly', async () => {
274
- const jwtPayload: JWTPayload = { apiKey: 'user-openai-key', baseURL: 'user-endpoint' };
275
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.OpenAI, {
276
- openai: jwtPayload,
277
- });
278
-
279
105
  const payload: ChatStreamPayload = {
280
106
  messages: [{ role: 'user', content: 'Hello, world!' }],
281
107
  model: 'text-davinci-002',
@@ -296,15 +122,10 @@ describe('AgentRuntime', () => {
296
122
 
297
123
  vi.spyOn(LobeOpenAI.prototype, 'chat').mockResolvedValue(new Response(''));
298
124
 
299
- await runtime.chat(payload, createTraceOptions(payload, options));
125
+ await mockModelRuntime.chat(payload, createTraceOptions(payload, options));
300
126
  });
301
127
 
302
128
  describe('callback', async () => {
303
- const jwtPayload: JWTPayload = { apiKey: 'user-openai-key', baseURL: 'user-endpoint' };
304
- const runtime = await AgentRuntime.initializeWithProviderOptions(ModelProvider.OpenAI, {
305
- openai: jwtPayload,
306
- });
307
-
308
129
  const payload: ChatStreamPayload = {
309
130
  messages: [{ role: 'user', content: 'Hello, world!' }],
310
131
  model: 'text-davinci-002',
@@ -345,7 +166,7 @@ describe('AgentRuntime', () => {
345
166
  );
346
167
  vi.spyOn(LangfuseTraceClient.prototype, 'update').mockImplementation(updateMock);
347
168
 
348
- await runtime.chat(payload, createTraceOptions(payload, options));
169
+ await mockModelRuntime.chat(payload, createTraceOptions(payload, options));
349
170
 
350
171
  expect(updateMock).toHaveBeenCalledWith({ tags: ['Tools Call'] });
351
172
  });
@@ -366,7 +187,7 @@ describe('AgentRuntime', () => {
366
187
  },
367
188
  );
368
189
 
369
- await runtime.chat(payload, createTraceOptions(payload, options));
190
+ await mockModelRuntime.chat(payload, createTraceOptions(payload, options));
370
191
 
371
192
  // Verify onStart was called
372
193
  expect(updateMock).toHaveBeenCalledWith({ completionStartTime: expect.any(Date) });
@@ -389,7 +210,7 @@ describe('AgentRuntime', () => {
389
210
  },
390
211
  );
391
212
 
392
- await runtime.chat(payload, createTraceOptions(payload, options));
213
+ await mockModelRuntime.chat(payload, createTraceOptions(payload, options));
393
214
 
394
215
  // Verify onCompletion was called with expected output
395
216
  expect(updateMock).toHaveBeenCalledWith({
@@ -419,7 +240,7 @@ describe('AgentRuntime', () => {
419
240
  const shutdownAsyncMock = vi.fn();
420
241
  vi.spyOn(Langfuse.prototype, 'shutdownAsync').mockImplementation(shutdownAsyncMock);
421
242
 
422
- await runtime.chat(payload, createTraceOptions(payload, options));
243
+ await mockModelRuntime.chat(payload, createTraceOptions(payload, options));
423
244
 
424
245
  // Verify onCompletion was called with expected output
425
246
  expect(shutdownAsyncMock).toHaveBeenCalled();
@@ -3,61 +3,18 @@ import { ClientOptions } from 'openai';
3
3
  import type { TracePayload } from '@/const/trace';
4
4
 
5
5
  import { LobeRuntimeAI } from './BaseAI';
6
- import { LobeAi21AI } from './ai21';
7
- import { LobeAi360AI } from './ai360';
8
- import { LobeAnthropicAI } from './anthropic';
9
- import { LobeAzureOpenAI } from './azureOpenai';
10
- import { LobeAzureAI } from './azureai';
11
- import { LobeBaichuanAI } from './baichuan';
12
- import { LobeBedrockAI, LobeBedrockAIParams } from './bedrock';
13
- import { LobeCloudflareAI, LobeCloudflareParams } from './cloudflare';
14
- import { LobeDeepSeekAI } from './deepseek';
15
- import { LobeFireworksAI } from './fireworksai';
16
- import { LobeGiteeAI } from './giteeai';
17
- import { LobeGithubAI } from './github';
18
- import { LobeGoogleAI } from './google';
19
- import { LobeGroq } from './groq';
20
- import { LobeHigressAI } from './higress';
21
- import { LobeHuggingFaceAI } from './huggingface';
22
- import { LobeHunyuanAI } from './hunyuan';
23
- import { LobeInternLMAI } from './internlm';
24
- import { LobeJinaAI } from './jina';
25
- import { LobeLMStudioAI } from './lmstudio';
26
- import { LobeMinimaxAI } from './minimax';
27
- import { LobeMistralAI } from './mistral';
28
- import { LobeMoonshotAI } from './moonshot';
29
- import { LobeNovitaAI } from './novita';
30
- import { LobeNvidiaAI } from './nvidia';
31
- import { LobeOllamaAI } from './ollama';
6
+ import { LobeBedrockAIParams } from './bedrock';
7
+ import { LobeCloudflareParams } from './cloudflare';
32
8
  import { LobeOpenAI } from './openai';
33
- import { LobeOpenRouterAI } from './openrouter';
34
- import { LobePerplexityAI } from './perplexity';
35
- import { LobePPIOAI } from './ppio';
36
- import { LobeQwenAI } from './qwen';
37
- import { LobeSambaNovaAI } from './sambanova';
38
- import { LobeSenseNovaAI } from './sensenova';
39
- import { LobeSiliconCloudAI } from './siliconcloud';
40
- import { LobeSparkAI } from './spark';
41
- import { LobeStepfunAI } from './stepfun';
42
- import { LobeTaichuAI } from './taichu';
43
- import { LobeTencentCloudAI } from './tencentcloud';
44
- import { LobeTogetherAI } from './togetherai';
9
+ import { providerRuntimeMap } from './runtimeMap';
45
10
  import {
46
11
  ChatCompetitionOptions,
47
12
  ChatStreamPayload,
48
13
  EmbeddingsOptions,
49
14
  EmbeddingsPayload,
50
- ModelProvider,
51
15
  TextToImagePayload,
52
16
  TextToSpeechPayload,
53
17
  } from './types';
54
- import { LobeUpstageAI } from './upstage';
55
- import { LobeVLLMAI } from './vllm';
56
- import { LobeVolcengineAI } from './volcengine';
57
- import { LobeWenxinAI } from './wenxin';
58
- import { LobeXAI } from './xai';
59
- import { LobeZeroOneAI } from './zeroone';
60
- import { LobeZhipuAI } from './zhipu';
61
18
 
62
19
  export interface AgentChatOptions {
63
20
  enableTrace?: boolean;
@@ -128,307 +85,25 @@ class AgentRuntime {
128
85
  * Try to initialize the runtime with the provider and the options.
129
86
  * @example
130
87
  * ```ts
131
- * const runtime = await AgentRuntime.initializeWithProviderOptions(provider, {
132
- * [provider]: {...options},
133
- * })
88
+ * const runtime = await AgentRuntime.initializeWithProviderOptions(provider, options)
134
89
  * ```
135
90
  * **Note**: If you try to get a AgentRuntime instance from client or server,
136
91
  * you should use the methods to get the runtime instance at first.
137
92
  * - `src/app/api/chat/agentRuntime.ts: initAgentRuntimeWithUserPayload` on server
138
93
  * - `src/services/chat.ts: initializeWithClientStore` on client
139
94
  */
140
- static async initializeWithProviderOptions(
95
+ static async initializeWithProvider(
141
96
  provider: string,
142
- params: Partial<{
143
- ai21: Partial<ClientOptions>;
144
- ai360: Partial<ClientOptions>;
145
- anthropic: Partial<ClientOptions>;
146
- azure: { apiKey?: string; apiVersion?: string; baseURL?: string };
147
- azureai: { apiKey?: string; apiVersion?: string; baseURL?: string };
148
- baichuan: Partial<ClientOptions>;
149
- bedrock: Partial<LobeBedrockAIParams>;
150
- cloudflare: Partial<LobeCloudflareParams>;
151
- deepseek: Partial<ClientOptions>;
152
- doubao: Partial<ClientOptions>;
153
- fireworksai: Partial<ClientOptions>;
154
- giteeai: Partial<ClientOptions>;
155
- github: Partial<ClientOptions>;
156
- google: { apiKey?: string; baseURL?: string };
157
- groq: Partial<ClientOptions>;
158
- higress: Partial<ClientOptions>;
159
- huggingface: { apiKey?: string; baseURL?: string };
160
- hunyuan: Partial<ClientOptions>;
161
- internlm: Partial<ClientOptions>;
162
- jina: Partial<ClientOptions>;
163
- lmstudio: Partial<ClientOptions>;
164
- minimax: Partial<ClientOptions>;
165
- mistral: Partial<ClientOptions>;
166
- moonshot: Partial<ClientOptions>;
167
- novita: Partial<ClientOptions>;
168
- nvidia: Partial<ClientOptions>;
169
- ollama: Partial<ClientOptions>;
170
- openai: Partial<ClientOptions>;
171
- openrouter: Partial<ClientOptions>;
172
- perplexity: Partial<ClientOptions>;
173
- ppio: Partial<ClientOptions>;
174
- qwen: Partial<ClientOptions>;
175
- sambanova: Partial<ClientOptions>;
176
- sensenova: Partial<ClientOptions>;
177
- siliconcloud: Partial<ClientOptions>;
178
- spark: Partial<ClientOptions>;
179
- stepfun: Partial<ClientOptions>;
180
- taichu: Partial<ClientOptions>;
181
- tencentcloud: Partial<ClientOptions>;
182
- togetherai: Partial<ClientOptions>;
183
- upstage: Partial<ClientOptions>;
184
- vllm: Partial<ClientOptions>;
185
- volcengine: Partial<ClientOptions>;
186
- wenxin: Partial<ClientOptions>;
187
- xai: Partial<ClientOptions>;
188
- zeroone: Partial<ClientOptions>;
189
- zhipu: Partial<ClientOptions>;
190
- }>,
97
+ params: Partial<
98
+ ClientOptions &
99
+ LobeBedrockAIParams &
100
+ LobeCloudflareParams & { apiKey?: string; apiVersion?: string; baseURL?: string }
101
+ >,
191
102
  ) {
192
- let runtimeModel: LobeRuntimeAI;
103
+ // @ts-expect-error runtime map not include vertex so it will be undefined
104
+ const providerAI = providerRuntimeMap[provider] ?? LobeOpenAI;
105
+ const runtimeModel: LobeRuntimeAI = new providerAI(params);
193
106
 
194
- switch (provider) {
195
- default:
196
- case ModelProvider.OpenAI: {
197
- // Will use the openai as default provider
198
- runtimeModel = new LobeOpenAI(params.openai ?? (params as any)[provider]);
199
- break;
200
- }
201
-
202
- case ModelProvider.Azure: {
203
- runtimeModel = new LobeAzureOpenAI(
204
- params.azure?.baseURL,
205
- params.azure?.apiKey,
206
- params.azure?.apiVersion,
207
- );
208
- break;
209
- }
210
-
211
- case ModelProvider.AzureAI: {
212
- runtimeModel = new LobeAzureAI(params.azureai);
213
- break;
214
- }
215
-
216
- case ModelProvider.ZhiPu: {
217
- runtimeModel = new LobeZhipuAI(params.zhipu);
218
- break;
219
- }
220
-
221
- case ModelProvider.Google: {
222
- runtimeModel = new LobeGoogleAI(params.google);
223
- break;
224
- }
225
-
226
- case ModelProvider.Moonshot: {
227
- runtimeModel = new LobeMoonshotAI(params.moonshot);
228
- break;
229
- }
230
-
231
- case ModelProvider.Bedrock: {
232
- runtimeModel = new LobeBedrockAI(params.bedrock);
233
- break;
234
- }
235
-
236
- case ModelProvider.LMStudio: {
237
- runtimeModel = new LobeLMStudioAI(params.lmstudio);
238
- break;
239
- }
240
-
241
- case ModelProvider.Ollama: {
242
- runtimeModel = new LobeOllamaAI(params.ollama);
243
- break;
244
- }
245
-
246
- case ModelProvider.VLLM: {
247
- runtimeModel = new LobeVLLMAI(params.vllm);
248
- break;
249
- }
250
-
251
- case ModelProvider.Perplexity: {
252
- runtimeModel = new LobePerplexityAI(params.perplexity);
253
- break;
254
- }
255
-
256
- case ModelProvider.Anthropic: {
257
- runtimeModel = new LobeAnthropicAI(params.anthropic);
258
- break;
259
- }
260
-
261
- case ModelProvider.DeepSeek: {
262
- runtimeModel = new LobeDeepSeekAI(params.deepseek);
263
- break;
264
- }
265
-
266
- case ModelProvider.HuggingFace: {
267
- runtimeModel = new LobeHuggingFaceAI(params.huggingface);
268
- break;
269
- }
270
-
271
- case ModelProvider.Minimax: {
272
- runtimeModel = new LobeMinimaxAI(params.minimax);
273
- break;
274
- }
275
-
276
- case ModelProvider.Mistral: {
277
- runtimeModel = new LobeMistralAI(params.mistral);
278
- break;
279
- }
280
-
281
- case ModelProvider.Groq: {
282
- runtimeModel = new LobeGroq(params.groq);
283
- break;
284
- }
285
-
286
- case ModelProvider.Github: {
287
- runtimeModel = new LobeGithubAI(params.github);
288
- break;
289
- }
290
-
291
- case ModelProvider.OpenRouter: {
292
- runtimeModel = new LobeOpenRouterAI(params.openrouter);
293
- break;
294
- }
295
-
296
- case ModelProvider.TogetherAI: {
297
- runtimeModel = new LobeTogetherAI(params.togetherai);
298
- break;
299
- }
300
-
301
- case ModelProvider.FireworksAI: {
302
- runtimeModel = new LobeFireworksAI(params.fireworksai);
303
- break;
304
- }
305
-
306
- case ModelProvider.ZeroOne: {
307
- runtimeModel = new LobeZeroOneAI(params.zeroone);
308
- break;
309
- }
310
-
311
- case ModelProvider.Qwen: {
312
- runtimeModel = new LobeQwenAI(params.qwen);
313
- break;
314
- }
315
-
316
- case ModelProvider.Stepfun: {
317
- runtimeModel = new LobeStepfunAI(params.stepfun);
318
- break;
319
- }
320
-
321
- case ModelProvider.Novita: {
322
- runtimeModel = new LobeNovitaAI(params.novita);
323
- break;
324
- }
325
-
326
- case ModelProvider.Nvidia: {
327
- runtimeModel = new LobeNvidiaAI(params.nvidia);
328
- break;
329
- }
330
-
331
- case ModelProvider.Baichuan: {
332
- runtimeModel = new LobeBaichuanAI(params.baichuan);
333
- break;
334
- }
335
-
336
- case ModelProvider.Taichu: {
337
- runtimeModel = new LobeTaichuAI(params.taichu);
338
- break;
339
- }
340
-
341
- case ModelProvider.Ai360: {
342
- runtimeModel = new LobeAi360AI(params.ai360);
343
- break;
344
- }
345
-
346
- case ModelProvider.SiliconCloud: {
347
- runtimeModel = new LobeSiliconCloudAI(params.siliconcloud);
348
- break;
349
- }
350
-
351
- case ModelProvider.GiteeAI: {
352
- runtimeModel = new LobeGiteeAI(params.giteeai);
353
- break;
354
- }
355
-
356
- case ModelProvider.Upstage: {
357
- runtimeModel = new LobeUpstageAI(params.upstage);
358
- break;
359
- }
360
-
361
- case ModelProvider.Spark: {
362
- runtimeModel = new LobeSparkAI(params.spark);
363
- break;
364
- }
365
-
366
- case ModelProvider.Ai21: {
367
- runtimeModel = new LobeAi21AI(params.ai21);
368
- break;
369
- }
370
-
371
- case ModelProvider.Hunyuan: {
372
- runtimeModel = new LobeHunyuanAI(params.hunyuan);
373
- break;
374
- }
375
-
376
- case ModelProvider.SenseNova: {
377
- runtimeModel = new LobeSenseNovaAI(params.sensenova);
378
- break;
379
- }
380
-
381
- case ModelProvider.XAI: {
382
- runtimeModel = new LobeXAI(params.xai);
383
- break;
384
- }
385
-
386
- case ModelProvider.Jina: {
387
- runtimeModel = new LobeJinaAI(params.jina);
388
- break;
389
- }
390
-
391
- case ModelProvider.SambaNova: {
392
- runtimeModel = new LobeSambaNovaAI(params.sambanova);
393
- break;
394
- }
395
-
396
- case ModelProvider.Cloudflare: {
397
- runtimeModel = new LobeCloudflareAI(params.cloudflare);
398
- break;
399
- }
400
-
401
- case ModelProvider.InternLM: {
402
- runtimeModel = new LobeInternLMAI(params.internlm);
403
- break;
404
- }
405
-
406
- case ModelProvider.Higress: {
407
- runtimeModel = new LobeHigressAI(params.higress);
408
- break;
409
- }
410
-
411
- case ModelProvider.TencentCloud: {
412
- runtimeModel = new LobeTencentCloudAI(params[provider]);
413
- break;
414
- }
415
-
416
- case ModelProvider.Volcengine:
417
- case ModelProvider.Doubao: {
418
- runtimeModel = new LobeVolcengineAI(params.volcengine || params.doubao);
419
- break;
420
- }
421
-
422
- case ModelProvider.Wenxin: {
423
- runtimeModel = new LobeWenxinAI(params.wenxin);
424
- break;
425
- }
426
-
427
- case ModelProvider.PPIO: {
428
- runtimeModel = new LobePPIOAI(params.ppio ?? {});
429
- break;
430
- }
431
- }
432
107
  return new AgentRuntime(runtimeModel);
433
108
  }
434
109
  }
@@ -16,11 +16,11 @@ describe('LobeAzureOpenAI', () => {
16
16
  let instance: LobeAzureOpenAI;
17
17
 
18
18
  beforeEach(() => {
19
- instance = new LobeAzureOpenAI(
20
- 'https://test.openai.azure.com/',
21
- 'test_key',
22
- '2023-03-15-preview',
23
- );
19
+ instance = new LobeAzureOpenAI({
20
+ baseURL: 'https://test.openai.azure.com/',
21
+ apiKey: 'test_key',
22
+ apiVersion: '2023-03-15-preview',
23
+ });
24
24
 
25
25
  // 使用 vi.spyOn 来模拟 streamChatCompletions 方法
26
26
  vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue(
@@ -42,14 +42,14 @@ describe('LobeAzureOpenAI', () => {
42
42
  });
43
43
 
44
44
  it('should create an instance of OpenAIClient with correct parameters', () => {
45
- const endpoint = 'https://test.openai.azure.com/';
46
- const apikey = 'test_key';
45
+ const baseURL = 'https://test.openai.azure.com/';
46
+ const apiKey = 'test_key';
47
47
  const apiVersion = '2023-03-15-preview';
48
48
 
49
- const instance = new LobeAzureOpenAI(endpoint, apikey, apiVersion);
49
+ const instance = new LobeAzureOpenAI({ baseURL, apiKey, apiVersion });
50
50
 
51
51
  expect(instance.client).toBeInstanceOf(AzureOpenAI);
52
- expect(instance.baseURL).toBe(endpoint);
52
+ expect(instance.baseURL).toBe(baseURL);
53
53
  });
54
54
  });
55
55
 
@@ -13,18 +13,18 @@ import { OpenAIStream } from '../utils/streams';
13
13
  export class LobeAzureOpenAI implements LobeRuntimeAI {
14
14
  client: AzureOpenAI;
15
15
 
16
- constructor(endpoint?: string, apikey?: string, apiVersion?: string) {
17
- if (!apikey || !endpoint)
16
+ constructor(params: { apiKey?: string; apiVersion?: string, baseURL?: string; } = {}) {
17
+ if (!params.apiKey || !params.baseURL)
18
18
  throw AgentRuntimeError.createError(AgentRuntimeErrorType.InvalidProviderAPIKey);
19
19
 
20
20
  this.client = new AzureOpenAI({
21
- apiKey: apikey,
22
- apiVersion,
21
+ apiKey: params.apiKey,
22
+ apiVersion: params.apiVersion,
23
23
  dangerouslyAllowBrowser: true,
24
- endpoint,
24
+ endpoint: params.baseURL,
25
25
  });
26
26
 
27
- this.baseURL = endpoint;
27
+ this.baseURL = params.baseURL;
28
28
  }
29
29
 
30
30
  baseURL: string;
@@ -0,0 +1,97 @@
1
+ import { LobeAi21AI } from './ai21';
2
+ import { LobeAi360AI } from './ai360';
3
+ import LobeAnthropicAI from './anthropic';
4
+ import { LobeAzureOpenAI } from './azureOpenai';
5
+ import { LobeAzureAI } from './azureai';
6
+ import { LobeBaichuanAI } from './baichuan';
7
+ import LobeBedrockAI from './bedrock';
8
+ import { LobeCloudflareAI } from './cloudflare';
9
+ import { LobeDeepSeekAI } from './deepseek';
10
+ import { LobeFireworksAI } from './fireworksai';
11
+ import { LobeGiteeAI } from './giteeai';
12
+ import { LobeGithubAI } from './github';
13
+ import LobeGoogleAI from './google';
14
+ import { LobeGroq } from './groq';
15
+ import { LobeHigressAI } from './higress';
16
+ import { LobeHuggingFaceAI } from './huggingface';
17
+ import { LobeHunyuanAI } from './hunyuan';
18
+ import { LobeInternLMAI } from './internlm';
19
+ import { LobeJinaAI } from './jina';
20
+ import { LobeLMStudioAI } from './lmstudio';
21
+ import { LobeMinimaxAI } from './minimax';
22
+ import { LobeMistralAI } from './mistral';
23
+ import { LobeMoonshotAI } from './moonshot';
24
+ import { LobeNovitaAI } from './novita';
25
+ import { LobeNvidiaAI } from './nvidia';
26
+ import LobeOllamaAI from './ollama';
27
+ import { LobeOpenAI } from './openai';
28
+ import { LobeOpenRouterAI } from './openrouter';
29
+ import { LobePerplexityAI } from './perplexity';
30
+ import { LobePPIOAI } from './ppio';
31
+ import { LobeQwenAI } from './qwen';
32
+ import { LobeSambaNovaAI } from './sambanova';
33
+ import { LobeSenseNovaAI } from './sensenova';
34
+ import { LobeSiliconCloudAI } from './siliconcloud';
35
+ import { LobeSparkAI } from './spark';
36
+ import { LobeStepfunAI } from './stepfun';
37
+ import { LobeTaichuAI } from './taichu';
38
+ import { LobeTencentCloudAI } from './tencentcloud';
39
+ import { LobeTogetherAI } from './togetherai';
40
+ import { ModelProvider } from './types';
41
+ import { LobeUpstageAI } from './upstage';
42
+ import { LobeVLLMAI } from './vllm';
43
+ import { LobeVolcengineAI } from './volcengine';
44
+ import { LobeWenxinAI } from './wenxin';
45
+ import { LobeXAI } from './xai';
46
+ import { LobeZeroOneAI } from './zeroone';
47
+ import { LobeZhipuAI } from './zhipu';
48
+
49
+ export const providerRuntimeMap = {
50
+ [ModelProvider.OpenAI]: LobeOpenAI,
51
+ [ModelProvider.Azure]: LobeAzureOpenAI,
52
+ [ModelProvider.AzureAI]: LobeAzureAI,
53
+ [ModelProvider.ZhiPu]: LobeZhipuAI,
54
+ [ModelProvider.Google]: LobeGoogleAI,
55
+ [ModelProvider.Moonshot]: LobeMoonshotAI,
56
+ [ModelProvider.Bedrock]: LobeBedrockAI,
57
+ [ModelProvider.LMStudio]: LobeLMStudioAI,
58
+ [ModelProvider.Ollama]: LobeOllamaAI,
59
+ [ModelProvider.VLLM]: LobeVLLMAI,
60
+ [ModelProvider.Perplexity]: LobePerplexityAI,
61
+ [ModelProvider.Anthropic]: LobeAnthropicAI,
62
+ [ModelProvider.DeepSeek]: LobeDeepSeekAI,
63
+ [ModelProvider.HuggingFace]: LobeHuggingFaceAI,
64
+ [ModelProvider.Minimax]: LobeMinimaxAI,
65
+ [ModelProvider.Mistral]: LobeMistralAI,
66
+ [ModelProvider.Groq]: LobeGroq,
67
+ [ModelProvider.Github]: LobeGithubAI,
68
+ [ModelProvider.OpenRouter]: LobeOpenRouterAI,
69
+ [ModelProvider.TogetherAI]: LobeTogetherAI,
70
+ [ModelProvider.FireworksAI]: LobeFireworksAI,
71
+ [ModelProvider.ZeroOne]: LobeZeroOneAI,
72
+ [ModelProvider.Stepfun]: LobeStepfunAI,
73
+ [ModelProvider.Qwen]: LobeQwenAI,
74
+ [ModelProvider.Novita]: LobeNovitaAI,
75
+ [ModelProvider.Nvidia]: LobeNvidiaAI,
76
+ [ModelProvider.Taichu]: LobeTaichuAI,
77
+ [ModelProvider.Baichuan]: LobeBaichuanAI,
78
+ [ModelProvider.Ai360]: LobeAi360AI,
79
+ [ModelProvider.SiliconCloud]: LobeSiliconCloudAI,
80
+ [ModelProvider.GiteeAI]: LobeGiteeAI,
81
+ [ModelProvider.Upstage]: LobeUpstageAI,
82
+ [ModelProvider.Spark]: LobeSparkAI,
83
+ [ModelProvider.Ai21]: LobeAi21AI,
84
+ [ModelProvider.Hunyuan]: LobeHunyuanAI,
85
+ [ModelProvider.SenseNova]: LobeSenseNovaAI,
86
+ [ModelProvider.XAI]: LobeXAI,
87
+ [ModelProvider.Jina]: LobeJinaAI,
88
+ [ModelProvider.SambaNova]: LobeSambaNovaAI,
89
+ [ModelProvider.Cloudflare]: LobeCloudflareAI,
90
+ [ModelProvider.InternLM]: LobeInternLMAI,
91
+ [ModelProvider.Higress]: LobeHigressAI,
92
+ [ModelProvider.TencentCloud]: LobeTencentCloudAI,
93
+ [ModelProvider.Volcengine]: LobeVolcengineAI,
94
+ [ModelProvider.PPIO]: LobePPIOAI,
95
+ [ModelProvider.Doubao]: LobeVolcengineAI,
96
+ [ModelProvider.Wenxin]: LobeWenxinAI,
97
+ };
@@ -1,6 +1,8 @@
1
1
  import { VertexAI, VertexInit } from '@google-cloud/vertexai';
2
2
 
3
- import { AgentRuntimeError, AgentRuntimeErrorType, LobeGoogleAI } from '@/libs/agent-runtime';
3
+ import { AgentRuntimeErrorType } from '../error';
4
+ import { LobeGoogleAI } from '../google';
5
+ import { AgentRuntimeError } from '../utils/createError';
4
6
 
5
7
  export class LobeVertexAI extends LobeGoogleAI {
6
8
  static initFromVertexAI(params?: VertexInit) {
@@ -130,8 +130,9 @@ export const initAgentRuntimeWithUserPayload = (
130
130
  payload: JWTPayload,
131
131
  params: any = {},
132
132
  ) => {
133
- return AgentRuntime.initializeWithProviderOptions(provider, {
134
- [provider]: { ...getLlmOptionsFromPayload(provider, payload), ...params },
133
+ return AgentRuntime.initializeWithProvider(provider, {
134
+ ...getLlmOptionsFromPayload(provider, payload),
135
+ ...params,
135
136
  });
136
137
  };
137
138
 
@@ -147,12 +147,10 @@ export function initializeWithClientStore(provider: string, payload: any) {
147
147
  * Configuration override order:
148
148
  * payload -> providerAuthPayload -> commonOptions
149
149
  */
150
- return AgentRuntime.initializeWithProviderOptions(provider, {
151
- [provider]: {
152
- ...commonOptions,
153
- ...providerAuthPayload,
154
- ...payload,
155
- },
150
+ return AgentRuntime.initializeWithProvider(provider, {
151
+ ...commonOptions,
152
+ ...providerAuthPayload,
153
+ ...payload,
156
154
  });
157
155
  }
158
156